﻿//IE瀏覽器不支援location.origin
$(function () {
    if (!window.location.origin) {
        window.location.origin = window.location.protocol + "//" + window.location.hostname + (window.location.port ? ':' + window.location.port : '');
    }
    //LocalStorage、SessionStorage
    (function ($) {
        var UserData = {
            userData: null,
            name: location.hostname,
            init: function () {
                if (!UserData.userData) {
                    try {
                        UserData.userData = document.createElement('INPUT');
                        UserData.userData.type = "hidden";
                        UserData.userData.style.display = "none";
                        UserData.userData.addBehavior("#default#userData");
                        document.body.appendChild(UserData.userData);
                        var expires = new Date();
                        expires.setDate(expires.getDate() + 30);
                        UserData.userData.expires = expires.toUTCString();
                    } catch (e) {
                        return false;
                    }
                }
                return true;
            },
            setItem: function (key, value) {
                if (UserData.init()) {
                    try {
                        UserData.userData.load(UserData.name);
                        UserData.userData.setAttribute(key, value);
                        UserData.userData.save(UserData.name);
                    } catch (e) {
                        return false;
                    }
                }
            },
            getItem: function (key) {
                if (UserData.init()) {
                    try {
                        UserData.userData.load(UserData.name);
                        return UserData.userData.getAttribute(key)
                    } catch (e) {
                        return '';
                    }
                }
            },
            remove: function (key) {
                if (UserData.init()) {
                    try {
                        UserData.userData.load(UserData.name);
                        UserData.userData.removeAttribute(key);
                        UserData.userData.save(UserData.name);
                    } catch (e) {
                        return false;
                    }
                }
            }
        };

        $.LionStorage = {
            setItem: function (key, value) {
                if (!window.localStorage) {
                    UserData.setItem(key, value);
                } else {
                    localStorage.setItem(key, value);
                    var dtDate = new Date();
                    var dtBeforeDate = new Date(dtDate.getFullYear(), dtDate.getMonth(), dtDate.getDate() + 30);
                    localStorage.setItem(key + "__timestamp", dtBeforeDate.getTime());
                }
            },
            getItem: function (key) {
                if (!window.localStorage) {
                    return UserData.getItem(key) || '';
                } else {
                    var expire = localStorage.getItem(key + "__timestamp");
                    if (expire && expire < new Date().getTime()) {
                        this.remove(key);
                        this.remove(key + "__timestamp");
                    }
                    return localStorage.getItem(key) || '';
                }
            },
            remove: function (key) {
                if (!window.localStorage) {
                    UserData.remove(key);
                } else {
                    localStorage.removeItem(key);
                    localStorage.removeItem(key + "__timestamp");
                }
            }
        };

        $.LionSessStorage = {
            setItem: function (key, value) {
                if (!window.sessionStorage) {
                    UserData.setItem(key, value);
                } else {
                    sessionStorage.setItem(key, value);
                }
            },
            getItem: function (key) {
                if (!window.sessionStorage) {
                    return UserData.getItem(key) || '';
                } else {
                    return sessionStorage.getItem(key) || '';
                }
            },
            remove: function (key) {
                if (!window.sessionStorage) {
                    UserData.remove(key);
                } else {
                    sessionStorage.removeItem(key);
                }
            }
        };
    })(window.jQuery);
});

//#region obj to query URL string
function serialize(obj, prefix) {
    var str = [];
    for (var p in obj) {
        if (obj.hasOwnProperty(p)) {
            var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
            str.push(typeof v == "object" ?
              serialize(v, k) :
              encodeURIComponent(k) + "=" + encodeURIComponent(v));
        }
    }
    return str.join("&");
}

function serializeNoEncode(obj, prefix) {
    var str = [];
    for (var p in obj) {
        if (obj.hasOwnProperty(p)) {
            var k = prefix ? prefix + "[" + p + "]" : p, v = obj[p];
            str.push(typeof v == "object" ?
              serializeNoEncode(v, k) :
              k + "=" + v);
        }
    }
    return str.join("&");
}
//#endregion

//#region 正則
var LionRegex = {
    dot: /,/gi,
    slash: /\//gi
};
//#endregion

function guid() {
    function s4() {
        return Math.floor((1 + Math.random()) * 0x10000)
          .toString(16)
          .substring(1);
    }

    var item = "";
    for (var i = 0 ; i < 8; i++) {
        item += s4();
    }
    return item;
}

if (!Array.prototype.filter) {
    Array.prototype.filter = function (fun) {
        if (this === void 0 || this === null) throw new TypeError();

        var t = Object(this);
        var len = t.length >>> 0;
        if (typeof fun !== 'function') throw new TypeError();

        var res = [];
        var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
        for (var i = 0; i < len; i++) {
            if (i in t) {
                var val = t[i];
                if (fun.call(thisArg, val, i, t)) res.push(val);
            }
        }

        return res;
    };
}

//JQuery Orderby (排序)
var firstBy = (function () {
    //github.com/Teun/thenBy.js
    function identity(v) { return v; }

    function ignoreCase(v) { return typeof (v) === "string" ? v.toLowerCase() : v; }

    function makeCompareFunction(f, opt) {
        opt = typeof (opt) === "number" ? { direction: opt } : opt || {};
        if (typeof (f) != "function") {
            var prop = f;
            f = function (v1) { return !!v1[prop] ? v1[prop] : ""; }
        }
        if (f.length === 1) {
            var uf = f;
            var preprocess = opt.ignoreCase ? ignoreCase : identity;
            f = function (v1, v2) { return preprocess(uf(v1)) < preprocess(uf(v2)) ? -1 : preprocess(uf(v1)) > preprocess(uf(v2)) ? 1 : 0; }
        }
        if (opt.direction === -1) return function (v1, v2) { return -f(v1, v2) };
        return f;
    }

    function tb(func, opt) {
        var x = typeof (this) === "function" ? this : false;
        var y = makeCompareFunction(func, opt);
        var f = x ? function (a, b) {
            return x(a, b) || y(a, b);
        }
                  : y;
        f.thenBy = tb;
        return f;
    }
    return tb;
})();

//取得網址參數物件資料
function getUrlData(URL) {
    var search = URL || location.search;
    if (search == "" | search == "?" | search == "?&") return {}
    //正規參數名稱轉小寫，值不變
    var regex = /[&|?][A-Za-z0-9_]+[=]/g;
    search = search.replace(regex, function (match) {
        return match.toLowerCase();
    }).substring(1);
    //URL字串轉陣列去除指定值
    var array = search.split("&")
    for (var i = 0; i < array.length; i++) {
        if (array[i] == "" | array[i] == undefined) {
            array.splice(i, 1);//返回指定的元素  
            i--;
        }
    }
    search = array.join("&")    
    return JSON.parse('{"' + decodeURI(search).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"') + '"}')
}

//取網址指定參數的值 name為指定參數名稱
function get(name) {
    name = (new RegExp('[?&]' + encodeURIComponent(name) + '=([^&]*)')).exec(location.search)
    return decodeURIComponent(name[1]);
}

//讀取Cookie
function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) == 0) return decodeURIComponent(c.substring(nameEQ.length, c.length));
    }
    return null;
}

//取得使用者瀏覽器
function detectBrowser() {
    var isIE = navigator.userAgent.search("MSIE") > -1;
    var isIE7 = navigator.userAgent.search("MSIE 7") > -1;
    var isFirefox = navigator.userAgent.search("Firefox") > -1;
    var isOpera = navigator.userAgent.search("Opera") > -1;
    var isSafari = navigator.userAgent.search("Safari") > -1;//Google瀏覽器是用這核心

    if (isIE7) {
        browser = 'IE7';
    }
    if (isIE) {
        browser = 'IE';
    }
    if (isFirefox) {
        browser = 'Firefox';
    }
    if (isOpera) {
        browser = 'Opera';
    }
    if (isSafari) {
        browser = 'Safari/Chrome';
    }
    return browser;
}

//取得數字轉中文數字
function NumberToChineseNum(num) {
    var ChineseNum = "零一二三四五六七八九";

    return ChineseNum.substring(num, num + 1);
}

//屬性undefined
var undefined;
function isUndefined(property) {
    return (typeof property == 'undefined');
}

// 補字PadRight
String.prototype.padRight = function (l, c) {
    return this + Array(l - this.length + 1).join(c || " ");
}

// 補字PadLeft
String.prototype.padLeft = function (l, c) {
    return Array(l - this.length + 1).join(c || " ") + this;
}

//----------------------↓DateExpFunction↓----------------------
/****************************************************************************************\
Date.DateAdd(interval, number)
說明 
	傳回內容為某個基準日期加上數個時間間隔單位後的日期。 

語法
	object.DateAdd(interval, number)
	參數		說明 
	interval	必要項。字串運算式，表示所要加上去之時間間隔單位。其值請參考設定部份。 
	number		必要項。數值運算式，表示要加上之時間間隔單位的次數。
				其數值可以為正數(可得未來日期)，亦可以為負數(可得過去的日期)。 

設定
	引數 interval 的設定值如下:
	設定	說明			設定	說明
	yyyy	西元年			w		一週的日數
	q		季 				ww		週        
	m		月 				h		時        
	y		一年的日數 		n		分        
	d		日 				s		秒        

註解
	您可以使用 DateAdd 函數計算基準日期加上或減去您所指定的時間間隔後的結果。
	例如，您可以用 DateAdd 來計算從今天起三十天後或三十天前的日期是那一天；
	或者計算距離現在 45 分鐘前或 45 分鐘後的時間。
	如果時間間隔是以 [天] 來計算，interval 引數可以是 [一年的日數] ("y")，[日] ("d")，或 [一週的日數] ("w")。
\****************************************************************************************/
if (isUndefined(Date.prototype.DateAdd) == true) {
    Date.prototype.DateAdd = function (interval, number) {
        var nd = new Date(this);
        switch (interval) {
            case 'y':
            case 'd':
            case 'w':
                nd.setDate(nd.getDate() + number);
                break;
            case 'yyyy':
                nd.setYear(nd.getFullYear() + number);
                break;
            case 'q':
                nd.setMonth(nd.getMonth() + number * 3);
                break;
            case 'm':
                nd.setMonth(nd.getMonth() + number);
                break;
            case 'ww':
                nd.setDate(nd.getDate() + number * 7);
                break;
            case 'h':
                nd.setHours(nd.getHours() + number);
                break;
            case 'n':
                nd.setMinutes(nd.getMinutes() + number);
                break;
            case 's':
                nd.setSeconds(nd.getSeconds() + number);
                break;
            default:
        }
        return nd;
    };
}

/****************************************************************************************\
Date.toFormatString(interval, isAddZeroChar, index, iLength)
說明 
	傳回格式化的日期字串。

語法
	object.toFormatString(interval, isAddZeroChar, index, iLength)
	參數			說明 
	interval		必要項。字串運算式，表示所要回傳的方式。其值請參考設定部份。
	isAddZeroChar	必要項。布林運算式，表示是否以雙位數字回傳；即只有個位數時，於十位數補零。
	index			非必要項。數值運算式，要回傳字串的起始索引值，由零開始；預設為0。
					當index小於零時，則由右邊起算傳回特定數量的字元。
	iLength			非必要項。數值運算式，要回傳字串的長度；預設為字串原長度。

設定
	引數 interval 的設定值如下:
	設定	說明											備註
	ed		yyyy/mm/dd										
    edlion		yyyymmdd										
	et24	hh:nn:ss										(24hr)
	et12	hh:nn:ss am/pm									(12hr)
	edt24	yyyy/mm/dd hh:nn:ss								(24hr)
	edt12	yyyy/mm/dd hh:nn:ss	am/pm						(12hr)
	cd		yyyy年mm月dd日
	ct24	hh時nn分ss秒									(24hr)
	ct12	上午/下午 hh時nn分ss秒							(12hr)
	ct12e	上午/下午 hh:nn:ss								(12hr)
	cdt24	yyyy年mm月dd日 hh時nn分ss秒						(24hr)
	cdt12	yyyy年mm月dd日 上午/下午 hh時nn分ss秒			(12hr)
	td		民國yyy年mm月dd日
	tdt24	民國yyy年mm月dd日 hh時nn分ss秒					(24hr)
	tdt12	民國yyy年mm月dd日 上午/下午 hh時nn分ss秒		(12hr)
	esd		mm/dd
	csd		mm月dd日
    edw     yyyy/mm/dd(W)
備註
	以日期時間Wed Mar-9-2005 14:6:43為例：
	當interval為ed、isAddZeroChar為true時，將回傳2005/03/09；
	當interval為ed、isAddZeroChar為false時，將回傳2005/3/9；
	當interval為cdt24、isAddZeroChar為false時，將回傳2005年3月9日 14時6分43秒。
\****************************************************************************************/
if (isUndefined(Date.prototype.toFormatString) == true) {
    Date.prototype.toFormatString = function (interval, isAddZeroChar, index, iLength) {
        var n = new Date(this);
        var s = '';
        var t = '';
        switch (interval) {
            case 'ed':
            case 'edw':
            case 'edt24':
            case 'edt12':
                s = n.getFullYear() + '/' +
					(isAddZeroChar ? (new String(n.getMonth() + 101).substr(1, 2)) : (n.getMonth() + 1)) + '/' +
					(isAddZeroChar ? (new String(n.getDate() + 100).substr(1, 2)) : (n.getDate()));
                break;
            case 'cd':
            case 'cdt24':
            case 'cdt12':
                s = n.getFullYear() + '年' +
					(isAddZeroChar ? (new String(n.getMonth() + 101).substr(1, 2)) : (n.getMonth() + 1)) + '月' +
					(isAddZeroChar ? (new String(n.getDate() + 100).substr(1, 2)) : (n.getDate())) + '日';
                break;
            case 'td':
            case 'tdt24':
            case 'tdt12':
                if (isAddZeroChar) {
                    s = '民國' + new String(n.getFullYear() - 911).substr(1, 3) + '年' +
						new String(n.getMonth() + 101).substr(1, 2) + '月' +
						new String(n.getDate() + 100).substr(1, 2) + '日';
                } else {
                    s = '民國' + (n.getFullYear() - 1911) + '年' + (n.getMonth() + 1) + '月' + n.getDate() + '日';
                }
                break;
            case 'esd':
                if (isAddZeroChar) {
                    s = new String(n.getMonth() + 101).substr(1, 2) + '/' + new String(n.getDate() + 100).substr(1, 2);
                } else {
                    s = (n.getMonth() + 1) + '/' + n.getDate();
                }
                break;
            case 'csd':
                if (isAddZeroChar) {
                    s = new String(n.getMonth() + 101).substr(1, 2) + '月' +
						new String(n.getDate() + 100).substr(1, 2) + '日';
                } else {
                    s = (n.getMonth() + 1) + '月' + n.getDate() + '日';
                }
                break;
            case 'edlion':
                s = n.getFullYear() +
					(isAddZeroChar ? (new String(n.getMonth() + 101).substr(1, 2)) : (n.getMonth() + 1)) +
					(isAddZeroChar ? (new String(n.getDate() + 100).substr(1, 2)) : (n.getDate()));
                break;
            default:
                break;
        }
        var hh = n.getHours();
        var h1 = (isAddZeroChar ? new String(hh + 100).substr(1, 2) : hh);
        var h2 = hh % 12;
        if (h2 == 0) {
            h2 = 12;
        } else {
            h2 = (isAddZeroChar ? new String(h2 + 100).substr(1, 2) : h2);
        }
        var nn = (isAddZeroChar ? new String(n.getMinutes() + 100).substr(1, 2) : n.getMinutes());
        var ss = (isAddZeroChar ? new String(n.getSeconds() + 100).substr(1, 2) : n.getSeconds());
        switch (interval) {
            case 'et24':
            case 'edt24':
                t = h1 + ':' + nn + ':' + ss;
                break;
            case 'et12':
            case 'edt12':
                t = h2 + ':' + nn + ':' + ss + ' ' + ((Math.floor(hh / 12) == 0) ? 'AM' : 'PM');
                break;
            case 'ct24':
            case 'cdt24':
            case 'tdt24':
                t = h1 + '時' + nn + '分' + ss + '秒';
                break;
            case 'ct12':
            case 'cdt12':
            case 'tdt12':
                t = ((Math.floor(hh / 12) == 0) ? '上午' : '下午') + ' ' + h2 + '時' + nn + '分' + ss + '秒';
                break;
            case 'ct12e':
                t = ((Math.floor(hh / 12) == 0) ? '上午' : '下午') + ' ' + h2 + ':' + nn + ':' + ss;
            default:
        }
        switch (interval) {
            case 'edt24':
            case 'cdt24':
            case 'tdt24':
            case 'edt12':
            case 'cdt12':
            case 'tdt12':
                s += ' ' + t;
                break;
            case 'ed':
            case 'edlion':
            case 'cd':
            case 'td':
            case 'esd':
            case 'csd':
                break;
            case 'edw':
                s += "(" + n.getWeekString() + ")";
                break;
            default:
                s = t;
        }
        if (typeof (index) == 'undefined') index = 0;
        if (index < 0) index = s.length + index;
        if (typeof (iLength) == 'undefined') iLength = s.length - index;
        if (iLength > s.length - index) iLength = s.length;
        return s.substr(index, iLength);
    };
}

/****************************************************************************************\
Date.toFormat(interval)
說明 
	傳回使用者定義日期/時間格式字串。

語法
	object.toFormat(interval)
	參數			說明 
	interval		必要項。字串運算式，表示所要回傳的方式。其值請參考設定部份。

設定
	yy		將年份顯示成兩位數的數值格式，並且加上前置零 (如果需要的話)。  
	yyy		將年份顯示成四位數的數值格式。 
	yyyy	將年份顯示成四位數的數值格式。 
	d		將日期顯示成數字，且不需要前置零 (例如，1)。如果這是使用者定義數值格式中的唯一字元，請使用 %d。 
	dd		將日期顯示成數字，並且加上前置零 (例如，01)。 
	ddd		用縮寫來顯示星期幾 (例如，Sun)。 
	dddd	用完整名稱來顯示星期幾 (例如，Sunday)。 
	m		將月份顯示成數字，且不需要前置零 (例如，以 1 表示一月)。如果這是使用者定義數值格式中的唯一字元，請使用 %m。 
	mm		將月份顯示成數字，並且加上前置零 (例如，01/12/01)。  
	mmm		用縮寫來顯示月份 (例如，Jan)。 
	mmmm	用完整名稱來顯示月份 (例如，January)。 
	h		使用 12 小時制將小時顯示成數字，且不需要前置零 (例如，1:15:15 PM)。如果這是使用者定義數值格式中的唯一字元，請使用 %h。 
	hh		使用 12 小時制將小時顯示成數字，並且加上前置零 (例如，01:15:15 PM)。 
	H		使用 24 小時制將小時顯示成數字，且不需要前置零 (例如：1:15:15)。如果這是使用者定義數值格式中的唯一字元，請使用 %H。 
	HH		使用 24 小時制將小時顯示成數字，並且加上前置零 (例如：01:15:15)。 
	n		將分鐘顯示成數字，且不需要前置零 (例如，12:1:15)。如果這是使用者定義數值格式中的唯一字元，請使用 %n。 
	nn		將分鐘顯示成數字，並且加上前置零 (例如，12:01:15)。 
	s		將秒數顯示成數字，且不需要前置零 (例如，12:15:5)。如果這是使用者定義數值格式中的唯一字元，請使用 %s。 
	ss		將秒數顯示成數字，並且加上前置零 (例如，12:15:05)。 
	T		使用 12 小時制，並且在正午之前的任何小時加上顯示大寫 A；在正午與 11:59 PM 之前的任何小時加上顯示大寫 P。如果這是使用者定義數值格式中的唯一字元，請使用 %T。 
	TT		使用 12 小時制，並且在正午之前的任何小時加上顯示大寫 AM；在正午與 11:59 PM 之前的任何小時加上顯示大寫 PM。 
	t		使用 12 小時制，並且在正午之前的任何小時加上顯示小寫 a；在正午與 11:59 PM 之前的任何小時加上顯示小寫 p。如果這是使用者定義數值格式中的唯一字元，請使用 %t。 
	tt		使用 12 小時制，並且在正午之前的任何小時加上顯示小寫 am；在正午與 11:59 PM 之前的任何小時加上顯示小寫 pm。 
	z		顯示時區時差，且不需要前置零 (例如，-8)。如果這是使用者定義數值格式中的唯一字元，請使用 %z。 
	zz		顯示時區時差，並且加上前置零 (例如，-08) 
	zzz		顯示完整時區時差 (例如，-08:00) 
\****************************************************************************************/
if (isUndefined(Date.prototype.toFormat) == true) {
    Date.prototype.toFormat = function (interval) {
        var s = interval;
        var n = new Date(this);
        if (s.indexOf('yyyy', 0) != -1) {
            s = s.replace(/yyyy/g, n.getFullYear());
        } else if (s.indexOf('yyy', 0) != -1) {
            s = s.replace(/yyy/g, n.getFullYear() - 1911);
        } else if (s.indexOf('yy', 0) != -1) {
            s = s.replace(/yy/g, new String(n.getFullYear()).substr(2, 2));
        }
        if (s.indexOf('mmmm', 0) != -1) {
            s = s.replace(/mmmm/g, n.getMonthString(false));
        } else if (s.indexOf('mmm', 0) != -1) {
            s = s.replace(/mmm/g, n.getMonthString(true));
        } else if (s.indexOf('mm', 0) != -1) {
            s = s.replace(/mm/g, new String(n.getMonth() + 101).substr(1, 2));
        } else if (s.indexOf('%m', 0) != -1) {
            return n.getMonth() + 1;
        } else if (s.indexOf('m', 0) != -1) {
            s = s.replace(/m/g, (n.getMonth() + 1));
        }
        if (s.indexOf('dddd', 0) != -1) {
            s = s.replace(/dddd/g, n.getWeekString(false));
        } else if (s.indexOf('ddd', 0) != -1) {
            s = s.replace(/ddd/g, n.getWeekString(true));
        } else if (s.indexOf('dd', 0) != -1) {
            s = s.replace(/dd/g, new String(n.getDate() + 100).substr(1, 2));
        } else if (s.indexOf('%d', 0) != -1) {
            return n.getDate();
        } else if (s.indexOf('d', 0) != -1) {
            s = s.replace(/d/g, n.getDate());
        }
        if (s.indexOf('hh', 0) != -1) {
            s = s.replace(/hh/g, ((n.getHours() % 12 == 0) ? '12' : new String(n.getHours() % 12 + 100).substr(1, 2)));
        } else if (s.indexOf('%h', 0) != -1) {
            return ((n.getHours() % 12 == 0) ? '12' : n.getHours() % 12);
        } else if (s.indexOf('h', 0) != -1) {
            s = s.replace(/h/g, ((n.getHours() % 12 == 0) ? '12' : n.getHours() % 12));
        } else if (s.indexOf('HH', 0) != -1) {
            s = s.replace(/HH/g, new String(n.getHours() + 100).substr(1, 2));
        } else if (s.indexOf('%H', 0) != -1) {
            return n.getHours();
        } else if (s.indexOf('H', 0) != -1) {
            s = s.replace(/H/g, n.getHours());
        }
        if (s.indexOf('nn', 0) != -1) {
            s = s.replace(/nn/g, new String(n.getMinutes() + 100).substr(1, 2));
        } else if (s.indexOf('%n', 0) != -1) {
            return n.getMinutes();
        } else if (s.indexOf('n', 0) != -1) {
            s = s.replace(/n/g, n.getMinutes());
        }
        if (s.indexOf('ss', 0) != -1) {
            s = s.replace(/ss/g, new String(n.getSeconds() + 100).substr(1, 2));
        } else if (s.indexOf('%s', 0) != -1) {
            return n.getSeconds();
        } else if (s.indexOf('s', 0) != -1) {
            s = s.replace(/s/g, n.getSeconds());
        }
        if (s.indexOf('TT', 0) != -1) {
            s = s.replace(/TT/g, ((n.getHours() < 12) ? 'AM' : 'PM'));
        } else if (s.indexOf('%T', 0) != -1) {
            return ((n.getHours() < 12) ? 'A' : 'P');
        } else if (s.indexOf('T', 0) != -1) {
            s = s.replace(/T/g, ((n.getHours() < 12) ? 'A' : 'P'));
        } else if (s.indexOf('tt', 0) != -1) {
            s = s.replace(/tt/g, ((n.getHours() < 12) ? 'am' : 'pm'));
        } else if (s.indexOf('%t', 0) != -1) {
            return ((n.getHours() < 12) ? 'a' : 'p');
        } else if (s.indexOf('t', 0) != -1) {
            s = s.replace(/t/g, ((n.getHours() < 12) ? 'a' : 'p'));
        }
        var u = '';
        if (n.getTime() > new Date(n.toUTCString()).getTime()) {
            u = '+';
            var utc = n.getTime() - new Date(n.toUTCString()).getTime();
        } else {
            u = '-';
            var utc = new Date(n.toUTCString()).getTime() - n.getTime();
        }
        if (s.indexOf('zzz', 0) != -1) {
            s = s.replace(/zzz/g, u + new String(utc.getHours() + 100).substr(1, 2) + ':' + new String(utc.getMinutes()).substr(1, 2));
        } else if (s.indexOf('zz', 0) != -1) {
            s = s.replace(/zz/g, u + new String(utc.getHours() + 100).substr(1, 2));
        } else if (s.indexOf('%z', 0) != -1) {
            return (u + utc.getHours());
        } else if (s.indexOf('z', 0) != -1) {
            s = s.replace(/z/g, u + utc.getHours());
        }
        return s;
    };
}

/****************************************************************************************\
Date.getMonthString(bShort)
說明 
	傳回月份字串。

語法
	object.getMonthString(bShort)
	參數			說明 
	bShort			必要項。布林運算式，表示回傳方式是否為簡稱格式。
\****************************************************************************************/
if (isUndefined(Date.prototype.getMonthString) == true) {
    Date.prototype.getMonthString = function (bShort) {
        var ms = new Array('January', 'February', 'March', 'April', 'May', 'June',
						   'July', 'August', 'September', 'October', 'November', 'December');
        if (bShort) {
            return ms[this.getMonth()].substr(0, 3);
        } else {
            return ms[this.getMonth()];
        }
    };
}

/****************************************************************************************\
Date.getWeekString(interval)
說明 
	傳回星期字串。

語法
	object.getWeekString(interval)
	參數			說明 
	interval			必要項。字串運算式，表示所要回傳的方式。其值請參考設定部份。
設定
	Short	英文縮寫格式。
    EN      英文原型格式。
    TW      中文格式(預設)。
\****************************************************************************************/
if (isUndefined(Date.prototype.getWeekString) == true) {
    Date.prototype.getWeekString = function (interval) {
        var ws = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
        var TWws = new Array('日', '一', '二', '三', '四', '五', '六');
        switch (interval)
        {
            case 'Short':
                return ws[this.getDay()].substr(0, 3);
            case 'EN':
                return ws[this.getDay()];
            case 'TW':
                return ws[this.getDay()];
            default:
                return TWws[this.getDay()];
        }
    };
}

/****************************************************************************************\
Date.getWeekNo()
說明 
	傳回週別。第一週索引值為零。

語法
	object.getWeekNo()
\****************************************************************************************/
if (isUndefined(Date.prototype.getWeekNo) == true) {
    Date.prototype.getWeekNo = function () {
        var n = new Date(this);
        var firstDay = new Date(n.getFullYear() + '/1/1');
        var iWeek = Math.ceil((n.getDayNo() - ((7 - firstDay.getDay()) % 7)) / 7);	// Week No. (First Index Is 0)
        return iWeek;
    };
}

/****************************************************************************************\
Date.getChtWeek()
說明 
	傳回中文星期字串。

語法
	object.getChtWeek()
\****************************************************************************************/
if (isUndefined(Date.prototype.getChtWeek) == true) {
    Date.prototype.getChtWeek = function () {
        var cws = new Array('星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六');
        return cws[this.getDay()];
    };
}

/****************************************************************************************\
Date.getDayMilliseconds()
說明 
	傳回一天的豪秒數。

語法
	object.getDayMilliseconds()
\****************************************************************************************/
if (isUndefined(Date.prototype.getDayMilliseconds) == true) {
    Date.prototype.getDayMilliseconds = function () {
        return 24 * 60 * 60 * 1000;
    };
}

/****************************************************************************************\
Date.getDayNo()
說明 
	傳回該年到當日的天數。一月一日為第一天。

語法
	object.getDayNo()
\****************************************************************************************/
if (isUndefined(Date.prototype.getDayNo) == true) {
    Date.prototype.getDayNo = function () {
        var n = new Date(this);
        var firstDay = new Date(n.getFullYear() + '/1/1');
        var iDay = Math.ceil((n.getTime() - firstDay.getTime()) / n.getDayMilliseconds()); // Day No.(First Index Is 1)
        return iDay;
    };
}

/****************************************************************************************\
Date.DateDiff(interval, dateValue)
說明 
	傳回本體(this)與傳入日期間相差的時間間隔單位數目。

語法
	object.DateDiff(interval, dateValue)
	DateDiff 函數語法中有下列幾部份：

	組成部分	說明  
	interval	必要項。字串運算式，用來計算本體及 dateValue 之時間差的時間間隔單位。請參閱設定部份。 
	dateValue	必要項。日期運算式。您要用來計算的日期。 

設定
	引數 interval 的設定值如下:
	設定	說明			設定	說明
	yyyy	西元年			w		一週的日數
	q		季 				ww		週        
	m		月 				h		時        
	y		一年的日數 		n		分        
	d		日 				s		秒        

註解
	您可以使用 DateDiff 函數來決定兩個日期之間的時間間隔單位數目。
	例如，您可以使用 DateDiff 來計算某兩個日期之間相隔幾日，或計算從今天起到年底還有多少個星期。

	如果想知道本體與 dateValue 相差的 [日] 數，interval 可以是 [一年的日數] ("y") 或 [日] ("d")。
	如果 interval 是 [一週的日數] ("w")，DateDiff 會傳回兩日期間相差的週數。
	如果本體是星期一，DateDiff 會計算到 dateValue 為止之星期一的個數，包含 dateValue 但不包含本體。
	不過，如果 interval 是 [週] ("ww")，DateDiff 函數會藉由計算本體與 dateValue 之間星期天的個數，會傳回兩日期間的 [日歷週] 數。
	如果 dateValue 剛好是星期天，則 dateValue 也會被加進計數結果中；但不論本體是否為星期天，它都不會被算進去。

	如果本體比 dateValue 來得晚，DateDiff 函數傳回值為負數。

	但若計算十二月三十一日和來年的一月一日的年份差，DateDiff 會傳回 1 表示相差一個年份，雖然實際上只相差一天而已。 

	以下範例即使用 DateDiff 函數來表示指定的日期與今天相差的天數： 

	alert('Days from today: ' + new Date('2005/01/01').DateDiff('d', new Date()));
\****************************************************************************************/
if (isUndefined(Date.prototype.DateDiff) == true) {
    Date.prototype.DateDiff = function (interval, dateValue) {
        var n = new Date(this);
        var d = new Date(dateValue);
        switch (interval) {
            case 'yyyy':
                return d.getFullYear() - n.getFullYear();
                break;
            case 'q':
                return Math.ceil((d.getMonth() + 1) / 3) - Math.ceil((n.getMonth() + 1) / 3);
                break;
            case 'm':
                return d.getMonth() - n.getMonth();
                break;
            case 'y':
            case 'd':
            case 'w':
                return Math.floor((d.getTime() - n.getTime()) / n.getDayMilliseconds());
                break;
            case 'ww':
                var fWeek = new Date(n.DateAdd('d', (7 - n.getDay()) % 7));
                return Math.floor(fWeek.DateDiff('d', dateValue) / 7);
                break;
            case 'h':
                return Math.floor((d.getTime() - n.getTime()) / (n.getDayMilliseconds() / 24));
                break;
            case 'n':
                return Math.floor((d.getTime() - n.getTime()) / (n.getDayMilliseconds() / 24 / 60));
                break;
            case 's':
                return Math.floor((d.getTime() - n.getTime()) / 1000);
                break;
            default:
                break;
        }
    };
}
//----------------------↑DateExpFunction↑----------------------

//可在Javascript中使用如同C#中的string.format
//使用方式 : var fullName = String.format('Hello. My name is {0} {1}.', 'FirstName', 'LastName');
String.format = function () {
    var s = arguments[0];
    if (s == null) return "";
    for (var i = 0; i < arguments.length - 1; i++) {
        var reg = getStringFormatPlaceHolderRegEx(i);
        s = s.replace(reg, (arguments[i + 1] == null ? "" : arguments[i + 1]));
    }
    return cleanStringFormatResult(s);
}
//可在Javascript中使用如同C#中的string.format (對jQuery String的擴充方法)
//使用方式 : var fullName = 'Hello. My name is {0} {1}.'.format('FirstName', 'LastName');
String.prototype.format = function () {
    var txt = this.toString();
    for (var i = 0; i < arguments.length; i++) {
        var exp = getStringFormatPlaceHolderRegEx(i);
        txt = txt.replace(exp, (arguments[i] == null ? "" : arguments[i]));
    }
    return cleanStringFormatResult(txt);
}
//讓輸入的字串可以包含{}
function getStringFormatPlaceHolderRegEx(placeHolderIndex) {
    return new RegExp('({)?\\{' + placeHolderIndex + '\\}(?!})', 'gm')
}
//當format格式有多餘的position時，就不會將多餘的position輸出
//ex:
// var fullName = 'Hello. My name is {0} {1} {2}.'.format('firstName', 'lastName');
// 輸出的 fullName 為 'firstName lastName', 而不會是 'firstName lastName {2}'
function cleanStringFormatResult(txt) {
    if (txt == null) return "";
    return txt.replace(getStringFormatPlaceHolderRegEx("\\d+"), "");
}