﻿// Mozilla 1.8 has support for indexOf, lastIndexOf, forEach, filter, map, some, every
// http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:lastIndexOf
if (!Array.prototype.indexOf) {
        Array.prototype.indexOf = function (obj, fromIndex) {
                if (fromIndex == null) {
                        fromIndex = 0;
                } else if (fromIndex < 0) {
                        fromIndex = Math.max(0, this.length + fromIndex);
                }
                for (var i = fromIndex; i < this.length; i++) {
                        if (this[i] === obj)
                                return i;
                }
                return -1;
        };
}

// http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:lastIndexOf
if (!Array.prototype.lastIndexOf) {
        Array.prototype.lastIndexOf = function (obj, fromIndex) {
                if (fromIndex == null) {
                        fromIndex = this.length - 1;
                } else if (fromIndex < 0) {
                        fromIndex = Math.max(0, this.length + fromIndex);
                }
                for (var i = fromIndex; i >= 0; i--) {
                        if (this[i] === obj)
                                return i;
                }
                return -1;
        };
}


// http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:forEach
if (!Array.prototype.forEach) {
        Array.prototype.forEach = function (f, obj) {
                var l = this.length;    // must be fixed during loop... see docs
                for (var i = 0; i < l; i++) {
                        f.call(obj, this[i], i, this);
                }
        };
}

// http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter
if (!Array.prototype.filter) {
        Array.prototype.filter = function (f, obj) {
                var l = this.length;    // must be fixed during loop... see docs
                var res = [];
                for (var i = 0; i < l; i++) {
                        if (f.call(obj, this[i], i, this)) {
                                res.push(this[i]);
                        }
                }
                return res;
        };
}

// http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:map
if (!Array.prototype.map) {
        Array.prototype.map = function (f, obj) {
                var l = this.length;    // must be fixed during loop... see docs
                var res = [];
                for (var i = 0; i < l; i++) {
                        res.push(f.call(obj, this[i], i, this));
                }
                return res;
        };
}

// http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:some
if (!Array.prototype.some) {
        Array.prototype.some = function (f, obj) {
                var l = this.length;    // must be fixed during loop... see docs
                for (var i = 0; i < l; i++) {
                        if (f.call(obj, this[i], i, this)) {
                                return true;
                        }
                }
                return false;
        };
}

// http://developer-test.mozilla.org/docs/Core_JavaScript_1.5_Reference:Objects:Array:every
if (!Array.prototype.every) {
        Array.prototype.every = function (f, obj) {
                var l = this.length;    // must be fixed during loop... see docs
                for (var i = 0; i < l; i++) {
                        if (!f.call(obj, this[i], i, this)) {
                                return false;
                        }
                }
                return true;
        };
}

Array.prototype.contains = function (obj) {
        return this.indexOf(obj) != -1;
};

Array.prototype.copy = function (obj) {
        return this.concat();
};

Array.prototype.insertAt = function (obj, i) {
        this.splice(i, 0, obj);
};

Array.prototype.insertBefore = function (obj, obj2) {
        var i = this.indexOf(obj2);
        if (i == -1)
                this.push(obj);
        else
                this.splice(i, 0, obj);
};

Array.prototype.removeAt = function (i) {
        this.splice(i, 1);
};

Array.prototype.remove = function (obj) {
        var i = this.indexOf(obj);
        if (i != -1)
                this.splice(i, 1);
};


/***************** String ******************/
if (!String.prototype.toQueryParams) {
        String.prototype.toQueryParams = function() {
                var hash = {};
                var params = this.split('&');
                var rd = /([^=]*)=(.*)/;
                for (var j = 0; j < params.length; j++) {
                        var match = rd.exec(params[j]);
                        if (!match) continue;
                        var key = decodeURIComponent(match[1]);
                        var value = match[2]?decodeURIComponent(match[2]) : undefined;
                        if (hash[key] !== undefined) {
                                if (hash[key].constructor != Array)
                                        hash[key] = [hash[key]];
                                if (value)
                                        hash[key].push(value);
                        } else {
                                hash[key] = value;
                        }
                }
                return hash;
        }
}

if (!String.prototype.trim) {
        String.prototype.trim = function(){
            var re = /^\s+|\s+$/g;
            return function(){ return this.replace(re, ""); };
        }();
}

if (!String.prototype.replaceAll) {
        String.prototype.replaceAll = function(from, to){
                return this.replace(new RegExp(from, 'gm'), to);
        }
}

/**
 * È¡Ëæ»úÕûÊý
 * @param {Object} n ×î´óÕûÊý
 */
Math.randomInt = function(n) {
        return Math.floor(Math.random() * (n + 1));    
}
/**
 * ³£ÓÃ±äÁ¿
 */

$D = YAHOO.util.Dom;
$E = YAHOO.util.Event;
$ = $D.get;

TB = YAHOO.namespace('TB');
TB.namespace = function() {
        var args = Array.prototype.slice.call(arguments, 0), i;
        for (i = 0; i < args.length; ++i) {
                if (args[i].indexOf('TB') != 0) {
                        args[i] = 'TB.' + args[i];
                }
        }
        return YAHOO.namespace.apply(null, args);
}

/********* Env *********/
TB.namespace('env');
TB.env = {
        hostname: 'taobao.com',
        debug: false,
        lang: 'zh-cn' /*(navigator.userLanguage?navigator.userLanguage.toLowerCase():navigator.language.toLowerCase())*/
};

/******** Locale ********/
TB.namespace('locale');
TB.locale = {
        Messages: {},
        getMessage: function(key) {
                return TB.locale.Messages[key] || key;
        },
        setMessage: function(key, value) {
                TB.locale.Messages[key] = value;
        }
}
$M = TB.locale.getMessage;


/******** Trace *********/
TB.trace = function(msg) {
        if (!TB.env.debug) return;
        if (window.console) {
                window.console.debug(msg);
        } else {
                alert(msg);
        }
}

/********* TB.init *********/
TB.init = function() {
        this.namespace('widget', 'dom', 'bom', 'util', 'form', 'anim');

        if (location.hostname.indexOf('taobao.com') == -1) {
                TB.env.hostname = location.hostname;
                TB.env.debug = true;
        }

        var scripts = document.getElementsByTagName("script");
        var scriptName = /tbra(?:[\w\.\-]*?)\.js(?:$|\?(.*))/;
        var matchs;
        for (var i = 0; i < scripts.length; ++i) {
                if(matchs = scriptName.exec(scripts[i].src)) {
                        TB.env['path'] = scripts[i].src.substring(0, matchs.index);
                        if (matchs[1]) {
                                var params = matchs[1].toQueryParams();
                                for (n in params) {
                                        if (n == 't' || n == 'timestamp') {
                                                TB.env['timestamp'] = parseInt(params[n]);
                                                continue;
                                        }
                                        TB.env[n] = params[n];
                                }                              
                        }
                }
        }
        YAHOO.util.Get.css(TB.env['path'] + 'assets/tbra.css' + (TB.env.timestamp?'?t='+TB.env.timestamp+'.css':''));  
}
TB.init();/**
 * TB Common function
 */
TB.common = {
        /**
         * ÒÆ³ýÎÄ×ÖÇ°ºóµÄ¿Õ°××Ö·û
         *
         * @method trim
         * @param {String} str
         * @deprecated Ê¹ÓÃString.prototpye.trim()À´Ìæ´ú
         */
        trim: function(str) {
                return str.replace(/(^\s*)|(\s*$)/g,'');
        },

        /**
         * ±àÂëHTML (from prototype framework 1.4)
         * @method escapeHTML
         * @param {Object} str
         */
        escapeHTML: function(str) {
                var div = document.createElement('div');
                var text = document.createTextNode(str);
                div.appendChild(text);
                return div.innerHTML;
        },

        /**
         * ½âÂëHTML (from prototype framework 1.4)
         * @method unescapeHTML
         * @param {Object} str
         */
        unescapeHTML: function(str) {
                var div = document.createElement('div');
                div.innerHTML = str.replace(/<\/?[^>]+>/gi, '');
                return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
        },
       
        /**
         * É¾³ý×Ö·û´®ÖÐµÄ(x)htmlÖÐµÄ±êÇ©ÐÅÏ¢
         * @method stripTags
         * @param {Object} str
         */
        stripTags: function(str) {
        return str.replace(/<\/?[^>]+>/gi, '');
        },

        /**
         * ×ª»» NodeList »òÕß arguments ÎªÊý×é
         * @method toArray
         * @param {Object} list
         * @param {Object} start
         * @return {Array} ×ª»»ºóµÄÊý×é£¬Èç¹ûstart´óÓÚlistµÄÈÝÁ¿£¬·µ»Ø¿ÕÊý×é
         */
        toArray : function(list, start) {
                var array = [];
                for (var i = start || 0; i < list.length; i++) {
                        array[array.length] = list[i];
                }
                return array;
        },

        /**
         * ¸´ÖÆÅäÖÃÊôÐÔ¸øÄ³¶ÔÏó£¬Èç¹û¶ÔÏóÒÑ´æÔÚ¸ÃÅäÖÃ£¬²»½øÐÐ¸²¸Ç
         * @param {Object} obj Ä¿±ê¶ÔÏó
         * @param {Object} config °üº¬ÊôÐÔ/²ÎÊý ¶ÔÏó
         */    
        applyIf: function(obj, config) {
        if(obj && config && typeof config == 'object'){
                for(var p in config) {
                                if (!YAHOO.lang.hasOwnProperty(obj, p))
                        obj[p] = config[p];
                        }
        }
        return obj;
        },

        /**
         * ¸´ÖÆÅäÖÃÊôÐÔ¸øÄ³¶ÔÏó£¬Èç¹û¶ÔÏóÒÑ´æÔÚ¸ÃÅäÖÃ£¬½«±»¸²¸ÇÎªÐÂÊôÐÔ
         * @param {Object} obj Ä¿±ê¶ÔÏó
         * @param {Object} config °üº¬ÊôÐÔ/²ÎÊý ¶ÔÏó
         */            
        apply: function(obj, config) {
        if(obj && config && typeof config == 'object'){
                for(var p in config)
                                obj[p] = config[p];
                }
                return obj;
        },
       
        /**
         * ¸ñÊ½»¯×Ö·û´®
         * eg:
         *      TB.common.formatMessage('{0}ÌìÓÐ{1}¸öÐ¡Ê±', [1, 24])
         *  or
         *  TB.common.formatMessage('{day}ÌìÓÐ{hour}¸öÐ¡Ê±', {day:1, hour:24}}
         * @param {Object} msg
         * @param {Object} values
         */
        formatMessage: function(msg, values, filter) {
                var pattern = /\{([\w-]+)?\}/g;
                return function(msg, values, filter) {
                        return msg.replace(pattern, function(match, key) {
                                return filter?filter(values[key], key):values[key];
                        });    
                }
        }(),
       
        /**
         * ½âÎöURI
         */
        parseUri: (function() {
                var keys = ['source', 'prePath', 'scheme', 'username', 'password', 'host', 'port', 'path', 'dir', 'file', 'query', 'fragment'];
                var re = /^((?:([^:\/?#.]+):)?(?:\/\/)?(?:([^:@]*):?([^:@]*)?@)?([^:\/?#]*)(?::(\d*))?)((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?/;        
                return function(sourceUri) {
                        var uri = {};
                        var uriParts = re.exec(sourceUri);
                        for(var i = 0; i < uriParts.length; ++i){
                                uri[keys[i]] = (uriParts[i] ? uriParts[i] : '');
                        }
                        return uri;
                }
        })()
};

TB.applyIf = TB.common.applyIf;
TB.apply = TB.common.apply;TB.locale.Messages={loading:"\u52a0\u8f7d\u4e2d...",pleaseWait:"\u6b63\u5728\u5904\u7406\uff0c\u8bf7\u7a0d\u5019...",ajaxError:"\u5bf9\u4e0d\u8d77\uff0c\u53ef\u80fd\u56e0\u4e3a\u7f51\u7edc\u6545\u969c\u5bfc\u81f4\u7cfb\u7edf\u53d1\u751f\u5f02\u5e38\u9519\u8bef\uff01",prevPageText:"\u4e0a\u4e00\u9875",nextPageText:"\u4e0b\u4e00\u9875",year:"\u5e74",month:"\u6708",day:"\u5929",hour:"\u5c0f\u65f6",minute:"\u5206\u949f",second:"\u79d2",timeoutText:"\u65f6\u95f4\u5230"};
/**
 * @author zexin.zhaozx
 */

(function() {
        var ua = navigator.userAgent.toLowerCase();
        var _isOpera = ua.indexOf('opera') != -1,
                _isSafari = ua.indexOf('safari') != -1,
                _isGecko = !_isOpera && !_isSafari && ua.indexOf('gecko') > -1,
                _isIE = !_isOpera && ua.indexOf('msie') != -1,
                _isIE6 = !_isOpera && ua.indexOf('msie 6') != -1,
                _isIE7 = !_isOpera && ua.indexOf('msie 7') != -1;
               
        TB.bom = {
                isOpera: _isOpera,
                isSafari: _isSafari,
                isGecko: _isGecko,
                isIE: _isIE,
                isIE6: _isIE6,
                isIE7: _isIE7,
                       
                /**
             * »ñÈ¡cookie
             * @method getCookie
             * @param {String} name cookieÃû³Æ
             * @return {String} cookie µÄÖµ»òÕß¿Õ×Ö·û´®
             */
                getCookie: function(name) {
                        var value = document.cookie.match('(?:^|;)\\s*'+name+'=([^;]*)');
                        return value ? unescape(value[1]) : '';
                },
       
            /**
             * ÉèÖÃcookie
             * @method setCookie
             * @param {String} name cookieÃû³Æ
                 * @param {String} value cookieµÄÖµ
             * @return {String} cookie µÄÖµ»òÕß¿Õ×Ö·û´®
             */
                setCookie: function(name, value, expire, domain, path) {
                        value = escape(value);
                        value += (domain) ? '; domain=' + domain : '';
                        value += (path) ? "; path=" + path : '';
                        if (expire){
                                var date = new Date();
                                date.setTime(date.getTime() + (expire * 86400000));
                                value += "; expires=" + date.toGMTString();
                        }
                        document.cookie = name + "=" + value;
                },
       
                /**
                 * É¾³ýcookie
                 * @method removeCookie
                 * @param {Object} name
                 */
                removeCookie: function(name) {
                        this.setCookie(name, '', -1);
                },
       
                /**
                 * ÌáÈ¡µ±Ç°hostnameµÄdomain.domain;
                 * Ä¬ÈÏ·µ»Øµ±Ç°hostnameµÄµÚÒ»²ã¸¸¼¶Óò£¬Èç www.xyx.taobao.com -> xyz.taoboa.com£¬store.taobao.com - > taobao.com
                 * ¿É´«µÝÒ»¸ö²ÎÊýn£¬Ö¸¶¨È¡n¼¶µÄ¸¸¼¶Óò£¬Èçn=2, Ôòwww.xyx.taobao.com -> taoboa.com
                 * Èç¹ûhostname±¾ÉíÖ»ÓÐ¶þ¼¶Óò£¬»ò²ÎÊýn¹ý´ó£¬Ôò×ÜÊÇ·µ»Ø¶þ¼¶Óò
                 *
                 * ×¢Òâ£ºÀàËÆsina.com.cnÕâÑù´ø¹ú¼ÒÇøÓòµÄÓòÃû¿ÉÄÜÓÐÎó¡£
                 *
                 * @method pickDocumentDomain
                 * @return expected document.domain value
                 */
                pickDocumentDomain: function() {
                        var host = arguments[1] || location.hostname;
                        var da = host.split('.'), len = da.length;
                        var deep = arguments[0]|| (len<3?0:1);
                        if (deep>=len || len-deep<2)
                                deep = len-2;
                        return da.slice(deep).join('.');
                },
               
                /**
                 * Ìí¼Óµ½ÊÕ²Ø¼Ð
                 * @param {Object} title
                 * @param {Object} url
                 */
                addBookmark: function(title, url) {
                    if (window.sidebar) {
                        window.sidebar.addPanel(title, url,"");
                    } else if( document.external ) {
                        window.external.AddFavorite( url, title);
                    } else {
                                /* TODO */
                        }
                }
        }
})();/**
 * DOM utilities
 * @TODO
 */
TB.dom = {
       
        /**
         * insertAfter
         * @param {Object} node
         * @param {Object} refNode
         * @deprecated use YAHOO.util.Dom.insertAfter
         */
        insertAfter: function(node, refNode) {
                return $D.insertAfter(node, refNode);
        },
       
        /**
         * ¸ù¾ÝtagName»ñÈ¡×î½üÒ»¸ö×æÏÈ½Úµã
         * @param {Object} el
         * @param {Object} tag
         * @deprecated use YAHOO.util.Dom.getAncestorByTagName
         */
        getAncestorByTagName: function(el, tag) {
                return $D.getAncestorByTagName(el, tag);
        },
       
        /**
         * ¸ù¾Ýclass»ñÈ¡×î½üµÄÒ»¸ö×æÏÈ½Úµã
         * @param {Object} el
         * @param {Object} cls
         * @deprecated use YAHOO.util.Dom.getAncestorByClassName
         */
        getAncestorByClassName: function(el, cls) {
                return $D.getAncestorByClassName(el, cls);
        },
       
        /**
         * »ñÈ¡Ö®ºóµÄÐÖµÜ½Úµã
         * @param {Object} node
         * @deprecated use YAHOO.util.Dom.getNextSibling
         */    
        getNextSibling: function(node) {
                return $D.getNextSibling(node);
        },
       
        /**
         * »ñÈ¡Ö®Ç°µÄÐÖµÜ½Úµã
         * @param {Object} node
         * @deprecated use YAHOO.util.Dom.getPreviousSibling
         */
        getPreviousSibling: function(node) {
                return $D.getPreviousSibling(node);    
        },
       
        /**
         * »ñÈ¡±íµ¥ÓòµÄlabel
         * @param {Object} el
         * @param {Object} parent
         */
        getFieldLabelHtml: function(el, parent) {
                var input = $(el), labels = (parent || input.parentNode).getElementsByTagName('label');
                for (var i = 0; i < labels.length; i++) {
                        var forAttr = labels[i].htmlFor || labels[i].getAttribute('for')
                        if (forAttr == input.id)
                                return labels[i].innerHTML;
                }
                return null;
        },
       
        /**
         * »ñÈ¡iframeµÄdocument
         * @param {Object} el
         */
        getIframeDocument: function(el) {
                var iframe = $(el);
                return iframe.contentWindow? iframe.contentWindow.document : iframe.contentDocument;
        },


        /**
         * ÉèÖÃ±íµ¥µÄactionÊôÐÔ£¬´¦Àí±íµ¥ÖÐ°üº¬Í¬ÃûµÄfieldÊ±µÄÇé¿ö
         * @param {Object} form  form ¶ÔÏó
         * @param {Object} url  action url
         */
        setFormAction: function(form, url) {
                form = $(form);
            var actionInput = form.elements['action'];
            var postSet;
            if (actionInput) {
                var ai = form.removeChild(actionInput);
                postSet = function() {
                    form.appendChild(ai);
                        }
            }
            form.action = url;
            if (postSet)
                postSet();
            return true;
        },
       
        /**
         * Ìí¼ÓÑùÊ½ÎÄ±¾
         * @param {Object} cssText
         * @param {Object} doc
         */
        addCSS: function(cssText, doc) {
                doc = doc || document;
                var styleEl = doc.createElement('style');
                styleEl.type = "text/css";
                doc.getElementsByTagName('head')[0].appendChild(styleEl); //ÏÈappendChild£¬·ñÔòhackÊ§Ð§
                if (styleEl.styleSheet) {
                        styleEl.styleSheet.cssText = cssText;
                } else {
                        styleEl.appendChild(doc.createTextNode(cssText));
                }
        },
       
        /**
         * ¸ù¾Ý½Å±¾Ãû×Ö£¬È¡µÃ½Å±¾²ÎÊý
         * @param {Object}||{RegExp}||{String} script
         */
        getScriptParams: function(script) {
                var p = /\?(.*?)($|\.js)/;
                var m;
                //Èç¹ûÊÇ <script> tag
                if (YAHOO.lang.isObject(script) && script.tagName && script.tagName.toLowerCase()=='script') {
                        if (script.src && (m = script.src.match(p))) {
                                return m[1].toQueryParams();  
                        }
                } else {
                        //Èç¹ûÊÇ string£¬ ×ª³É regexp
                        if (YAHOO.lang.isString(script)) {
                                script = new RegExp(script, 'i');
                        }
                        var scripts = document.getElementsByTagName("script");
                        var matchs, ssrc;
                        for (var i = 0; i < scripts.length; ++i) {
                                ssrc = scripts[i].src;
                                if (ssrc && script.test(ssrc) && (m = ssrc.match(p))) {
                                        return m[1].toQueryParams();
                                }
                        }
                }
        }      
       
}/**
 * @fileOverview TB.anim »ùÓÚYAHOO.util.Anim·â×°µÄ¶¯»­Ð§¹û
 * @name TB.anim
 * @example
        new TB.anim.Highlight(el, {
                startColor: '#ffff99'
        }).animate();
 */
 
/**
 * @constructor
 * @param {Object} el Ó¦ÓÃ¶¯»­µÄÔªËØ
 * @param {Object} [config]  ÅäÖÃ²ÎÊý
 */    
TB.anim.Highlight = function(el, config) {
        if (!el) return;
        this.init(el, config)
}

/**
 * Ä¬ÈÏÅäÖÃ
 */
TB.anim.Highlight.defConfig = {
        /** ¼ÓÁÁ¿ªÊ¼Ê±ÉèÖÃµÄ±³¾°É«*/
        startColor: '#ffff99',
        /** ¶¯»­Ê±³¤ */
        duration: .5,
        /** ÊÇ·ñ±£³ÖÔ­ÏÈµÄ±³¾° */
        keepBackgroundImage: true
};

TB.anim.Highlight.prototype.init = function(el, config) {
        var Y = YAHOO.util;
        config = TB.applyIf(config||{}, TB.anim.Highlight.defConfig);

        var attr = {backgroundColor: {from: config.startColor}};
        var anim =      new Y.ColorAnim(el, attr, config.duration);
        var originBgColor = anim.getAttribute('backgroundColor');
        anim.attributes['backgroundColor']['to'] = originBgColor;

        if (config.keepBackgroundImage) {
                var originBg = $D.getStyle(el, 'background-image');
                anim.onComplete.subscribe(function() {
                        $D.setStyle(el, 'background-image', originBg);
                });
        }
       
        /**
         * onComplete »Øµ÷£¬Ö±½ÓÒýÓÃ±»·â×°µÄ Anim ¶ÔÏóµÄ onComplete ÊÂ¼þ
         */    
        this.onComplete = anim.onComplete;
       
        /**
         * Ö´ÐÐ¶¯»­
         */
        this.animate = function() {
                $D.setStyle(el, 'background-image', 'none');
                anim.animate();
        }
};

/**
 * @author xiaoma<xiaoma@taobao.com>
 */

/**
        config ÊôÐÔËµÃ÷

        position: {String} [left|right|top|bottom]
        autoFit: {Boolean} ÊÇ·ñ×ÔÊÊÓ¦´°¿Ú
        width: {Number} popup width
        height: {Number} popup height
        offset: {Array} offset
        eventType: {String} [mouse|click] Êó±êÒÆ¶¯´¥·¢»¹ÊÇµã»÷´¥·¢
        disableClick: {Boolean}
        delay: {Number} Êó±êÒÆ¶¯´¥·¢Ê±¼äÑÓ³Ù
        onShow: {function} ÏÔÊ¾»Øµ÷º¯Êý
        onHide: {Function} Òþ²Ø»Øµ÷º¯Êý
 */
       
TB.widget.SimplePopup = new function() {
        var Y = YAHOO.util;

        var defConfig = {
                position: 'right',
                autoFit: true,
                eventType: 'mouse',
                delay: 0.1,
                disableClick: true,  /* stopEvent when eventType = mouse */
                width: 200,
                height: 200            
        };
       
        /**
         * ÊÂ¼þ´¦ÀíÆ÷
         * scope is handle
         * @param {Object} ev
         */    
        var triggerClickHandler = function(ev) {
                var target = $E.getTarget(ev);
                if (triggerClickHandler._target == target) {
                        this.popup.style.display == 'block'? this.hide() : this.show();
                } else {
                        this.show();
                }
                $E.preventDefault(ev);
                triggerClickHandler._target = target;
        }
        var triggerMouseOverHandler = function(ev) {
                clearTimeout(this._popupHideTimeId);
                var self = this;
                this._popupShowTimeId = setTimeout(function(){
                        self.show();
                }, this.config.delay * 1000);
                if (this.config.disableClick && !this.trigger.onclick) {
                        this.trigger.onclick = function(e) {
                                $E.preventDefault($E.getEvent(e));
                        };
                }                      
        }

        var triggerMouseOutHandler = function(ev) {
                clearTimeout(this._popupShowTimeId);
                if (!$D.isAncestor(this.popup, $E.getRelatedTarget(ev))){
                        this.delayHide();
                }
                $E.preventDefault(ev);
        }
       
        var popupMouseOverHandler = function(ev) {
                var handle = this.currentHandle? this.currentHandle : this;
                clearTimeout(handle._popupHideTimeId);
        }


        var popupMouseOutHandler = function(ev) {
                var handle = this.currentHandle? this.currentHandle : this;
                if (!$D.isAncestor(handle.popup, $E.getRelatedTarget(ev))){
                        handle.delayHide();
                }
        }
       
        this.decorate = function(trigger, popup, config) {
                if (YAHOO.lang.isArray(trigger) || (YAHOO.lang.isObject(trigger) && trigger.length)) {
                        config.shareSinglePopup = true;
                        var groupHandle = {};
                        groupHandle._handles = [];
                        /* batch²Ù×÷Ê±´¦ÓÚ¼òµ¥¿¼ÂÇ£¬²»·µ»Øhandle object */
                        for (var i = 0; i < trigger.length; i++) {
                                var h = this.decorate(trigger[i], popup, config);
                                h._beforeShow = function(){
                                        groupHandle.currentHandle = this;
                                        return true;
                                };
                                groupHandle._handles[i] = h;
                        }
                        if (config.eventType == 'mouse') {
                                $E.on(popup, 'mouseover', popupMouseOverHandler, groupHandle, true);
                                $E.on(popup, 'mouseout', popupMouseOutHandler, groupHandle, true);
                        }                      
                        return groupHandle;
                }
               
                trigger = $(trigger);
                popup = $(popup);
                if (!trigger || !popup) return;
                config = TB.applyIf(config||{}, defConfig);
                /* ·µ»Ø¸øµ÷ÓÃÕßµÄ¿ØÖÆÆ÷£¬Ö»°üº¬¶Ôµ÷ÓÃÕß¿É¼ûµÄ·½·¨/ÊôÐÔ */              
                var handle = {};                

                handle._popupShowTimeId = null;
                handle._popupHideTimeId = null;
                handle._beforeShow = function(){return true};

                var onShowEvent = new Y.CustomEvent("onShow", handle, false, Y.CustomEvent.FLAT);
                if (config.onShow) {
                        onShowEvent.subscribe(config.onShow);  
                }
                var onHideEvent = new Y.CustomEvent("onHide", handle, false, Y.CustomEvent.FLAT);
                if (config.onHide) {
                        onHideEvent.subscribe(config.onHide);  
                }                      

                if (config.eventType == 'mouse') {
                        $E.on(trigger, 'mouseover', triggerMouseOverHandler, handle, true);
                        $E.on(trigger, 'mouseout', triggerMouseOutHandler, handle, true);
                        /* batch ²Ù×÷Ê±£¬Popup µÄÊó±êÊÂ¼þÖ»×¢²áÒ»´Î */
                        if (!config.shareSinglePopup) {
                                $E.on(popup, 'mouseover', popupMouseOverHandler, handle, true);
                                $E.on(popup, 'mouseout', popupMouseOutHandler, handle, true);
                        }
                }
                else if (config.eventType == 'click') {
                        $E.on(trigger, 'click', triggerClickHandler, handle, true);
                }

                TB.apply(handle, {
                        popup: popup,
                        trigger: trigger,
                        config: config,
                        show: function() {
                                if (!this._beforeShow()) return;
                                var pos = $D.getXY(this.trigger);
                                if (YAHOO.lang.isArray(this.config.offset)) {
                                        pos[0] += parseInt(this.config.offset[0]);
                                        pos[1] += parseInt(this.config.offset[1]);
                                }
                                var tw = this.trigger.offsetWidth, th = this.trigger.offsetHeight;
                                var pw = config.width, ph = config.height;
                                var dw = $D.getViewportWidth(), dh = $D.getViewportHeight();
                var sl = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
                                var st = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
                               
                                var l = pos[0], t = pos[1];
                                if (config.position == 'left') {
                                        l = pos[0]-pw;
                                }
                                else if (config.position == 'right') {
                                        l = pos[0]+tw;
                                } else if (config.position == 'bottom') {
                                        t = t+th;
                                } else if (config.position == 'top') {
                                        t = t-ph;
                                        if (t < 0) t = 0;
                                }
                               
                                if(this.config.autoFit) {
                                        if (t-st+ph > dh) {
                                                t = dh-ph+st-2; /* 2px Æ«²î */
                                                if (t < 0) {
                                                        t = 0;
                                                }
                                        }
                                }
                                       
                                this.popup.style.position = 'absolute';
                                this.popup.style.top = t + 'px';
                                this.popup.style.left = l + 'px';
                                if (this.config.effect) {
                                        if (this.config.effect == 'fade') {
                                                $D.setStyle(this.popup, 'opacity', 0);
                                                this.popup.style.display = 'block';
                                                var anim = new Y.Anim(this.popup, { opacity: {to: 1} }, 0.4);
                                                anim.animate();
                                        }
                                } else {
                                        this.popup.style.display = 'block';
                                }
                                onShowEvent.fire();                                    
                        },
                        hide: function() {
                                $D.setStyle(this.popup, 'display', 'none');
                                onHideEvent.fire();
                        },
                        delayHide: function() {
                                var self = this;
                        this._popupHideTimeId = setTimeout(function(){
                                        self.hide();
                                }, this.config.delay*1000);
                        }                      
                });
               
                $D.setStyle(popup, 'display', 'none');

                return handle;          
        }
}
       
/**
 * @author xiaoma
 */
/** ¼òµ¥¹ö¶¯ */
TB.widget.SimpleScroll = new function() {
       
        var Y = YAHOO.util;    
        var defConfig = {
                delay: 2,
                speed: 20,
                startDelay: 2,
                direction: 'vertical',  /* 'horizontal(h)' or 'vertical(v)'. defaults to vertical. */          
                disableAutoPlay: false,
                distance: 'auto',
                scrollItemCount: 1  /** ËæÍ¬Ò»ÐÐ¹ö¶¯µÄliÊýÁ¿£¬Ä¬ÈÏ1 */          
        }
        /**
         * container ±ØÐëÊÇÒ»¸ö ul
         * @param {Object} container
         * @param {Object} config
         */
        this.decorate = function(container, config) {
                container = $(container);
                config = TB.applyIf(config||{}, defConfig);
                var step = 2;
                if (config.speed < 20) {
                        step = 5;
                }
                if (config.lineHeight) {
                        config.distance = config.lineHeight;
                }
               
                var scrollTimeId = null, startTimeId = null, startDelayTimeId = null;
                /* ÊÇ·ñºáÏò¹ö¶¯ */
                var isHorizontal = (config.direction.toLowerCase() == 'horizontal') || (config.direction.toLowerCase() == 'h');
               
                /* ·µ»Ø¸øµ÷ÓÃÕßµÄ¿ØÖÆÆ÷£¬Ö»°üº¬¶Ôµ÷ÓÃÕß¿É¼ûµÄ·½·¨/ÊôÐÔ */      
                var handle = {};
                handle._distance = 0;
                /* ¿Õ¼äÉÏÄÜ·ñ»¹¿ÉÒÔ¹ö¶¯ */
                handle.scrollable = true;
                /* ±¾´ÎÔ¤¼Æ¹ö¶¯µÄ¾àÀë */
                handle.distance = config.distance;
                /* Ã¿´Î¹ö¶¯µÄ¾àÀë */
                handle._distance = 0;
                /* Êó±êÒÆ¶¯ÉÏÈ¥Ê±ÔÝÍ£ */
                handle.suspend = false;
                /* ÔÝÍ£ */
                handle.paused = false;
       
               
                /* ÄÚ²¿Ê¹ÓÃÊÂ¼þ */
                var _onScrollEvent = new Y.CustomEvent("_onScroll", handle, false, Y.CustomEvent.FLAT);
                _onScrollEvent.subscribe(function() {
                        var curLi = container.getElementsByTagName('li')[0];
                        if (!curLi) {
                                this.scrollable = false;
                                return;
                        }
                        this.distance = (config.distance == 'auto')?curLi[isHorizontal?'offsetWidth':'offsetHeight']:config.distance;
                        with(container) {
                                if (isHorizontal)
                                        this.scrollable = (scrollWidth - scrollLeft - offsetWidth) >= this.distance;
                                else
                                        this.scrollable = (scrollHeight - scrollTop - offsetHeight) >= this.distance;
                        }
                });
               
                /* ¹«¿ªÊÂ¼þ */
                var onScrollEvent = new Y.CustomEvent("onScroll", handle, false, Y.CustomEvent.FLAT);
                if (config.onScroll) {
                        onScrollEvent.subscribe(config.onScroll);
                } else {
                        onScrollEvent.subscribe(function() {
                                for (var i = 0; i < config.scrollItemCount; i++) {
                                        container.appendChild(container.getElementsByTagName('li')[0]);
                                }
                                container[isHorizontal?'scrollLeft':'scrollTop'] = 0;
                        });
                }
               
                var scroll = function() {
                        if (handle.suspend) return;
                        handle._distance += step;
                        var _d;
                        if ((_d = handle._distance % handle.distance) < step) {
                                container[isHorizontal?'scrollLeft':'scrollTop'] += (step - _d);
                                clearInterval(scrollTimeId);
                                onScrollEvent.fire();
                                _onScrollEvent.fire();
                                startTimeId = null;
                                if (handle.scrollable && !handle.paused) handle.play();
                        }else{
                                container[isHorizontal?'scrollLeft':'scrollTop'] += step;
                        }
                }
               
                var start = function() {
                        if (handle.paused) return;
                        handle._distance = 0;
                        scrollTimeId = setInterval(scroll, config.speed);
                }


                $E.on(container, 'mouseover', function(){handle.suspend=true;});
                $E.on(container, 'mouseout', function(){handle.suspend=false;});
               
                TB.apply(handle, {
                        subscribeOnScroll: function(func, override) {
                                if (override === true && onScrollEvent.subscribers.length > 0)
                                        onScrollEvent.unsubscribeAll();
                                onScrollEvent.subscribe(func);
                        },
                        pause: function() {
                                this.paused = true;
                                clearTimeout(startTimeId);
                                startTimeId = null;
                        },
                        play: function() {
                                this.paused = false;
                                if (startDelayTimeId) {clearTimeout(startDelayTimeId);}
                                if (!startTimeId) {
                                        startTimeId = setTimeout(start, config.delay*1000);    
                                }
                        }
                });
                handle.onScroll = handle.subscribeOnScroll;
               
                /** ³õÊ¼»¯ÒÆ¶¯¾àÀë²¢ÅÐ¶ÏÊÇ·ñ¿É¹ö¶¯ */
                _onScrollEvent.fire();
                /** ×Ô¶¯¿ªÊ¼¹ö¶¯ */            
                if (!config.disableAutoPlay) {
                        startDelayTimeId = setTimeout(function(){handle.play();}, config.startDelay*1000);
                }              
                return handle;
        }
};/**
 * TBra Slide
 *
 * ÏÞÖÆ£º»ÃµÆÆ¬±ØÐë°üÀ¨ÔÚ<ul>ÖÐ£¬Ã¿ÕÅ»ÃµÆÆ¬ÊÇÒ»¸ö<li>¡£
 * @author xiaoma<xiaoma@taobao.com>
 *
 */
/* »ÃµÆÆ¬²¥·Å */
(function() {
        var Y = YAHOO.util;
       
        TB.widget.Slide = function(container, config) {
                this.init(container, config);
        }
        /* Ä¬ÈÏ²ÎÊýÅäÖÃ */
        TB.widget.Slide.defConfig = {
                slidesClass: 'Slides',                  /* »ÃµÆÓ°Æ¬ulµÄclassName */
                triggersClass: 'SlideTriggers',         /* ´¥µãµÄclassName */
                currentClass: 'Current',                        /* µ±Ç°´¥µãµÄclassName */
                eventType: 'click',                                     /* ´¥µã½ÓÊÜµÄÊÂ¼þÀàÐÍ£¬Ä¬ÈÏÊÇÊó±êµã»÷ */
                autoPlayTimeout: 5,                                     /* ×Ô¶¯²¥·ÅÊ±¼ä¼ä¸ô */
                disableAutoPlay: false                          /* ½ûÖ¹×Ô¶¯²¥·Å */
        };
        TB.widget.Slide.prototype = {
                /**
                 * ³õÊ¼»¯¶ÔÏóÊôÐÔºÍÐÐÎª
                 * @method init
                 * @param {Object} container ÈÝÆ÷¶ÔÏó»òID
                 * @param {Object} config ÅäÖÃ²ÎÊý
                 */
                init: function(container, config) {
                        this.container = $(container);
                        this.config = TB.applyIf(config||{}, TB.widget.Slide.defConfig);
                        try {
                                this.slidesUL = $D.getElementsByClassName(this.config.slidesClass, 'ul', this.container)[0];
                               
                                if(!this.slidesUL) {
                                        //È¡µÚÒ»¸ö ul ×Ó½Úµã
                                        this.slidesUL = $D.getFirstChild(this.container, function(node) {
                                                return node.tagName.toLowerCase === 'ul';
                                        });
                                }
                               
                                this.slides = $D.getChildren(this.slidesUL); //Ö»È¡Ö±½ÓµÄ×Ó<li>ÔªËØ
                                if (this.slides.length == 0) {
                                        throw new Error();
                                }
                        } catch (e) {
                                throw new Error("can't find slides!");
                        }
                        this.delayTimeId = null;                /* eventType = 'mouse' Ê±£¬ÑÓ³ÙµÄTimeId */
                        this.autoPlayTimeId = null;             /* ×Ô¶¯²¥·ÅTimeId */
                        this.curSlide = -1;
                        this.sliding = false;
                        this.pause = false;
                        this.onSlide = new Y.CustomEvent("onSlide", this, false, Y.CustomEvent.FLAT);
                        if (YAHOO.lang.isFunction(this.config.onSlide)){
                                this.onSlide.subscribe(this.config.onSlide, this, true);
                        }
                       
                        this.beforeSlide = new Y.CustomEvent("beforeSlide", this, false, Y.CustomEvent.FLAT);
                        if (YAHOO.lang.isFunction(this.config.beforeSlide)){
                                this.beforeSlide.subscribe(this.config.beforeSlide, this, true);
                        }                      
                       
                        /* Ö¸¶¨tbra.cssÖÐÉè¶¨µÄ class */
                        $D.addClass(this.container, 'tb-slide');
                        $D.addClass(this.slidesUL, 'tb-slide-list');
                        $D.setStyle(this.slidesUL, 'height', (this.config.slideHeight || this.container.offsetHeight) + 'px');
                       
                        this.initSlides(); /* ³õÊ¼»¯»ÃµÆÆ¬ÉèÖÃ */
                        this.initTriggers();
                        if (this.slides.length > 0)
                                this.play(1);
                        if (! this.config.disableAutoPlay){
                                this.autoPlay();
                        }
                        if (YAHOO.lang.isFunction(this.config.onInit)) {
                                this.config.onInit.call(this);
                        }
                },
               
                /**
                 * ¸ù¾Ý»ÃµÆÆ¬³¤¶È×Ô¶¯Éú³É´¥µã£¬°üº¬ÔÚÒ»¸ö<ul>ÖÐ£¬Ò³ÃæÖÐCSSÖÐ±ØÐëÓÐ¶ÔÓ¦ÊôÐÔÉèÖÃ
                 * @method initTriggers
                 */
                initTriggers: function() {
                        var ul = document.createElement('ul');
                        this.container.appendChild(ul);
                        for (var i = 0; i < this.slides.length; i++) {
                                var li = document.createElement('li');
                                li.innerHTML = i+1;
                                ul.appendChild(li);
                        }
                        $D.addClass(ul, this.config.triggersClass);
                        this.triggersUL = ul;
                        if (this.config.eventType == 'mouse') {
                                $E.on(this.triggersUL, 'mouseover', this.mouseHandler, this, true);
                                $E.on(this.triggersUL, 'mouseout', function(e){
                                        clearTimeout(this.delayTimeId);
                                        this.pause = false;
                                }, this, true);
                        } else {
                                $E.on(this.triggersUL, 'click', this.clickHandler, this, true);
                        }
                },
               
                /**
                 * ³õÊ¼»¯»ÃµÆÆ¬
                 * @method initSlides
                 */
                initSlides: function() {
                        $E.on(this.slides, 'mouseover', function(){this.pause = true;}, this, true);
                        $E.on(this.slides, 'mouseout', function(){this.pause = false;}, this, true);
                        $D.setStyle(this.slides, 'display', 'none');
                },
               
                /**
                 * µã»÷ÊÂ¼þ´¦Àí
                 * @param {Object} e Event¶ÔÏó
                 */
                clickHandler: function(e) {
                        var t = $E.getTarget(e);
                        var idx = parseInt(TB.common.stripTags(t.innerHTML));
                        while(t != this.container) {
                                if(t.nodeName.toUpperCase() == "LI") {
                                         /* Èç¹û»¹ÔÚ»¬¶¯ÖÐ,Í£Ö¹ÏìÓ¦ */
                                        if (!this.sliding){
                                                this.play(idx, true);
                                        }
                                        break;
                                } else {
                                        t = t.parentNode;
                                }
                        }              
                },
               
                /**
                 * Êó±êÊÂ¼þ´¦Àí
                 * @param {Object} e Event ¶ÔÏó
                 */
                mouseHandler: function(e) {
                        var t = $E.getTarget(e);
                        var idx = parseInt(TB.common.stripTags(t.innerHTML));
                        while(t != this.container) {
                                if(t.nodeName.toUpperCase() == "LI") {
                                        var self = this;                        
                                        this.delayTimeId = setTimeout(function() {
                                                        self.play(idx, true);
                                                        self.pause = true;
                                                }, (self.sliding?.5:.1)*1000);
                                        break;
                                } else {
                                        t = t.parentNode;
                                }
                        }
                },
               
                /**
                 * ²¥·ÅÖ¸¶¨Ò³µÄ»ÃµÆÆ¬
                 * @param {Object} n Ò³Êý£¬Ò²¾ÍÊÇ´¥µãÊý×ÖÖµ
                 * @param {Object} flag Èç¹ûflag=true£¬ÔòÊÇÓÃ»§´¥·¢µÄ£¬·´Ö®ÔòÎª×Ô¶¯²¥·Å
                 */
                play: function(n, flag) {
                        n = n - 1;
                        if (n == this.curSlide) return;
                        var curSlide = this.curSlide >= 0 ? this.curSlide : 0;
                        if (flag && this.autoPlayTimeId)
                                clearInterval(this.autoPlayTimeId);
                        var triggersLis = this.triggersUL.getElementsByTagName('li');
                        triggersLis[curSlide].className = '';
                        triggersLis[n].className = this.config.currentClass;
                        this.beforeSlide.fire(n);
                        this.slide(n);
                        this.curSlide = n;
                        if (flag && !this.config.disableAutoPlay)
                                this.autoPlay();
                },
               
                /**
                 * ÇÐ»»»ÃµÆÆ¬£¬×î¼òµ¥µÄÇÐ»»¾ÍÊÇÒþ²Ø/ÏÔÊ¾¡£
                 * ²»Í¬µÄÐ§¹û¿ÉÒÔ¸²¸Ç´Ë·½·¨
                 * @see TB.widget.ScrollSlide
                 * @see TB.widget.FadeSlide
                 * @param {Object} n Ò³Êý
                 */
                slide: function(n) {
                        var curSlide = this.curSlide >= 0 ? this.curSlide : 0;
                        this.sliding = true;
                        $D.setStyle(this.slides[curSlide], 'display', 'none');
                        $D.setStyle(this.slides[n], 'display', 'block');
                        this.sliding = false;
                        this.onSlide.fire(n);
                },
               
                /**
                 * ÉèÖÃ×Ô¶¯²¥·Å
                 * @method autoPlay
                 */
                autoPlay: function() {
                        var self = this;
                        var callback = function() {
                                if ( !self.pause && !self.sliding ) {
                                        var n = (self.curSlide+1) % self.slides.length + 1;
                                        self.play(n, false);
                                }
                        }
                        this.autoPlayTimeId = setInterval(callback, this.config.autoPlayTimeout * 1000);
                }
        }
       
        /**
         * ¹ö¶¯Ð§¹ûµÄ»ÃµÆÆ¬²¥·ÅÆ÷
         * @param {Object} container
         * @param {Object} config
         */
        TB.widget.ScrollSlide = function(container, config){
                this.init(container, config);
        }
        YAHOO.extend(TB.widget.ScrollSlide, TB.widget.Slide, {
                /**
                 * ¸²¸Ç¸¸ÀàµÄÐÐÎª£¬²»Òþ²Ø»ÃµÆÆ¬
                 * CSSÖÐ×¢ÒâÉèÖÃ slidesUL overflow:hidden£¬±£Ö¤Ö»ÏÔÊ¾Ò»·ù»ÃµÆ
                 */
                initSlides: function() {
                        TB.widget.ScrollSlide.superclass.initSlides.call(this);
                        $D.setStyle(this.slides, 'display', '');
                },
                /**
                 * ¸²¸Ç¸¸ÀàµÄÐÐÎª£¬Ê¹ÓÃ¹ö¶¯¶¯»­
                 * @param {Object} n
                 */
                slide: function(n) {
                        var curSlide = this.curSlide >= 0 ? this.curSlide : 0;
                        var args = { scroll: {by:[0, this.slidesUL.offsetHeight*(n-curSlide)]} };
                        var anim = new Y.Scroll(this.slidesUL, args, .5, Y.Easing.easeOutStrong);
                        anim.onComplete.subscribe(function(){
                                this.sliding = false;
                                this.onSlide.fire(n);
                        }, this, true);
                        anim.animate();
                        this.sliding = true;
                }
        });
       
        /**
         * µ­Èëµ­³öÐ§¹ûµÄ»ÃµÆÆ¬²¥·ÅÆ÷
         * @param {Object} container
         * @param {Object} config
         */
        TB.widget.FadeSlide = function(container, config){
                this.init(container, config);
        }
        YAHOO.extend(TB.widget.FadeSlide, TB.widget.Slide, {
                /**
                 * ¸²¸Ç¸¸ÀàµÄÐÐÎª£¬ÉèÖÃ»ÃµÆÆ¬µÄposition=absolute
                 */
                initSlides: function() {
                        TB.widget.FadeSlide.superclass.initSlides.call(this);
                        $D.setStyle(this.slides, 'position', 'absolute');
                        $D.setStyle(this.slides, 'top', this.config.slideOffsetY||0);
                        $D.setStyle(this.slides, 'left', this.config.slideOffsetX||0);
                        $D.setStyle(this.slides, 'z-index', 1);
                },
               
                /**
                 * ¸²¸Ç¸¸ÀàµÄÐÐÎª£¬Ê¹ÓÃµ­Èëµ­³ö¶¯»­
                 * @param {Object} n
                 */
                slide: function(n) {
                        /* µÚÒ»´ÎÔËÐÐ */
                        if (this.curSlide == -1) {
                                $D.setStyle(this.slides[n], 'display', 'block');
                                this.onSlide.fire(n);
                        } else {
                                var curSlideLi = this.slides[this.curSlide];
                                $D.setStyle(curSlideLi, 'display', 'block');
                                $D.setStyle(curSlideLi, 'z-index', 10);
                                var fade = new Y.Anim(curSlideLi, { opacity: { to: 0 } }, .5, Y.Easing.easeNone);
                                fade.onComplete.subscribe(function(){
                                        $D.setStyle(curSlideLi, 'z-index', 1);
                                        $D.setStyle(curSlideLi, 'display', 'none');
                                        $D.setStyle(curSlideLi, 'opacity', 1);
                                        this.sliding = false;
                                        this.onSlide.fire(n);
                                }, this, true);
                               
                                $D.setStyle(this.slides[n], 'display', 'block');
                               
                                fade.animate();                
                                this.sliding = true;
                        }
                }
        });    
       
})();


/**
 * Slide µÄ·â×°£¬Í¨¹ý effect ²ÎÊý£¬´´½¨²»Í¬µÄSlide¶ÔÏó
 */
TB.widget.SimpleSlide = new function() {
       
        this.decorate = function(container, config) {
                if (!container) return;
                config = config || {};
                if (config.effect == 'scroll') {
                        /** <li>ÏÂ°üº¬<iframe>Ê±£¬firefoxÏÔÊ¾Òì³£ */
                        if (YAHOO.env.ua.gecko) {
                                if (YAHOO.util.Dom.get(container).getElementsByTagName('iframe').length > 0) {
                                        return new TB.widget.Slide(container, config);
                                }
                        }
                        return new TB.widget.ScrollSlide(container, config);
                }
                else if (config.effect == 'fade') {
                        return new TB.widget.FadeSlide(container, config);
                }
                else {
                        return new TB.widget.Slide(container, config);
                }
        }      
}/* ¼òµ¥TabÇÐ»» */
TB.widget.SimpleTab = new function() {
        var Y = YAHOO.util;
        var defConfig = {
                eventType: 'click',
                currentClass: 'Current',  /* li µ±Ç°Ñ¡ÖÐ×´Ì¬Ê±µÄclassName */
                tabClass: '',  /* ×÷Îª tab µÄelementµÄ className */
                autoSwitchToFirst: true,  /* ÊÇ·ñÄ¬ÈÏÑ¡ÖÐµÚÒ»¸ötab */
                stopEvent: true,  /* Í£Ö¹ÊÂ¼þ´«²¥ */
                delay: 0.1  /* available when eventType=mouse */
        };
        var getImmediateDescendants = function(p) {
                var ret = [];
                if (!p) return ret;
                for (var i = 0, c = p.childNodes; i < c.length; i++) {
                        if (c[i].nodeType == 1)
                                ret[ret.length] = c[i];
                }
                return ret;    
        };
        this.decorate = function(container, config) {
                container = $(container);
                config = TB.applyIf(config||{}, defConfig);
                /* ·µ»Ø¸øµ÷ÓÃÕßµÄ¿ØÖÆÆ÷£¬Ö»°üº¬¶Ôµ÷ÓÃÕß¿É¼ûµÄ·½·¨/ÊôÐÔ */              
                var handle = {};
       
                var tabPanels = getImmediateDescendants(container);
                var tab = tabPanels.shift(0);
                var tabTriggerBoxs  = tab.getElementsByTagName('li');
                var tabTriggers, delayTimeId;
                if (config.tabClass) {
                        tabTriggers = $D.getElementsByClassName(config.tabClass, '*', container);
                } else {
                        tabTriggers = TB.common.toArray(tab.getElementsByTagName('a')); /* Ä¬ÈÏÈ¡tabÏÂµÄ<a> */
                }
                var onSwitchEvent = new Y.CustomEvent("onSwitch", null, false, Y.CustomEvent.FLAT);
                if (config.onSwitch) {
                        onSwitchEvent.subscribe(config.onSwitch);
                }

                var focusHandler = function(ev) {
                        if (delayTimeId)
                                cacelHandler();
                        var idx = tabTriggers.indexOf(this);
                        handle.switchTab(idx);
                        if (config.stopEvent) {
                                try {
                                        $E.stopEvent(ev);
                                }catch (e) {
                                        /* ignore */
                                }
                        }
                        return !config.stopEvent;
                }
                var delayHandler = function(ev) {
                        var target = this;
                        delayTimeId = setTimeout(function(){
                                focusHandler.call(target, ev);
                        }, config.delay*1000);
                        if (config.stopEvent)
                                $E.stopEvent(ev);
                        return !config.stopEvent;
                }
                var cacelHandler = function() {
                        clearTimeout(delayTimeId);
                }
                if (config.eventType == 'mouse') {
                        $E.on(tabTriggers, 'focus', focusHandler);
                        $E.on(tabTriggers, 'mouseover', config.delay?delayHandler:focusHandler);
                        $E.on(tabTriggers, 'mouseout', cacelHandler);
                }
                else {
                        $E.on(tabTriggers, 'click', focusHandler);
                }

                /* ¶¨Òå¹«¿ªµÄ·½·¨ */
                TB.apply(handle, {
                        switchTab: function(idx) {
                                $D.setStyle(tabPanels, 'display', 'none');
                                $D.removeClass(tabTriggerBoxs, config.currentClass);
                                $D.addClass(tabTriggerBoxs[idx], config.currentClass);
                                $D.setStyle(tabPanels[idx], 'display', 'block');
                                onSwitchEvent.fire(idx);
                        },
                        subscribeOnSwitch: function(func) {
                                onSwitchEvent.subscribe(func);
                        }
                });
                handle.onSwitch = handle.subscribeOnSwitch;
               
                /*³õÊ¼»¯²Ù×÷*/
                $D.setStyle(tabPanels, 'display', 'none');
                if (config.autoSwitchToFirst)
                        handle.switchTab(0);
               
                /* ·µ»Ø²Ù×÷¶ÔÏó */
                return handle;
        }
};/**
 * ÆÀ·Ö×é¼þ
 * ÐèÒªstar-rating.css
 */

TB.widget.SimpleRating = new function() {
       
        var defConfig = {
                rateUrl: '',  /* ÆÀ·ÖÊý¾Ý·¢ËÍ¸øµÄURL */
                rateParams: '',  /* ÆäËû²ÎÊý£¬¸ñÊ½k1=v1&k2=v2 */
                scoreParamName: 'score', /* ÆÀÂÛ²ÎÊýÃû */
                topScore: 5,  /* ×î¸ß·Ö */
                currentRatingClass: 'current-rating'
        };

        var rateHandler = function(ev, handle) {
                $E.stopEvent(ev);
                var aEl = $E.getTarget(ev);
                var score = parseInt(aEl.innerHTML);
                try {
                        aEl.blur();    
                } catch (e) {}
                handle.rate(score);
        }
       
        var updateCurrentRating = function(currentRatingLi, avg, config) {
                if (currentRatingLi)
                        currentRatingLi.innerHTML = avg;
                        $D.setStyle(currentRatingLi, 'width', avg*100/config.topScore + '%');
        }
               
        this.decorate = function(ratingContainer, config) {
                ratingContainer = $(ratingContainer);  /* Ò»¸ö<ul> */
                config = TB.applyIf(config || {}, defConfig);
                var currentRatingLi = $D.getElementsByClassName(config.currentRatingClass, 'li', ratingContainer)[0];
               
                var onRateEvent = new YAHOO.util.CustomEvent('onRate', null, false, YAHOO.util.CustomEvent.FLAT);
                if (config.onRate)
                        onRateEvent.subscribe(config.onRate);
                var handle = {};
               
                handle.init = function(avg) {
                        /* ¼ì²é¿´ÊÇ·ñÐèÒªÏÔÊ¾µ±Ç°µÄ·ÖÊý */
                        updateCurrentRating(currentRatingLi, avg, config);
                }
               
                handle.update = function(ret) {
                        if (ret && ret.Average && currentRatingLi) {
                                updateCurrentRating(currentRatingLi, ret.Average, config);
                        }
                        /* Ö»ÄÜÆÀ·ÖÒ»´Î */
                        $E.purgeElement(ratingContainer, true, 'click');
                        /* ÒÆ³ýÆäËûµÄli */
                        for (var lis = ratingContainer.getElementsByTagName('li'), i = lis.length-1; i > 0; i--) {
                                ratingContainer.removeChild(lis[i]);            
                        }
                        onRateEvent.fire(ret);
                }
               
                handle.rate = function(score) {
                        var indicator = TB.util.Indicator.attach(ratingContainer, {message:$M('pleaseWait')});
                        indicator.show();              
                        ratingContainer.style.display = 'none';
                        var postData = config.scoreParamName + '=' + score;
                        if (config.rateParams)
                                postData += '&' + config.rateParams;
                        YAHOO.util.Connect.asyncRequest('POST', config.rateUrl, {
                                success: function(req) {
                                        indicator.hide();
                                        ratingContainer.style.display = '';                                    
                                        var ret = eval('(' + req.responseText + ')');
                                        if (ret.Error) {
                                                alert(ret.Error.Message);
                                                return;
                                        } else {
                                                handle.update(ret);    
                                        }
                                },
                                failure: function(req) {
                                        indicator.hide();
                                        ratingContainer.style.display = '';                                                    
                                        TB.trace($M('ajaxError'));
                                }
                        }, postData);                          
                }
               
                handle.onRate = function(callback) {
                        if (YAHOO.lang.isFunction(callback))
                                onRateEvent.subscribe(callback);                
                }                              
               
                var triggers = ratingContainer.getElementsByTagName('a');
                for (var i = 0; i < triggers.length; i++) {
                        $E.on(triggers[i], 'click', rateHandler, handle);
                }
                               
                return handle;
        }
}/**
 * @author zexin.zhaozx
 */
TB.widget.InputHint = new function() {
        var defConfig = {
                hintMessage: '',
                hintClass: 'tb-input-hint',
                appearOnce: false
        };
        var EMPTY_PATTERN = /^\s*$/;
       
        var focusHandler = function(ev, handle) {
                if (!handle.disabled)
                        handle.disappear();
        }
        var blurHandler = function(ev, handle) {
                if (!handle.disabled)
                        handle.appear();
        }
       
        this.decorate = function(inputField, config) {
                inputField = $(inputField);
                config = TB.applyIf(config || {}, defConfig);
                var hintMessage = config.hintMessage || inputField.title;
                var handle = {};
                handle.disabled = false;
               
                handle.disappear = function() {
                        if (hintMessage == inputField.value) {
                                inputField.value = '';
                                $D.removeClass(inputField, config.hintClass);
                        }
                };
               
                handle.appear = function() {
                        if (EMPTY_PATTERN.test(inputField.value) || hintMessage == inputField.value) {
                                $D.addClass(inputField, config.hintClass);
                                inputField.value = hintMessage;                        
                        }
                }
               
                handle.purge = function() {
                        this.disappear();
                        $E.removeListener(inputField, 'focus', focusHandler);
                        $E.removeListener(inputField, 'drop', focusHandler);
                        $E.removeListener(inputField, 'blur', blurHandler);
                }
               
                /* ³õÊ¼»¯ */
                if (!inputField.title)
                        inputField.setAttribute("title", hintMessage);
                $E.on(inputField, 'focus', focusHandler, handle);
                $E.on(inputField, 'drop', focusHandler, handle); /* for ie/safari */
               
                if (!config.appearOnce)
                        $E.on(inputField, 'blur', blurHandler, handle);
               
                /* Ä¬ÈÏÏÈÏÔÊ¾ */
                handle.appear();
                return handle;
        }
}/**
 * Countdown Timer
 * @author xiaoma<xiaoma@taobao.com>
 */
TB.util.CountdownTimer = new function() {
       
        var Y = YAHOO.util;
       
        var MINUTE = 60;
        var HOUR = MINUTE * 60;
        var DAY = HOUR*24;      
       
        var defConfig = {
                formatStyle: 'short', /* 'long' £º xÌìxÐ¡Ê±x·ÖxÃë  or 'short' £º[xÌìxÐ¡Ê± | xÐ¡Ê±x·Ö | x·ÖxÃë]  or custom */
                formatPattern: '',  /* for formatStyle == custom */
                hideZero: true, /* for formatStyle == 'long' : if day==0 then show xÐ¡Ê±x·ÖxÃë£¬etc. */
                timeoutText: 'timeoutText',
                updatable: true
        };
       
        var leadingZero = function(n) {
                return ((n < 10) ? "0" : "") + n;
        }
       
        var genTimeFilter = function(lt) {
                return function(val, key) {
                        switch(key) {
                                case 'd':
                                        return parseInt(lt / DAY);
                                case 'dd':
                                        return leadingZero(parseInt(lt / DAY));
                                case 'hh':
                                        return leadingZero(parseInt(lt % DAY / HOUR));
                                case 'h':
                                        return parseInt(lt % DAY / HOUR);
                                case 'mm':
                                        return leadingZero(parseInt(lt % DAY % HOUR / MINUTE));
                                case 'm':
                                        return parseInt(lt % DAY % HOUR / MINUTE);
                                case 'ss':
                                        return leadingZero(parseInt(lt % DAY % HOUR % MINUTE));
                                case 's':
                                        return parseInt(lt % DAY % HOUR % MINUTE);                              
                        }
                }
        }
       
        this.attach = function(container, leftTime, config) {
                container = $(container);
                leftTime = parseInt(leftTime);
                config = TB.applyIf(config||{}, defConfig);
                var handle = {};
                               
                var onStartEvent = new Y.CustomEvent("onStart", null, false, Y.CustomEvent.FLAT);
                if (config.onStart) {
                        onStartEvent.subscribe(config.onStart);
                }
                var onEndEvent = new Y.CustomEvent("onEnd", null, false, Y.CustomEvent.FLAT);
                if (config.onEnd) {
                        onEndEvent.subscribe(config.onEnd);
                }
               
                var currTime = parseInt(new Date().getTime()/1000);
                var endTime = currTime + leftTime;


                var updateTimer = function() {
                        handle.update();                        
                }
                               
                handle.update = function() {
                        var pattern = config.formatPattern, values = {}, nu = 1;
                        if (config.formatStyle == 'long') {
                                pattern = '{d}' + $M('day') + '{hh}' + $M('hour') + '{mm}' + $M('minute') + '{ss}' + $M('second');
                        }                      
                        var lt = endTime - parseInt(new Date().getTime()/1000);
                        if (lt <= 0) {
                                container.innerHTML = $M(config.timeoutText);
                                onEndEvent.fire();
                                return;                        
                        }
                        else if (lt > DAY) {
                                if (config.formatStyle == 'short') {
                                        pattern = '{d}' + $M('day') + '{hh}' + $M('hour');
                                        nu = Math.floor(lt % DAY % HOUR) || HOUR;
                                }
                        }
                        else if (lt > HOUR) {
                                if (config.formatStyle == 'short') {
                                        pattern = '{hh}' + $M('hour') + '{mm}' + $M('minute');
                                        nu = Math.floor(lt % HOUR % MINUTE) || MINUTE;
                                } else if (config.formatStyle == 'long' && config.hideZero) {
                                        pattern = '{hh}' + $M('hour') + '{mm}' + $M('minute') + '{ss}' + $M('second');
                                }
                        }
                        else if (lt > 0) {
                                if (config.formatStyle == 'short' || (config.formatStyle == 'long' && config.hideZero)) {
                                        pattern = '{mm}' + $M('minute') + '{ss}' + $M('second');
                                }
                        }
                       
                        container.innerHTML = TB.common.formatMessage(pattern, values, genTimeFilter(lt));
                        if (config.updatable && nu > 0)
                                setTimeout(updateTimer, nu*1000);
                }
               
                handle.init = function() {
                        this.update();
                        onStartEvent.fire();
                }
                               
                handle.init();
                return handle;
        }
}/** ×´Ì¬Ö¸Ê¾Æ÷ */
TB.util.Indicator = new function() {
       
        var defConfig = {
                message: 'loading',
                useShim: false,
                useIFrame: false,
                centerIndicator: true
        }
       
        var prepareShim = function(target, useIFrame) {
                var shim = document.createElement('div');
                shim.className = 'tb-indic-shim';
                $D.setStyle(shim, 'display', 'none');
                target.parentNode.insertBefore(shim, target);
                if (useIFrame) {
                        var shimFrame = document.createElement('iframe');
                        shimFrame.setAttribute("frameBorder", 0);
                        shimFrame.className = 'tb-indic-shim-iframe';
                        target.parentNode.insertBefore(shimFrame, target);
                }
                return shim;
        }      
       
        this.attach = function(target, config) {
                target = $(target);
                config = TB.applyIf(config||{}, defConfig);
               
                var indicator =  document.createElement('div');
                indicator.className = 'tb-indic';
                $D.setStyle(indicator, 'display', 'none');
                $D.setStyle(indicator, 'position', 'static');
                indicator.innerHTML = '<span>'+$M(config.message)+'</span>';
               
                if (config.useShim) {
                        var shim = prepareShim(target, config.useIFrame);
                        shim.appendChild(indicator);
                } else {
                        target.parentNode.insertBefore(indicator, target);      
                }
               
                var handle = {};
               
                handle.show = function(xy) {
                        if (config.useShim) {
                                var region = $D.getRegion(target);      
                               
                                var shim = indicator.parentNode;
                                $D.setStyle(shim, 'display', 'block');
                                $D.setXY(shim, [region[0], region[1]]);
                                $D.setStyle(shim, 'width', (region.right-region.left)+'px');
                                $D.setStyle(shim, 'height', (region.bottom-region.top)+'px');
                               
                                if (config.useIFrame) {
                                        var shimFrame = shim.nextSibling;
                                        $D.setStyle(shimFrame, 'width', (region.right-region.left)+'px');
                                        $D.setStyle(shimFrame, 'height', (region.bottom-region.top)+'px');
                                        $D.setStyle(shimFrame, 'display', 'block');
                                }
                               
                                $D.setStyle(indicator, 'display', 'block');
                                $D.setStyle(indicator, 'position', 'absolute');
                                if (config.centerIndicator) {
                                        $D.setStyle(indicator, 'top', '50%');
                                        $D.setStyle(indicator, 'left', '50%');
                                        indicator.style.marginTop = -(indicator.offsetHeight/2) + 'px';
                                        indicator.style.marginLeft = -(indicator.offsetWidth/2) + 'px';
                                }
                        } else {
                                $D.setStyle(indicator, 'display', '');
                                if (xy) {
                                        $D.setStyle(indicator, 'position', 'absolute');
                                        $D.setXY(indicator, xy);
                                }
                        }
                };

                handle.hide = function() {
                        if (config.useShim) {
                                var shim = indicator.parentNode;
                                $D.setStyle(indicator, 'display', 'none');
                                $D.setStyle(shim, 'display', 'none');
                                if (config.useIFrame)
                                        $D.setStyle(indicator.parentNode.nextSibling, 'display', 'none');
                                try {
                                        if (config.useIFrame)
                                                shim.parentNode.removeChild(shim.nextSibling);
                                        shim.parentNode.removeChild(shim);
                                } catch (e) {}
                        } else {
                                $D.setStyle(indicator, 'display', 'none');
                                try {
                                        indicator.parentNode.removeChild(indicator);
                                } catch (e) {}
                        }
                };
               
                return handle;
        }
}/* ¼òµ¥·ÖÒ³ */
TB.util.Pagination = new function() {
       
        var PAGE_SEPARATOR = '...'; /*Ò³Ê¡ÂÔ·ûºÅ*/      

        /* Ä¬ÈÏÅäÖÃ²ÎÊý */      
        var defConfig = {
                pageUrl: '',
                prevPageClass: 'PrevPage',  /*ÉÏÒ»Ò³<li>µÄclassName*/
                noPrevClass: 'NoPrev',       /*ÉÏÒ»Ò³²»¿ÉÓÃÊ±<li>µÄclassName*/
                prevPageText: 'prevPageText',
                nextPageClass: 'NextPage',  /*ÏÂÒ»Ò³<li>µÄclassName*/
                nextPageText: 'nextPageText',
                noNextClass: 'NoNext',       /*ÏÂÒ»Ò³²»¿ÉÓÃÊ±<li>µÄclassName*/          
                currPageClass: 'CurrPage',  /*µ±Ç°Ò³<li>µÄclassName*/
                pageParamName: 'page',          /*±êÊ¶Ò³ÊýµÄ²ÎÊýÃû*/
                appendParams: '',   /*¸½´øÆäËûµÄ²ÎÊý*/
                pageBarMode: 'bound',  /*·ÖÒ³ÌõµÄÑùÊ½  bound | eye | line*/
                showIndicator: true,   /*ÏÔÊ¾¼ÓÔØÌáÊ¾Í¼±ê*/
                cachePageData: false  /*»º´æ·ÖÒ³Êý¾Ý*/
        }
       
        /**
         * Í£Ö¹clickÊÂ¼þ´«²¥£¬ÓÃÓÚÉÏ/ÏÂÒ»Ò³²»¿ÉÓÃÊ±£¬»òÕß·ÖÒ³Êý¾Ý¼ÓÔØÖÐÊ±ËùÓÐ·ÖÒ³µã¶¼±»½ûÓÃÊ±
         * @param {Object} ev  ÊÂ¼þ¶ÔÏó
         */
        var cancelHandler = function(ev) {
                $E.stopEvent(ev);
        }
       
        /**
         * ·ÖÒ³µã»÷ÊÂ¼þ´¦Àí³ÌÐò
         * @param {Object} ev    ÊÂ¼þ¶ÔÏó
         * @param {Object} args  ²ÎÊý¸ñÊ½Îª [pageIndex, handle]
         */
        var pageHandler = function(ev, args) {
                $E.stopEvent(ev);
                var target = $E.getTarget(ev);
                args[1].gotoPage(args[0]);
        }
       
        /**
         * ¹¹Ôì"bound"ÐÎÊ½µÄ·ÖÒ³ÁÐ±í
         * @param {Object} pageIndex  µ±Ç°Ò³
         * @param {Object} pageCount  ×ÜÒ³Êý
         */
        var buildBoundPageList = function(pageIndex, pageCount) {
        var l = [];
        var leftStart = 1;
        var leftEnd = 2;
        var mStart = pageIndex - 2;
        var mEnd = pageIndex + 2;
        var rStart = pageCount - 1;
        var rEnd = pageCount;


        if (mStart <= leftEnd) {
            leftStart = 0;
            leftEnd = 0;
            mStart = 1;
        }

        if (mEnd >= rStart) {
            rStart = 0;
            rEnd = 0;
            mEnd = pageCount;
        }

        if (leftEnd > leftStart) {
            for (var i = leftStart; i <= leftEnd; ++i) {
                l[l.length] = ""+i;
            }

            if ((leftEnd + 1) < mStart) {
                l[l.length] = PAGE_SEPARATOR;
            }
        }

        for (var i = mStart; i <= mEnd; ++i) {
                l[l.length] = ""+i;
        }

        if (rEnd > rStart) {
            if ((mEnd + 1) < rStart) {
                l[l.length] = PAGE_SEPARATOR;
            }

            for (var i = rStart; i <= rEnd; ++i) {
                l[l.length] = ""+i;
            }
        }
        return l;
        }
       
        /**
         * ´´½¨°üÀ¨Ò³·ûµÄ<li> element
         * @param {Object} idx   Ò³·û
         * @param {Object} config
         */
        var buildPageEntry = function(idx, config) {
                var liEl = document.createElement('li');
                if (idx != PAGE_SEPARATOR) {
                        $D.addClass(liEl, (idx=='prev')?config.prevPageClass:(idx=='next')?config.nextPageClass:'');
                        var aEl = document.createElement('a');
                        aEl.setAttribute('title',(idx == 'prev')?$M(config.prevPageText):(idx=='next')?$M(config.nextPageText):''+idx);
                        aEl.href = buildPageUrl(idx, config) + '&t=' + new Date().getTime();
                        aEl.innerHTML = (idx=='prev')?$M(config.prevPageText):(idx=='next')?$M(config.nextPageText):idx;
                        liEl.appendChild(aEl);
                } else {
                        /*Èç¹ûÊÇ·ÖÒ³Ê¡ÂÔ·Ö¸ô·û£¬Ö±½ÓÏÔÊ¾Ê¡ÂÔºÅ*/
                        liEl.innerHTML = PAGE_SEPARATOR;
                }
                return liEl;
        }
       
        /**
         * ¹¹ÔìÒ³±êUrl
         * @param {Object} idx
         * @param {Object} config
         */
        var buildPageUrl = function(idx, config) {
                var url = config.pageUrl + (config.pageUrl.lastIndexOf('?')!=-1?'&':'?') + config.pageParamName + '=' + idx;
                if (config.appendParams)
                        url += '&' + config.appendParams;
                return url;
        }
       
        /**
         * ½Ó¿Úº¯Êý
         * @param {Object} pageBarContainer ·ÖÒ³ÌõÈÝÆ÷
         * @param {Object} pageDataContainer  Ò³ÃæÊý¾ÝÈÝÆ÷
         * @param {Object} config ÅäÖÃ²ÎÊý
         */
        this.attach = function(pageBarContainer, pageDataContainer, config) {  
                pageBarContainer = $(pageBarContainer);
                pageDataContainer = $(pageDataContainer);
                config = TB.applyIf(config||{}, defConfig);
               
                /*Êý¾Ý»º´æ¶ÔÏó*/
                if (config.cachePageData) {
                        var pageDataCache = {};
                }
               
                var ulEl = document.createElement('ul');
                pageBarContainer.appendChild(ulEl);
               
                var pageLoadEvent = new YAHOO.util.CustomEvent('pageLoad', null, false, YAHOO.util.CustomEvent.FLAT);
               
                var handle = {};
               
                /**
                 * ÖØÐÂÕûÀí·ÖÒ³·û
                 * @param {Object} pageObj  JSON¸ñÊ½µÄ·ÖÒ³Êý¾Ý
                 *
                 * Êý¾Ý¸ñÊ½
                 * {
                 *              "Pagination": {
                 *                      "PageIndex": 1, //µ±Ç°Ò³
                 *                      "PageCount" : 3 , //×ÜÒ³Êý
                 *                      "PageSize" : 100, //Ò³ÃæÌõÄ¿Êý
                 *                      "TotalCount" : 300, //ÌõÄ¿×ÜÊý£¨¿ÉÑ¡£©
                 *                      "PageData" : "<html>" //±àÂëºóµÄhtml´úÂë
                 *              }
                 *      }
                 */
                handle.rebuildPageBar = function(pageObj) {
                        if (!pageObj) return;

                        this.pageIndex = parseInt(pageObj.PageIndex);
                        this.totalCount = parseInt(pageObj.TotalCount);
                        this.pageCount = parseInt(pageObj.PageCount);
                        this.pageSize = parseInt(pageObj.PageSize);
                       
                        /* Çå³ýpage UL ÄÚÈÝ²¢ÖØÐÂ¹¹Ôì */
                        ulEl.innerHTML = '';
                       
                        /* »ñÈ¡·ÖÒ³Ò³ÂëÁÐ±í */
                        var list = this.repaginate();

                        /* ÉÏÒ»Ò³µ¼º½µ¥Ôª */
                        var prevLiEl = buildPageEntry('prev', config);
                        if (!this.isPrevPageAvailable()) {
                                $D.addClass(prevLiEl, config.noPrevClass);
                                $E.on(prevLiEl, 'click', cancelHandler);
                        } else {
                                $E.on(prevLiEl, 'click', pageHandler, [this.pageIndex-1, this]);
                        }
                        ulEl.appendChild(prevLiEl);                    
                       
                        /* Ñ­»·¹¹Ôì·ÖÒ³·û */
                        for (var i = 0; i < list.length; i++) {
                                var liEl = buildPageEntry(list[i], config);
                                if (list[i] == this.pageIndex) {
                                        $D.addClass(liEl, config.currPageClass);
                                        $E.on(liEl, 'click', cancelHandler);
                                } else {
                                        $E.on(liEl, 'click', pageHandler, [list[i], this]);                            
                                }
                                ulEl.appendChild(liEl);
                        }
                       
                        /* ÏÂÒ»Ò³µ¼º½µ¥Ôª */
                        var nextLiEl = buildPageEntry('next', config);
                        if (!this.isNextPageAvailable()) {
                                $D.addClass(nextLiEl, config.noNextClass);
                                $E.on(nextLiEl, 'click', cancelHandler);
                        } else {
                                $E.on(nextLiEl, 'click', pageHandler, [this.pageIndex+1, this]);
                        }                      
                        ulEl.appendChild(nextLiEl);
                }
               
                /**
                 * ¹¹Ôì·ÖÒ³Ò³Âë±í
                 */
                handle.repaginate = function() {
                        var mode = config.pageBarMode;
                        if (mode == 'bound') {
                                /* ·µ»Ø bound ÐÎÊ½µÄ·ÖÒ³Ìõ£¬¼ä¶ÏÐÔµÄÏÔÊ¾Ò³Âë */
                                return buildBoundPageList(parseInt(this.pageIndex), parseInt(this.pageCount));
                        } else if (mode == 'line') {
                                /* ·µ»Ø line ÐÎÊ½µÄ·ÖÒ³Ìõ£¬ÏÔÊ¾ËùÓÐÒ³Âë */
                                var l = [];
                                for (var i = 1; i <= this.pageCount; i++) {
                                        l.push(i);
                                }
                                return l;
                        } else if (mode == 'eye') {
                                /* ·µ»Ø eye ÐÎÊ½µÄ·ÖÒ³Ìõ,Ö»ÓÐÏòÇ°ÏòºóµÄ·ÖÒ³ÐÎÊ½ */
                                return [];
                        }
                }
               
                /**
                 * ÏÔÊ¾Ö¸¶¨Ò³ÂëµÄÊý¾Ý
                 * @param {Object} idx  Ò³Âë
                 */
                handle.gotoPage = function(idx) {
                        this.disablePageBar();
                        if (config.showIndicator) {
                                $D.setStyle(pageDataContainer, 'display', 'none');
                                var indicator = TB.util.Indicator.attach(pageDataContainer, {message:$M('loading')});
                                indicator.show();
                        }
                        var url = buildPageUrl(idx, config);
                       
                        /* Èç¹ûÉèÖÃÁËÊý¾Ý»º´æ£¬¶ø·¢ÏÖ»º´æÊý¾ÝÒÑ´æÔÚ£¬Ö±½ÓÏÔÊ¾»º´æÖÐµÄÊý¾Ý */
                        if (config.cachePageData) {
                                if (pageDataCache[url]) {
                                        handle.showPage(pageDataCache[url]);
                                        return;
                                }
                        }
                       
                        YAHOO.util.Connect.asyncRequest('GET', url + '&t=' + new Date().getTime(), {
                                success: function(req) {
                                        var resultSet = eval('(' + req.responseText + ')');
                                        handle.showPage(resultSet.Pagination);
                                        if (config.cachePageData) {
                                                pageDataCache[url] = resultSet.Pagination;      
                                        }
                                        if (config.showIndicator){
                                                indicator.hide();
                                                $D.setStyle(pageDataContainer, 'display', 'block');
                                        }                      
                                },
                                failure: function(req) {
                                        if (config.showIndicator){
                                                $D.setStyle(pageDataContainer, 'display', 'block');                                            
                                                indicator.hide();
                                        }
                                        handle.rebuildPageBar();                        
                                        alert($M('ajaxError'));
                                }
                        });    
                }
               
                handle.showPage = function(pageObj) {
                        this._showPage(pageObj);
                        this.rebuildPageBar(pageObj);
                        pageLoadEvent.fire(pageObj);
                }
               
                handle._showPage = function(pageObj) {
                        if (pageObj.PageData && YAHOO.lang.isString(pageObj.PageData))
                                pageDataContainer.innerHTML = pageObj.PageData;
                }


                /**
                 * ´æÔÚÏÂÒ»Ò³£¿
                 */
                handle.isNextPageAvailable = function() {
                        return this.pageIndex < this.pageCount;
                }

                /**
                 * ´æÔÚÉÏÒ»Ò³?
                 */
                handle.isPrevPageAvailable = function() {
                        return this.pageIndex > 1;
                }
               
                /**
                 * ½ûÓÃ·ÖÒ³Ìõ£¬µ±ÓÃ»§µã»÷Ä³¸ö·ÖÒ³·ûÊ±£¬½ûÓÃÕû¸ö·ÖÒ³ÌõÖÐËùÓÐ<a>µÄµã»÷²Ù×÷£¬²¢ÉèÖÃÆädisabled=1
                 * @param {Object} bar
                 */
                handle.disablePageBar = function() {
                        $D.addClass(pageBarContainer, 'Disabled');
                        /* ÏÈÖØÖÃËùÓÐonclick event handler */
                        $E.purgeElement(pageBarContainer, true, 'click');
                        var els = TB.common.toArray(pageBarContainer.getElementsByTagName('a'));
                        els.forEach(function(el, i){
                                $E.on(el, 'click', cancelHandler);
                                el.disabled = 1;
                        });
                }              
               
                /**
                 * ×¢²áÒ³ÃæÊý¾Ý¼ÓÔØÍê³ÉºóÖ´ÐÐµÄ»Øµ÷º¯Êý
                 * @param {Object} callback
                 */
                handle.onPageLoad = function(callback) {
                        if (YAHOO.lang.isFunction(callback))
                                pageLoadEvent.subscribe(callback);
                }
               
                /**
                 * ÉèÖÃqueryÆäËû²ÎÊý
                 * @param {Object} params
                 */
                handle.setAppendParams = function(params) {
                        config.appendParams = params;
                }
               
                return handle;          
        }                      
}/**
 * ¹¹ÔìqueryString
 * @param {Object} maps
 */
TB.util.QueryData = function() {
        this.data = [];
        this.addField = function(input) {
                for(var i = 0; i < arguments.length; i++) {
                        var field = arguments[i];
                        if (field)
                                this.add(field.name, encodeURIComponent(field.value));
                }
        }
        this.add = function(name, value) {
                this.data.push({"name":name, "value":value});
        }
        this.get = function(name) {
                for (var i = 0; i < this.data.length; i++) {
                        if (this.data[i].name === name)
                                return this.data[i].value;
                }
                return null;
        }
        this.toQueryString = function() {
                var qs = this.data.map(function(o, i) {
                        return o.name + '=' + o.value;
                });
                return qs.join('&');                    
        }
}/**
 * @author zexin.zhaozx
 */
TB.form.CheckboxGroup = new function() {
        var Y = YAHOO.util;
        var defConfig = {
                checkAllBox: 'CheckAll',
                checkAllBoxClass: 'tb:chack-all',
                checkOnInit: true /* ³õÊ¼»¯Ê±ÊÇ·ñÔ¤´¦Àí */
        }
        var getChecked = function(o, i) { return o.checked;     }
        var setChecked = function(o, i) {
                if (o.type && o.type.toLowerCase()=='checkbox')
                        o.checked = true;
        }
        var setUnchecked = function(o, i) {
                if (o.type && o.type.toLowerCase()=='checkbox')
                        o.checked = false;
        }
       
        this.attach = function(checkboxGroup, config) {
                config = TB.applyIf(config || {}, defConfig);
                /*·µ»Ø¸øµ÷ÓÃÕßµÄ¿ØÖÆÆ÷£¬Ö»°üº¬¶Ôµ÷ÓÃÕß¿É¼ûµÄ·½·¨/ÊôÐÔ*/
                var handle = {};
                var onCheckEvent = new Y.CustomEvent('onCheck', handle, false, Y.CustomEvent.FLAT);                    
       
                var checkboxes = [];
                if (checkboxGroup) {
                        if(checkboxGroup.length)
                                checkboxes = TB.common.toArray(checkboxGroup);
                        else
                                checkboxes[0] = checkboxGroup; /*Èç¹ûÖ»ÓÐÒ»¸öcheckbox*/        
                }
               
                var checkAllBoxes = [];
                if (config.checkAllBoxClass) {
                        checkAllBoxes = $D.getElementsByClassName(config.checkAllBoxClass, null, checkboxes[0].form);
                }
                if ($(config.checkAllBox)) {
                        checkAllBoxes.push($(config.checkAllBox));
                }
 
                var doCheck = function() {
                        var checkedBoxes = checkboxes.filter(getChecked);
                        if (checkboxes.length == 0) {
                                checkAllBoxes.forEach(setUnchecked);
                        } else {
                                checkAllBoxes.forEach((checkedBoxes.length == checkboxes.length)?setChecked:setUnchecked);
                        }                      
                        handle._checkedBoxCount = checkedBoxes.length;
                }              
                var clickHandler = function(ev) {
                        var checkbox = $E.getTarget(ev);
                        doCheck();
                        onCheckEvent.fire(checkbox);
                        return true;
                }

                TB.apply(handle, {
                        _checkedBoxCount : 0,
                       
                        onCheck: function(func) {
                                onCheckEvent.subscribe(func);
                        },
                       
                        isCheckAll: function() {
                                return this._checkedBoxCount == checkboxes.length;                              
                        },
                        isCheckNone: function() {
                                return this._checkedBoxCount == 0;
                        },
                        isCheckSome: function() {
                                return this._checkedBoxCount != 0;
                        },
                        isCheckSingle: function() {
                                return this._checkedBoxCount == 1;
                        },
                        isCheckMulti: function() {
                                return this._checkedBoxCount > 1;
                        },                      
                        toggleCheckAll: function() {
                                var allChecked = checkboxes.every(getChecked);
                                checkboxes.forEach(allChecked?setUnchecked:setChecked);
                                if (checkboxes.length == 0) {
                                        checkAllBoxes.forEach(setUnchecked);
                                } else {
                                        checkAllBoxes.forEach(allChecked?setUnchecked:setChecked);
                                }
                                handle._checkedBoxCount = (allChecked)?0:checkboxes.length;
                                checkboxes.forEach(function(o){
                                        onCheckEvent.fire(o);
                                });
                        },
                        toggleChecked: function(checkbox) {
                                checkbox.checked = !checkbox.checked;
                                doCheck();
                                onCheckEvent.fire(checkbox);
                        },
                        getCheckedBoxes: function() {
                                return checkboxes.filter(getChecked);
                        }
                });

                $E.on(checkboxes, 'click', clickHandler);
                if (config.onCheck && YAHOO.lang.isFunction(config.onCheck))
                        onCheckEvent.subscribe(config.onCheck, handle, true);
                if (checkAllBoxes.length > 0) {
                        $E.on(checkAllBoxes, 'click', handle.toggleCheckAll);
                }
                if (config.checkOnInit) {
                        doCheck();
                        var checkOnInit = function() {
                                checkboxes.forEach(function(o){
                                        onCheckEvent.fire(o);
                                });
                        }
                        setTimeout(checkOnInit, 10);
                }
                return handle;
        }        
}/**
 * @author zexin.zhaozx
 */
TB.form.TagAssistor = new function() {
       
        /**
         * Ä¬ÈÏÅäÖÃ²ÎÊý
         */
        var defConfig = {
                separator: ' ', /*Ä¬ÈÏ·Ö¸ô·ûÊÇ¿Õ¸ñ*/
                selectedClass: 'Selected'
        }
       
        /**
         * ÅÐ¶ÏÑ¡ÖÐµÄtagÊÇ·ñÔÚarrayÖÐ´æÔÚ£¬Èç¹û´æÔÚ·µ»Øtrue£¬·´Ö®false¡£
         * @param {Object} tagArr
         * @param {Object} tagEl
         */
        var tagExists = function(tagArr, tagEl) {
                return tagArr.indexOf(TB.common.trim(tagEl.innerHTML)) != -1;
        }
       
        var value2TagArray = function(textField, separator) {
                /*½«Á¬ÐøµÄ¿Õ¸ñÌæ»»Îªµ¥¸ö¿Õ¸ñ£¬²¢È¥³ýÊ×Î²µÄ¿Õ¸ñ*/
                var val = textField.value.replace(/\s+/g, ' ').trim();
                if (val.length > 0)
                        return val.split(separator);
                else
                        return [];
        }
       
        /**
         * Ö¸ÅÉ¸øÊäÈëÔªËØºÍ±¸Ñ¡tagµÄÈÝÆ÷
         * @param {Object} textField ±ØÐëÊÇÒ»¸ö<input>»òÕß<textarea>
         * @param {Object} tagsContainer ·ÅÖÃ±¸Ñ¡tagµÄelement£¬¿ÉÄÜÊÇÒ»¸öul»òdl
         * @param {Object} config ÅäÖÃ²ÎÊý
         */
        this.attach = function(textField, tagsContainer, config) {
                textField = $(textField);
                tagsContainer = $(tagsContainer);
                config = TB.applyIf(config || {}, defConfig);
               
               
                var triggers = TB.common.toArray(tagsContainer.getElementsByTagName('a'));              
               
                /**
                 * µã»÷±¸Ñ¡tagµÄÊÂ¼þ´¦Àí³ÌÐò
                 * @param {Object} ev
                 */
                var clickHandler = function(ev) {
                        var tagArray = value2TagArray(textField, config.separator);
                        var target = $E.getTarget(ev);
                        /* tagÒÑÑ¡ÖÐ */
                        if (tagExists(tagArray, target)) {
                                tagArray.remove(TB.common.trim(target.innerHTML));
                        } else {
                                tagArray.push(TB.common.trim(target.innerHTML));
                        }
                        updateClass(tagArray);
                        textField.value = tagArray.join(config.separator);
                }
               
                var updateClass = function(tagArray) {
                        triggers.forEach(function(o, i) {
                                if (tagExists(tagArray, o)) {
                                        $D.addClass(o, config.selectedClass);
                                } else {
                                        $D.removeClass(o, config.selectedClass);
                                }                                              
                        })                                              
                }
               
                var handle = {};
                /**
                 * ³õÊ¼»¯µÄÒ»Ð©¹¤×÷
                 */
                handle.init = function() {
                        var tagArray = value2TagArray(textField, config.separator);


                        /* ¸øÃ¿¸ö       ±¸Ñ¡tagµÄ<a> ×¢²áÊÂ¼þ´¦Àí³ÌÐò */
                        triggers.forEach(function(o, i){
                                if (tagExists(tagArray, o)) {
                                        $D.addClass(o, config.selectedClass);
                                }
                                $E.on(o, 'click', clickHandler);
                        });
                       
                        /* ¼à²âÃ¿´ÎµÄ¼üÅÌ¶¯×÷£¬Èç¹û·¢ÏÖÆ¥Åä»òÕß²»Æ¥ÅäµÄtagÎÄ×Ö£¬Ôö¼Ó»òÈ¡Ïû×ÅÖØÐ§¹û */
                        $E.on(textField, 'keyup', function(ev){
                                var tagArray = value2TagArray(textField, config.separator);
                                updateClass(tagArray);                          
                        });
                }
                handle.init();
        }
}
