﻿// 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');


	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];
				}				
			}
		}
	}
}
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();
	}
}

