Feeds:
文章
迴響

Archive for 2009 年 09 月

這個編輯器其實不難,但是花了不少時間在切圖 😄

主要還是透過 Google Chart API 去繪出方程式

直接看 Demo

Read Full Post »

這週研發會議聽到同事介紹 Python+Diango,讓我在次想起 Python,一直聽說 Python 可用來開發 GUI 程式,現在終於擠出時間來瞭解一下,稍微搜尋一下你應該也會發現用來開發 GUI 的框架少說也有五種以上,常見的 gtk, wxPython, java swing, QT,我嘗試用 gtk 不過因為覺得 UI 有點醜所以改用 wxPython,外觀比較像一般 Windows 的 UI,學習門檻也不會太高,輕鬆就完成一個簡單的 Widows 程式。

我嘗試將之前用 .NET 寫得 Course Transfer 移植到 Python+wxPython,這是一個簡單的 csv 依據規則轉換成 XML 的程式,使用的 UI 也都是基本控制項 Button, Label, TextBox, ProgressBar, DirDialog 等,也嘗試透過 Thread 在背景進行運算前端顯示進度,出乎意料的簡單,沒什麼需要特別處理,不同於 .NET 還要透過特別寫法才能更新 UI

Python 移植版本沒有特別進行一些檢查(目錄、檔案),所以程式比較短,檔案清單

test.py — 主程式
compile.py — py2exe 用的腳本
+cwc
– ui.py – UI
– utils.py – 輔助
– fs.py – 檔案 i

以下是畫面截圖

image image image

image

移植過程料處理部份沒有什麼問題,算是相當的簡單容易,csv 的處理也有內建的模組可用,唯一比較麻煩的部份是手工建立 UI 的排版,我想應該會有 wxPython 的 UI 設計工具才對,不然打造複雜 UI 是一件頭痛的事情。

還有將 python 程式轉成可執行程式,我在 Vista+VS2008+Python2.6+wxPython 所產生的 exe 無法在 XP SP2+VS2008 的環境運行,但是可在 Windows7執行,問題原因還沒找到,等找到後再報告吧。另外我在使用 py2exe 時,都會出現找不到 msvcp90.dll,我只好手動複製到 Python26 安裝目錄的 DLL,不太確定這樣作是否正確。

不過這是一個相當有趣的體驗,下次嘗試移植到 Python+pyQt 試試看 ^^

下載

Read Full Post »

最後一個物件 Date 主要也是兩個擴展 format 和 parse

 
var cfg = {
name: “,
dateTimeFormat: {
"AMDesignator":"AM","Calendar":{"MinSupportedDateTime":"@-62135568000000@","MaxSupportedDateTime":"@253402300799999@","AlgorithmType":1,"CalendarType":1,"Eras":[1],"TwoDigitYearMax":2029,"IsReadOnly":true},
"DateSeparator":"/","FirstDayOfWeek":0,"CalendarWeekRule":0,"FullDateTimePattern":"dddd, dd MMMM yyyy HH:mm:ss","LongDatePattern":"dddd, dd MMMM yyyy","LongTimePattern":"HH:mm:ss","MonthDayPattern":"MMMM dd","PMDesignator":"PM","RFC1123Pattern":"ddd, dd MMM yyyy HH’:’mm’:’ss ‘GMT’","ShortDatePattern":"MM/dd/yyyy","ShortTimePattern":"HH:mm","SortableDateTimePattern":"yyyy’-‘MM’-‘dd’T’HH’:’mm’:’ss","TimeSeparator":":","UniversalSortableDateTimePattern":"yyyy’-‘MM’-‘dd HH’:’mm’:’ss’Z’","YearMonthPattern":"yyyy MMMM","AbbreviatedDayNames":["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],"ShortestDayNames":["Su","Mo","Tu","We","Th","Fr","Sa"],"DayNames":["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],"AbbreviatedMonthNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthNames":["January","February","March","April","May","June","July","August","September","October","November","December",""],"IsReadOnly":true,"NativeCalendarName":"Gregorian Calendar","AbbreviatedMonthGenitiveNames":["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",""],"MonthGenitiveNames":["January","February","March","April","May","June","July","August","September","October","November","December",""]
}
};

cfg.StringBuilder = function(){
var data = [];
this.append = function(v){
data.push(v);
}

this.toString = function(){
return data.join(“);
}
};
Date._appendPreOrPostMatch = function(e, b) {
    var d = 0,
    a = false;
    for (var c = 0,
    g = e.length; c < g; c++) {
        var f = e.charAt(c);
        switch (f) {
        case "’":
            if (a) b.append("’");
            else d++;
            a = false;
            break;
        case "\":
            if (a) b.append("\");
            a = !a;
            break;
        default:
            b.append(f);
            a = false;
            break
        }
    }
    return d
};
Date._expandFormat = function(a, b) {
    if (!b) b = "F";
    if (b.length === 1) switch (b) {
    case "d":
        return a.ShortDatePattern;
    case "D":
        return a.LongDatePattern;
    case "t":
        return a.ShortTimePattern;
    case "T":
        return a.LongTimePattern;
    case "F":
        return a.FullDateTimePattern;
    case "M":
    case "m":
        return a.MonthDayPattern;
    case "s":
        return a.SortableDateTimePattern;
    case "Y":
    case "y":
        return a.YearMonthPattern;
    default:
        throw new Error(‘bad format’);
    }
    return b
};
Date._expandYear = function(c, a) {
    if (a < 100) {
        var b = (new Date).getFullYear();
        a += b – b % 100;
        if (a > c.Calendar.TwoDigitYearMax) return a – 100
    }
    return a
};
Date._getParseRegExp = function(b, e) {
    if (!b._parseRegExp) b._parseRegExp = {};
    else if (b._parseRegExp[e]) return b._parseRegExp[e];
    var c = Date._expandFormat(b, e);
    c = c.replace(/([^$.*+?|[](){}])/g, "\\$1");
    var a = new cfg.StringBuilder("^"),
    j = [],
    f = 0,
    i = 0,
    h = Date._getTokenRegExp(),
    d;
    while ((d = h.exec(c)) !== null) {
        var l = c.slice(f, d.index);
        f = h.lastIndex;
        i += Date._appendPreOrPostMatch(l, a);
        if (i % 2 === 1) {
            a.append(d[0]);
            continue
        }
        switch (d[0]) {
        case "dddd":
        case "ddd":
        case "MMMM":
        case "MMM":
            a.append("(\D+)");
            break;
        case "tt":
        case "t":
            a.append("(\D*)");
            break;
        case "yyyy":
            a.append("(\d{4})");
            break;
        case "fff":
            a.append("(\d{3})");
            break;
        case "ff":
            a.append("(\d{2})");
            break;
        case "f":
            a.append("(\d)");
            break;
        case "dd":
        case "d":
        case "MM":
        case "M":
        case "yy":
        case "y":
        case "HH":
        case "H":
        case "hh":
        case "h":
        case "mm":
        case "m":
        case "ss":
        case "s":
            a.append("(\d\d?)");
            break;
        case "zzz":
            a.append("([+-]?\d\d?:\d{2})");
            break;
        case "zz":
        case "z":
            a.append("([+-]?\d\d?)");
            break
        }

j[j.length] = d[0];
    }
    Date._appendPreOrPostMatch(c.slice(f), a);
    a.append("$");
    var k = a.toString().replace(/s+/g, "\s+"),
    g = {
        "regExp": k,
        "groups": j
    };
    b._parseRegExp[e] = g;
    return g
};
Date._getTokenRegExp = function() {
    return /dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z/g
};

/**
*
*
* example
var d = new Date();
alert( Date.parse(‘2009/09/21 12:06:46’, ‘yyyy/MM/dd hh:mm:ss’) ); // Mon Sep 21 00:06:46 UTC+0800 2009

*/
Date.parse = function(a) {
    return Date._parse(a, cfg, arguments)
};

Date._parse = function(g, c, h) {
    var e = false;
    for (var a = 1,
    i = h.length; a < i; a++) {
        var f = h[a];
        if (f) {
            e = true;
            var b = Date._parseExact(g, f, c);
            if (b) return b
        }
    }
    if (!e) {
        var d = c._getDateTimeFormats();
        for (var a = 0,
        i = d.length; a < i; a++) {
            var b = Date._parseExact(g, d[a], c);
            if (b) return b
        }
    }
    return null
};
Date._parseExact = function(s, y, j) {
    s = s.replace(/^s+|s+$/g, "");
    var m = j.dateTimeFormat,
    v = Date._getParseRegExp(m, y),
    x = (new RegExp(v.regExp)).exec(s);
    if (x !== null) {
        var w = v.groups,
        f = null,
        c = null,
        h = null,
        g = null,
        d = 0,
        n = 0,
        o = 0,
        e = 0,
        k = null,
        r = false;
        for (var p = 0,
        z = w.length; p < z; p++) {
            var a = x[p + 1];
            if (a) switch (w[p]) {
            case "dd":
            case "d":
                h = Date._parseInt(a);
                if (h < 1 || h > 31) return null;
                break;
            case "MMMM":
                c = j._getMonthIndex(a);
                if (c < 0 || c > 11) return null;
                break;
            case "MMM":
                c = j._getAbbrMonthIndex(a);
                if (c < 0 || c > 11) return null;
                break;
            case "M":
            case "MM":
                var c = Date._parseInt(a) – 1;
                if (c < 0 || c > 11) return null;
                break;
            case "y":
            case "yy":
                f = Date._expandYear(m, Date._parseInt(a));
                if (f < 0 || f > 9999) return null;
                break;
            case "yyyy":
                f = Date._parseInt(a);
                if (f < 0 || f > 9999) return null;
                break;
            case "h":
            case "hh":
                d = Date._parseInt(a);
                if (d === 12) d = 0;
                if (d < 0 || d > 11) return null;
                break;
            case "H":
            case "HH":
                d = Date._parseInt(a);
                if (d < 0 || d > 23) return null;
                break;
            case "m":
            case "mm":
                n = Date._parseInt(a);
                if (n < 0 || n > 59) return null;
                break;
            case "s":
            case "ss":
                o = Date._parseInt(a);
                if (o < 0 || o > 59) return null;
                break;
            case "tt":
            case "t":
                var u = a.toUpperCase();
                r = u === m.PMDesignator.toUpperCase();
                if (!r && u !== m.AMDesignator.toUpperCase()) return null;
                break;
            case "f":
                e = Date._parseInt(a) * 100;
                if (e < 0 || e > 999) return null;
                break;
            case "ff":
                e = Date._parseInt(a) * 10;
                if (e < 0 || e > 999) return null;
                break;
            case "fff":
                e = Date._parseInt(a);
                if (e < 0 || e > 999) return null;
                break;
            case "dddd":
                g = j._getDayIndex(a);
                if (g < 0 || g > 6) return null;
                break;
            case "ddd":
                g = j._getAbbrDayIndex(a);
                if (g < 0 || g > 6) return null;
                break;
            case "zzz":
                var q = a.split(/:/);
                if (q.length !== 2) return null;
                var i = Date._parseInt(q[0]);
                if (i < -12 || i > 13) return null;
                var l = Date._parseInt(q[1]);
                if (l < 0 || l > 59) return null;
                k = i * 60 + (a.startsWith("-") ? -l: l);
                break;
            case "z":
            case "zz":
                var i = Date._parseInt(a);
                if (i < -12 || i > 13) return null;
                k = i * 60;
                break
            }
        }
        var b = new Date;
        if (f === null) f = b.getFullYear();
        if (c === null) c = b.getMonth();
        if (h === null) h = b.getDate();
        b.setFullYear(f, c, h);
        if (b.getDate() !== h) return null;
        if (g !== null && b.getDay() !== g) return null;
        if (r && d < 12) d += 12;
        b.setHours(d, n, o, e);
        if (k !== null) {
            var t = b.getMinutes() – (k + b.getTimezoneOffset());
            b.setHours(b.getHours() + parseInt(t / 60), t % 60)
        }
        return b
    }
};
Date._parseInt = function(a) {
    return parseInt(a.replace(/^[s0]+(d+)$/, "$1"))
};

/**
* 日期格式化
*
* example
var d = new Date();
alert(d.format(‘yyyy/MM/dd hh:mm:ss’)); //

* @return {String}
*/
Date.prototype.format = function(a) {
    return this._toFormattedString(a, cfg)
};

Date.prototype._toFormattedString = function(e, h) {
    if (!e || e.length === 0 || e === "i") if (h && h.name.length > 0) return this.toLocaleString();
    else return this.toString();
    var d = h.dateTimeFormat;
    e = Date._expandFormat(d, e);
    var a = new cfg.StringBuilder,
    b;
    function c(a) {
        if (a < 10) return "0" + a;
        return a.toString()
    }
    function g(a) {
        if (a < 10) return "00" + a;
        if (a < 100) return "0" + a;
        return a.toString()
    }
    var j = 0,
    i = Date._getTokenRegExp();
    for (; true;) {
        var l = i.lastIndex,
        f = i.exec(e),
        k = e.slice(l, f ? f.index: e.length);
        j += Date._appendPreOrPostMatch(k, a);
        if (!f) break;
        if (j % 2 === 1) {
            a.append(f[0]);
            continue
        }
        switch (f[0]) {
        case "dddd":
            a.append(d.DayNames[this.getDay()]);
            break;
        case "ddd":
            a.append(d.AbbreviatedDayNames[this.getDay()]);
            break;
        case "dd":
            a.append(c(this.getDate()));
            break;
        case "d":
            a.append(this.getDate());
            break;
        case "MMMM":
            a.append(d.MonthNames[this.getMonth()]);
            break;
        case "MMM":
            a.append(d.AbbreviatedMonthNames[this.getMonth()]);
            break;
        case "MM":
            a.append(c(this.getMonth() + 1));
            break;
        case "M":
            a.append(this.getMonth() + 1);
            break;
        case "yyyy":
            a.append(this.getFullYear());
            break;
        case "yy":
            a.append(c(this.getFullYear() % 100));
            break;
        case "y":
            a.append(this.getFullYear() % 100);
            break;
        case "hh":
            b = this.getHours() % 12;
            if (b === 0) b = 12;
            a.append(c(b));
            break;
        case "h":
            b = this.getHours() % 12;
            if (b === 0) b = 12;
            a.append(b);
            break;
        case "HH":
            a.append(c(this.getHours()));
            break;
        case "H":
            a.append(this.getHours());
            break;
        case "mm":
            a.append(c(this.getMinutes()));
            break;
        case "m":
            a.append(this.getMinutes());
            break;
        case "ss":
            a.append(c(this.getSeconds()));
            break;
        case "s":
            a.append(this.getSeconds());
            break;
        case "tt":
            a.append(this.getHours() < 12 ? d.AMDesignator: d.PMDesignator);
            break;
        case "t":
            a.append((this.getHours() < 12 ? d.AMDesignator: d.PMDesignator).charAt(0));
            break;
        case "f":
            a.append(g(this.getMilliseconds()).charAt(0));
            break;
        case "ff":
            a.append(g(this.getMilliseconds()).substr(0, 2));
            break;
        case "fff":
            a.append(g(this.getMilliseconds()));
            break;
        case "z":
            b = this.getTimezoneOffset() / 60;
            a.append((b >= 0 ? "+": "-") + Math.floor(Math.abs(b)));
            break;
        case "zz":
            b = this.getTimezoneOffset() / 60;
            a.append((b >= 0 ? "+": "-") + c(Math.floor(Math.abs(b))));
            break;
        case "zzz":
            b = this.getTimezoneOffset() / 60;
            a.append((b >= 0 ? "+": "-") + c(Math.floor(Math.abs(b))) + d.TimeSeparator + c(Math.abs(this.getTimezoneOffset() % 60)));
            break
        }
    }
    return a.toString()
};

Read Full Post »

主要就是解析與格式化兩個功能

/**
* 字串解析數值
*
* example:
alert(Number.parse("-1.234")*2);  // -2.468
alert(Number.parse("0xf"));  // 15
alert(Number.parse("1,234,567.89"));  // 1234567.89
alert(Number.parse("1,234,567.89E4"));  // 12345678900
* @param {String} g
* @return
*/

Number.parse = function(g) {
    var a = g.replace(/^s+|s+$/g, "");
    if (a.match(/infinity/i) !== null) return parseFloat(a);
    if (a.match(/^0x[a-f0-9]+$/i) !== null) return parseInt(a);

    var d = {
NumberDecimalSeparator: ‘.’,
NumberGroupSeparator: ","
};
    b = d.NumberDecimalSeparator,
    c = d.NumberGroupSeparator,
    e = new RegExp("^[+-]?[\d\" + c + "]*\" + b + "?\d*([eE][+-]?\d+)?$");
    if (!a.match(e)) return Number.NaN;
    a = a.split(c).join("");
    a = a.replace(b, ".");
    return parseFloat(a)
};

/**
* 數值格式化
*
* exmaple:
var x = 123456789;
alert( x.format("d") ); // 123456789
alert( x.format("n") ); // 123,456,789.00
alert( x.format("c") ); // $123,456,789.00
alert( x.format("p") ); // 123,456,789.00 %
*
* @param {String} 格式化參數
* @return {String}
*/

Number.prototype.format = function(a) {
    return this._toFormattedString(a, {
name: “,
numberFormat: {
"CurrencyDecimalDigits":2,
"CurrencyDecimalSeparator":".",
"IsReadOnly":true,
"CurrencyGroupSizes":[3],
"NumberGroupSizes":[3],
"PercentGroupSizes":[3],
"CurrencyGroupSeparator":",",
"CurrencySymbol": ‘$’,
"NaNSymbol":"NaN",
"CurrencyNegativePattern":0,
"NumberNegativePattern":1,
"PercentPositivePattern":0,
"PercentNegativePattern":0,
"NegativeInfinitySymbol":"-Infinity",
"NegativeSign":"-",
"NumberDecimalDigits":2,
"NumberDecimalSeparator":".",
"NumberGroupSeparator":",",
"CurrencyPositivePattern":0,
"PositiveInfinitySymbol":"Infinity",
"PositiveSign":"+",
"PercentDecimalDigits":2,
"PercentDecimalSeparator":".",
"PercentGroupSeparator":",",
"PercentSymbol":"%",
"PerMilleSymbol":"u2030",
"NativeDigits":["0","1","2","3","4","5","6","7","8","9"],
"DigitSubstitution":1
}
});
};

Number.prototype._toFormattedString = function(d, j) {
    if (!d || d.length === 0 || d === "i") if (j && j.name.length > 0) return this.toLocaleString();
    else return this.toString();
    var q = ["n %", "n%", "%n"],
    p = ["-n %", "-n%", "-%n"],
    r = ["(n)", "-n", "- n", "n-", "n -"],
    o = ["$n", "n$", "$ n", "n $"],
    n = ["($n)", "-$n", "$-n", "$n-", "(n$)", "-n$", "n-$", "n$-", "-n $", "-$ n", "n $-", "$ n-", "$ -n", "n- $", "($ n)", "(n $)"];

    function i(p, k, j, l, o) {
        var e = j[0],
        g = 1,
        c = p.toString(),
        a = "",
        m = "",
        i = c.split(".");
        if (i.length > 1) {
            c = i[0];
            a = i[1];
            var h = a.split(/e/i);
            if (h.length > 1) {
                a = h[0];
                m = "e" + h[1]
            }
        }
        if (k > 0) {
            var f = a.length – k;
            if (f > 0) a = a.slice(0, k);
            else if (f < 0) for (var n = 0; n < Math.abs(f); n++) a += "0";
            a = o + a
        } else a = "";
        a += m;
        var b = c.length – 1,
        d = "";
        while (b >= 0) {
            if (e === 0 || e > b) if (d.length > 0) return c.slice(0, b + 1) + l + d + a;
            else return c.slice(0, b + 1) + a;
            if (d.length > 0) d = c.slice(b – e + 1, b + 1) + l + d;
            else d = c.slice(b – e + 1, b + 1);
            b -= e;
            if (g < j.length) {
                e = j[g];
                g++
            }
        }
        return c.slice(0, b + 1) + l + d + a
    }
    var a = j.numberFormat,
    e = Math.abs(this);
    if (!d) d = "D";
    var b = -1;
    if (d.length > 1) b = parseInt(d.slice(1));
    var c;
    switch (d.charAt(0)) {
    case "d":
    case "D":
        c = "n";
        if (b !== -1) {
            var g = "" + e,
            k = b – g.length;
            if (k > 0) for (var m = 0; m < k; m++) g = "0" + g;
            e = g
        }
        if (this < 0) e = -e;
        break;
    case "c":
    case "C":
        if (this < 0) c = n[a.CurrencyNegativePattern];
        else c = o[a.CurrencyPositivePattern];
        if (b === -1) b = a.CurrencyDecimalDigits;
        e = i(Math.abs(this), b, a.CurrencyGroupSizes, a.CurrencyGroupSeparator, a.CurrencyDecimalSeparator);
        break;
    case "n":
    case "N":
        if (this < 0) c = r[a.NumberNegativePattern];
        else c = "n";
        if (b === -1) b = a.NumberDecimalDigits;
        e = i(Math.abs(this), b, a.NumberGroupSizes, a.NumberGroupSeparator, a.NumberDecimalSeparator);
        break;
    case "p":
    case "P":
        if (this < 0) c = p[a.PercentNegativePattern];
        else c = q[a.PercentPositivePattern];
        if (b === -1) b = a.PercentDecimalDigits;
        e = i(Math.abs(this), b, a.PercentGroupSizes, a.PercentGroupSeparator, a.PercentDecimalSeparator);
        break;
    default:
        throw new Error(‘bad format’);
    }
    var l = /n|$|-|%/g,
    f = "";
    for (; true;) {
        var s = l.lastIndex,
        h = l.exec(c);
        f += c.slice(s, h ? h.index: c.length);
        if (!h) break;
        switch (h[0]) {
        case "n":
            f += e;
            break;
        case "$":
            f += a.CurrencySymbol;
            break;
        case "-":
            f += a.NegativeSign;
            break;
        case "%":
            f += a.PercentSymbol;
            break
        }
    }
    return f
};

Read Full Post »

幾個好用的字串擴展,其中 String.format 真是超級好用,ExtJs 也有提供一個類似的函數
/** 
 * 檢查後面字串是否與指定字串匹配
 *
 * example:
	var a = 'Chui-Wen Chiu';
	alert( a.endsWith('Chiu') ); // true

 * @param {String} a 要匹配的字串
 * @return {Boolean}
 */
String.prototype.endsWith = function(a) {
    return this.substr(this.length - a.length) === a
};

/** 
 * 檢查開頭字串是否與指定字串匹配
 *
 * example:
	var a = 'Chui-Wen Chiu';
	alert( a.startsWith('Chui') ); // true

 * @param {String} a 要匹配的字串
 * @return {Boolean}
 */
String.prototype.startsWith = function(a) {
    return this.substr(0, a.length) === a
};


/**
 * trim:去除兩邊空格
 *
 * example:
	var x = ' abc ';
	alert( '-->' + x.trim() + '<--'); // -->abc<--
 *
 * Ver2
 this.replace(/(^[s]*)|([s]*$)/g, "")
 *
 * @return {String}
 */
String.prototype.trim = function() {
    return this.replace(/^s+|s+$/g, "")
};

/**
 * 去除右側空格
 *
 * example:
	var x = ' abc ';
	alert( '-->' + x.trimEnd() + '<--'); // --> abc<--
 *
 * Version
return this.replace(/([s]*$)/g, "");
 * @return {String}
 */
String.prototype.trimEnd = function() {
    return this.replace(/s+$/, "")
};

/**
 * 去除左側空格
 *
 * example:
	var x = ' abc ';
	alert( '-->' + x.trimStart() + '<--'); // -->abc <--
 *
 * 另一個版本
this.replace(/([s]*$)/g, "")

 * @return {String}
 */
String.prototype.trimStart = function() {
    return this.replace(/^s+/, "")
};

/**
 * 字串格式化
 *
 * example:
	alert( String.format("a={0}, b={1}, c={0}", 10, 100) ); // a=10, b=100, c=10

 * @param {Mixed}
 * @return {String}
 */
String.format = function() {
    return String._toFormattedString(false, arguments)
};

/**
 *
 *
 * @param {Boolean}	l
 * @param {Mixed}	j
 * @return {String}
 */
String._toFormattedString = function(l, j) {
    var c = "",
    e = j[0];
    for (var a = 0; true;) {
        var f = e.indexOf("{", a),
        d = e.indexOf("}", a);
        if (f < 0 && d < 0) {
            c += e.slice(a);
            break
        }
        if (d > 0 && (d < f || f < 0)) {
            c += e.slice(a, d + 1);
            a = d + 2;
            continue
        }
        c += e.slice(a, f);
        a = f + 1;
        if (e.charAt(a) === "{") {
            c += "{";
            a++;
            continue
        }
        if (d < 0) break;
        var h = e.substring(a, d),
        g = h.indexOf(":"),
        k = parseInt(g < 0 ? h: h.substring(0, g)) + 1,
        i = g < 0 ? "": h.substring(g + 1),
        b = j[k];
        if (typeof b === "undefined" || b === null) b = "";
        if (b.toFormattedString) c += b.toFormattedString(i);
        else if (l && b.localeFormat) c += b.localeFormat(i);
        else if (b.format) c += b.format(i);
        else c += b.toString();
        a = d + 1
    }
    return c
};

Read Full Post »

這次提煉出用於 Function 的三個擴展,雖然不多但是常用於 js 的基礎框架中,如下:

 

/**
 * 建立回呼(callback) 
 *
 * example:

function doCallback(num, callback){
	callback(num*100);
}

doCallback( 9, Function.createCallback( function(v, data ){
	if(v==data){
		alert('pass');
	}else{
		alert('fail');
	}
}, 900));

 * @param {Function} b
 * @param {Mixed} a 最後一個參數
 * @return {Function} 
 */
Function.createCallback = function(b, a) {
    return function() {
        var e = arguments.length;
        if (e > 0) {
            var d = [];
            for (var c = 0; c < e; c++) d[c] = arguments[c];
            d[e] = a;
            return b.apply(this, d)
        }
        return b.call(this, a)
    }
};

/**
 * 建立委託(delegate) 
 *
 * example:
var a = {
	name: 'Chui-Wen Chiu'
};

var delegate = Function.createDelegate(a, function(prefox, postfix){
	return prefix + this.name + postfix;
});

alert( delegate("-->", "<--") ); // -->Chui-Wen Chiu<--

 * @param {Object} a
 * @param {Function} b
 * @return {Function} 
 */
Function.createDelegate = function(a, b) {
    return function() {
        return b.apply(a, arguments)
    }
};

/** 
 * 空函數
 *
 * example:

var My = {
	changeEventHandler: Function.emptyMethod,
	v: 0,
	setValue: function(v){
		if(v!=this.v){
			this.changeEventHandler.call(this, v);
		}
	}
};

My.setValue(100); // nothing
My.changeEventHandler = function(v){
	alert(v);
};
My.setValue(100); // 
 */
Function.emptyFunction = Function.emptyMethod = function() {};

Read Full Post »

最近花了點時間瞭解 ASP.NET 提供的 Ajax 框架,使用過後發現真的非常簡單亦用,JS 寫的數量也極低,主要原因是框架提供了一個 MicrosoftAjax.js 腳本與 ASP.NET 緊密整合,呼叫 Server 端的方法就像呼叫 JS 一般函數的自然,如果你用過 PHP 的框架 xajax,其實兩者的實作差不多,都是透過 Server 產生封裝過 JS,所以用戶端才可以透過簡單的函數呼叫來取用 Server 端的功能。

除了上述的優勢之外,其實在 MicrosoftAjax.js 有一組實作擴展了 Javascript 的內建物件,我覺得在網頁開發上相當實用,接下來幾篇就是我提煉的結果,這篇主要是 Array 的擴展

// ——————- JS Code ——————-

/**
 *  將 b 元素附加到 a 陣列之後
 *
 * example:
var x = [1, 2, 3, 4, 5];
Array.add(x, 6); //[1,2,3,4,5,6]

 * @param {Array} a 
 * @param {Object} b
 */
Array.add = Array.enqueue = function(a, b) {
    a[a.length] = b
};

/**
 *  將陣列 b 全部元素附加到 a 陣列之後
 *
 * example:
	var x = [1,2,3];
	var y = [4,5];
	Array.addRange(x,y);
	alert(x,y); // x = [1,2,3,4,5]

 * @param {Array} a 
 * @param {Array} b
 */
Array.addRange = function(a, b) {
    a.push.apply(a, b)
};

/**
 * 清空陣列
 *
 * example:
	var x = [1,2,3];
	Array.clear(x);
	alert(x); // x = []

 * @param {Array} a 
 */
Array.clear = function(a) {
    a.length = 0
};

/**
 * 完整深層複製一份陣列
 *
 * example:
	var x = [1,2,3];
	var y = Array.clone(x);
	alert(y); // y = [1,2,3]

 * @param {Array} a 
 * @return {Array}
 */
Array.clone = function(a) {
    if (a.length === 1) return [a[0]];
    else return Array.apply(null, a)
};

/**
 * 找尋指定元素在陣列中的索引位置
 *
 * example:
	var x = ['a', 'b', 'c','d'];
	alert( Array.indexOf(x, 'b') ); // 1
	alert( Array.indexOf(x, 'b', -4) ); // 1
	alert( Array.indexOf(x, 'b', 0) ); // 1
	alert( Array.indexOf(x, 'b', 2) ); // -1
 * @param {Array} d
 * @param {Mixed} e 要尋找的元素
 * @param {int} a 起始索引, 非數值0從 0 開始,小於 0 從反向位置開始
 * @return {int} -1=沒有找到, 否則回傳批配的元素索引
 */
Array.indexOf = function(d, e, a) {
    if (typeof e === "undefined") return - 1;
    var c = d.length;
    if (c !== 0) {
        a = a - 0;
        if (isNaN(a)) a = 0;
        else {
            if (isFinite(a)) a = a - a % 1;
            if (a < 0) a = Math.max(0, c + a)
        }
        for (var b = a; b < c; b++) if (typeof d[b] !== "undefined" && d[b] === e) return b
    }
    return - 1
};

/**
 * 找尋指定元素是否在陣列中
 * {@link Array.indexOf}
 *
 * example:
	var x = ['a', 'b', 'c','d'];
	alert( Array.indexOf(x, 'b') ); // 1
	alert( Array.indexOf(x, 'b', -4) ); // 1
	alert( Array.indexOf(x, 'b', 0) ); // 1
	alert( Array.indexOf(x, 'b', 2) ); // -1
 * @param {Array} a
 * @param {Mixed} b 要尋找的元素
 * @return {Boolean} 
 */
Array.contains = function(a, b) {
    return Array.indexOf(a, b) >= 0
};

/**
 * 移除陣列第一個元素
 *
 * example:
	var x = ['a', 'b', 'c','d'];
	Array.dequeue(x); 
	alert(x); // x = ['b', 'c', 'd']

 * @param {Array} a
 * @return {Mixed} 被移除的元素
 */
Array.dequeue = function(a) {
    return a.shift()
};

/**
 * 移除陣列指定索引的元素
 *
 * example:
	var x = ['a', 'b', 'c','d'];
	Array.removeAt(x, 1); 
	alert(x); // x = ['a', 'c', 'd']

 * @param {Array} a
 * @param {int} b 陣列索引
 */
Array.removeAt = function(a, b) {
    a.splice(b, 1)
};

/**
 * 移除陣列中第一個符合指定條件的元素
 *
 * example:
	var x = ['a', 'b', 'c','d'];
	Array.remove(x, 'b'); 
	alert(x); // x = ['a', 'c', 'd']

 * @param {Array} b 陣列
 * @param {Mixed} c 要搜尋的元素
 * @param {Boolean} 
 */
Array.remove = function(b, c) {
    var a = Array.indexOf(b, c);
    if (a >= 0) b.splice(a, 1);
    return a >= 0
};

/**
 * 使用指定的函數迭代套用陣列的每個元素
 *
 * example:
	var x = ['a', 'b', 'c','d'];
	Array.forEach(x, function(elem, index, array_object){
		array_object[index] = '[' + elem  + ']';
	});
	alert(x); // x=['[a]', '[b]', '[c]', '[d]'];

	var y = ['a', 'b', 'c','d'];
	var My = {
		fix: function(elem, index, array_object){
			array_object[index] = '[' + elem  + ']';
		}
	};
	Array.forEach(y, My.fix, My);
	alert(y); // y=['[a]', '[b]', '[c]', '[d]'];
 * @param {Array} b
 * @param {Function} e 套用到陣列元素的方法
 * @param {Object} d 方法所屬的物件
 * @param {int} b 陣列索引
 */
Array.forEach = function(b, e, d) {
    for (var a = 0,
    f = b.length; a < f; a++) {
        var c = b[a];
        if (typeof c !== "undefined") e.call(d, c, a, b)
    }
};

/**
 * 在陣列指定的位置上插入元素
 *
 * example:
	var x = ['a', 'b', 'c'];
	Array.insert(x, 1, '**');
	alert(x); // x=['a', '**', 'b', 'c', 'd'];

 * @param {Array} a
 * @param {int} b 指定要插入的索引位置
 * @param {Mixed} c 插入的元素
 */
Array.insert = function(a, b, c) {
    a.splice(b, 0, c)
};

/**
 * 字串轉陣列
 *
 * example:
	alert(Array.parse('[1,2,3,4]')); // [1,2,3,4]

 * @param {String} value
 * @return {Mixed}
 */

Array.parse = function(value) {
    if (!value) return [];
    return eval(value)
};

Read Full Post »

Older Posts »