var YAO = function(){
    var D = window.document, 
	documentElement = D.documentElement, 
	defaultView = D.defaultView, 
	head = D.getElementsByTagName('head')[0], 
	body = D.body, 
	OA = '[object  Array]', 
	OF = "[object Function]", 
	OP = Object.prototype, 
	userAgent = navigator.userAgent, 
	specialChar = {
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"': '\\"',
        '\\': '\\\\'
    }, 
	webkitKeymap = {
        63232: 38,
        63233: 40,
        63234: 37,
        63235: 39,
        63276: 33,
        63277: 34,
        25: 9
    }, 
	patterns = {
        HYPHEN: /(-[a-z])/i,
        ROOT_TAG: /body|html/i,
        CLASS_RE_TOKENS: /([\.\(\)\^\$\*\+\?\|\[\]\{\}])/g
    }, 
	reCache = {}, 
	listeners = [], 
	lastError = null, 
	CUSTOM_ATTRIBUTES = (!documentElement.hasAttribute) ? {
        'for': 'htmlFor',
        'class': 'className'
    } : {
        'htmlFor': 'for',
        'className': 'class'
    }, 
	nt = 'nodType', 
	_CLASS = 'class', 
	CLASS_NAME = 'className', 
	EMPTY = '', 
	SPACE = ' ', 
	C_START = '(?:^|\\s)', 
	C_END = '(?= |$)', 
	_G = 'g';
	
    return {
        version: 'v1.0.1 Beta',
        isArray: function(obj){
            return OP.toString.apply(obj) === OA;
        },
        isString: function(s){
            return typeof s === 'string';
        },
        isBoolean: function(b){
            return typeof b === 'boolean';
        },
        isFunction: function(fn){
            return OP.toString.apply(fn) === OF;
        },
        isNull: function(obj){
            return obj === null;
        },
        isNumber: function(num){
            return typeof num === 'number' && isFinite(num);
        },
        isObject: function(str){
            return (str && (typeof str === "object" || this.isFunction(str))) || false;
        },
        isUndefined: function(obj){
            return typeof obj === 'undefined';
        },
        isElement: function(obj){
            return obj && obj.nodeType === 1;
        },
        isHash: function(obj){
            return obj instanceof Hash;
        },
        isJSON: function(str){
            var json = str.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
            return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(json);
        },
        isXMLDoc: function(obj){
            return obj.documentElement && !obj.body || obj.tagName && obj.ownerDocument && !obj.ownerDocument.body;
        },
        hasOwnProperty: function(obj, prper){
            if (OP.hasOwnProperty) {
                return obj.hasOwnProperty(prper);
            }
            return !this.isUndefined(obj[prper]) && obj.constructor.prototype[prper] !== obj[prper];
        },
        trim: function(str){
            try {
                return str.replace(/^\s+/, '').replace(/\s+$/, '');
            } 
            catch (e) {
                return str;
            }
        },
        stripTags: function(){
            return str.replace(/<\/?[^>]+>/gi, '');
        },
        stripScripts: function(str){
            return str.replace(/<script[^>]*>([\\S\\s]*?)<\/script>/g, '');
        },
        encodeHTML: function(str){
            return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
        },
        decodeHTML: function(str){
            return str.replace(/&amp;/g, '&').replace(/&lt;/g, '<').replace(/&gt;/g, '>');
        },
        stringBuffer: function(){
            var a = [], i;
            for (i = 0; i < arguments.length; ++i) {
                a.push(arguments[i]);
            }
            return a.join('');
        },
        toCamel: function(property){
            var x = {};
            function G(y, z){
                return z.toUpperCase();
            }
            return x[property] || (x[property] = property.indexOf("-") === -1 ? property : property.replace(/-([a-z])/gi, G));
        },
        formatNumber: function(b, e){
            e = e || '';
            b += '';
            var d = b.split('.');
            var a = d[0];
            var c = d.length > 1 ? '.' + d[1] : '';
            var f = /(\d+)(\d{3})/;
            while (f.test(a)) {
                a = a.replace(f, '$1,$2');
            }
            return e + a + c;
        },
        unformatNumber: function(a){
            return a.replace(/([^0-9\.\-])/g, '') * 1;
        },
        keys: function(obj){
            var b = [];
            for (var p in obj) {
                b.push(p);
            }
            return b;
        },
        values: function(obj){
            var a = [];
            for (var p in obj) {
                a.push(obj[p]);
            }
            return a;
        },
        extend: function(sub, sup, override){
            if (!sup || !sub) {
                throw new Error('extend failed, please check that all dependencies are included.');
            }
            var F = function(){
            }, p;
            F.prototype = sup.prototype;
            sub.prototype = new F();
            sub.prototype.constructor = sub;
            sub.superclass = sup.prototype;
            if (sup.prototype.constructor === OP.constructor) {
                sup.prototype.constructor = sup;
            }
            if (override) {
                for (p in override) {
                    sub.prototype[p] = override[p];
                }
            }
        },
        augmentProto: function(sub, sup){
            if (!sub || !sup) {
                throw new Error('augment failed, please check that all dependencies are included.');
            }
            var d = sub.prototype, g = sup.prototype, b = arguments, c, h;
            if (b[2]) {
                for (c = 2; c < b.length; c += 1) {
                    d[b[c]] = g[b[c]];
                }
            }
            else {
                for (h in g) {
                    if (!d[h]) {
                        d[h] = g[h];
                    }
                }
            }
        },
        augmentObject: function(e, d){
            if (!d || !e) {
                throw new Error('augment failed, please check that all dependencies are included.');
            }
            var b = arguments, c, f;
            if (b[2]) {
                if (this.isString(b[2])) {
                    e[b[2]] = d[b[2]];
                }
                else {
                    for (c = 0; c < b[2].length; c += 1) {
                        e[b[2][c]] = d[b[2][c]];
                    }
                }
            }
            else {
                for (f in d) {
                    e[f] = d[f];
                }
            }
            return e;
        },
        clone: function(d, f){
            var e = function(){
            }, b, c = arguments;
            e.prototype = d;
            b = new e;
            if (f) {
                for (p in f) {
                    b[p] = f[p];
                }
            }
            return b;
        },
        cookie: {
            set: function(g, c, f, b){
                var e = new Date(), a = new Date();
                if (f == null || f == 0) {
                    f = 1;
                }
                a.setTime(e.getTime() + 3600000 * 24 * f);
                D.cookie = g + '=' + encodeURI(c) + ';expires=' + a.toGMTString() + ';domain=' + b + '; path=/';
            },
            get: function(e){
                var b = D.cookie, d = e + '=', c = b.indexOf('; ' + d), a = D.cookie.indexOf(';', c);
                if (c === -1) {
                    c = b.indexOf(d);
                    if (c != 0) {
                        return null;
                    }
                }
                else {
                    c += 2;
                }
                if (a === -1) {
                    a = b.length;
                }
                return decodeURI(b.substring(c + d.length, a));
            },
            del: function(b, a){
                if (this.get(b)) {
                    D.cookie = b + '=' + ((domain) ? '; domain=' + a : '') + '; expires=Thu, 01-Jan-70 00:00:01 GMT';
                }
            }
        },
        userAgent: function(){
            var C = {
                ie: 0,
                opera: 0,
                gecko: 0,
                webkit: 0,
                mobile: null,
                air: 0,
                caja: 0
            }, B = userAgent, A;
            if ((/KHTML/).test(B)) {
                C.webkit = 1;
            }
            A = B.match(/AppleWebKit\/([^\s]*)/);
            if (A && A[1]) {
                C.webkit = parseFloat(A[1]);
                if (/ Mobile\//.test(B)) {
                    C.mobile = 'Apple';
                }
                else {
                    A = B.match(/NokiaN[^\/]*/);
                    if (A) {
                        C.mobile = A[0];
                    }
                }
                A = B.match(/AdobeAIR\/([^\s]*)/);
                if (A) {
                    C.air = A[0];
                }
            }
            if (!C.webkit) {
                A = B.match(/Opera[\s\/]([^\s]*)/);
                if (A && A[1]) {
                    C.opera = parseFloat(A[1]);
                    A = B.match(/Opera Mini[^;]*/);
                    if (A) {
                        C.mobile = A[0];
                    }
                }
                else {
                    A = B.match(/MSIE\s([^;]*)/);
                    if (A && A[1]) {
                        C.ie = parseFloat(A[1]);
                    }
                    else {
                        A = B.match(/Gecko\/([^\s]*)/);
                        if (A) {
                            C.gecko = 1;
                            A = B.match(/rv:([^\s\)]*)/);
                            if (A && A[1]) {
                                C.gecko = parseFloat(A[1]);
                            }
                        }
                    }
                }
            }
            A = B.match(/Caja\/([^\s]*)/);
            if (A && A[1]) {
                C.caja = parseFloat(A[1]);
            }
            return C;
        }(),
        addListener: function(el, sType, fn, obj, overrideContext, bCapture){
            var oEl = null, context = null, wrappedFn = null;
            if (YAO.isString(el)) {
                oEl = YAO.getEl(el);
                el = oEl;
            }
            if (!el || !fn || !fn.call) {
                return false;
            }
            context = el;
            if (overrideContext) {
                if (overrideContext === true) {
                    context = obj;
                }
                else {
                    context = overrideContext;
                }
            }
            wrappedFn = function(e){
                return fn.call(context, YAO.getEvent(e, el), obj);
            };
            try {
                try {
                    el.addEventListener(sType, wrappedFn, bCapture);
                } 
                catch (e) {
                    try {
                        el.attachEvent('on' + sType, wrappedFn);
                    } 
                    catch (e) {
                        el['on' + sType] = wrappedFn;
                    }
                }
            } 
            catch (e) {
                lastError = e;
                YAO.removeListener(el, sType, wrappedFn, bCapture);
                return false;
            }
            if ('unload' != sType) {
                listeners[listeners.length] = [el, sType, fn, wrappedFn, bCapture];
            }
            return true;
        },
        on: function(el, sType, fn){
            return YAO.addListener(el, sType, fn, el, true, false);
        },
        removeListener: function(el, sType, fn, bCapture){
            try {
                if (window.removeEventListener) {
                    return function(el, sType, fn, bCapture){
                        el.removeEventListener(sType, fn, (bCapture));
                    };
                }
                else {
                    if (window.detachEvent) {
                        return function(el, sType, fn){
                            el.detachEvent("on" + sType, fn);
                        };
                    }
                    else {
                        return function(){
                        };
                    }
                }
            } 
            catch (e) {
                lastError = e;
                return false;
            }
            return true;
        },
        isMouseLeaveOrEnter: function(e, handler){
            if (e.type !== 'mouseout' && e.type !== 'mouseover') {
                return false;
            }
            var reltg = e.relatedTarget ? e.relatedTarget : (e.type === 'mouseout' ? e.toElement : e.fromElement);
            while (reltg && reltg !== handler) {
                reltg = reltg.parentNode;
            }
            return (reltg !== handler);
        },
        stopEvent: function(evt){
            this.stopPropagation(evt);
            this.preventDefault(evt);
        },
        stopPropagation: function(evt){
            if (evt.stopPropagation) {
                evt.stopPropagation();
            }
            else {
                evt.cancelBubble = true;
            }
        },
        preventDefault: function(evt){
            if (evt.preventDefault) {
                evt.preventDefault();
            }
            else {
                evt.returnValue = false;
            }
        },
        getEvent: function(e, boundEl){
            var ev = e || window.event;
            if (!ev) {
                var c = this.getEvent.caller;
                while (c) {
                    ev = c.arguments[0];
                    if (ev && Event == ev.constructor) {
                        break;
                    }
                    c = c.caller;
                }
            }
            return ev;
        },
        getCharCode: function(ev){
            var code = ev.keyCode || ev.charCode || 0;
            if (this.userAgent.webkit && (code in webkitKeymap)) {
                code = webkitKeymap[code];
            }
            return code;
        },
        _unload: function(e){
            var j, l;
            if (listeners) {
                for (j = listeners.length - 1; j > -1; j--) {
                    l = listeners[j];
                    if (l) {
                        this.removeListener(l[0], l[1], l[3], l[4]);
                    }
                }
                l = null;
            }
            this.removeListener(window, "unload", YAO._unload);
        },
        purge: function(d){
            var a = d.attributes, i, l, n;
            if (a) {
                l = a.length;
                for (i = 0; i < l; ++i) {
                    n = a[i].name;
                    if (typeof d[n] === 'function') {
                        d[n] = null;
                    }
                }
            }
            a = d.childNodes;
            if (a) {
                l = a.length;
                for (i = 0; i < l; i += 1) {
                    YAO.purge(d.childNodes[i]);
                }
            }
        },
        getEl: function(elem){
            var elemID, E, m, i, k, length, len;
            if (elem) {
                if (elem[nt] || elem.item) {
                    return elem;
                }
                if (this.isString(elem)) {
                    elemID = elem;
                    elem = D.getElementById(elem);
                    if (elem && elem.id === elemID) {
                        return elem;
                    }
                    else {
                        if (elem && elem.all) {
                            elem = null;
                            E = D.all[elemID];
                            for (i = 0, len = E.length; i < len; i += 1) {
                                if (E[i].id === elemID) {
                                    return E[i];
                                }
                            }
                        }
                    }
                    return elem;
                }
                else {
                    if (elem.DOM_EVENTS) {
                        elem = elem.get("element");
                    }
                    else {
                        if (this.isArray(elem)) {
                            m = [];
                            for (k = 0, length = elem.length; k < length; k += 1) {
                                m[m.length] = YAO.getEl(elem[k]);
                            }
                            return m;
                        }
                    }
                }
            }
            return null;
        },
        hasClass: function(el, className){
            var ret = false, current;
            if (el && className) {
                current = this.getAttribute(el, CLASS_NAME) || EMPTY;
                if (className.exec) {
                    ret = className.test(current);
                }
                else {
                    ret = className && (SPACE + current + SPACE).indexOf(SPACE + className + SPACE) > -1;
                }
            }
            else {
                throw new Error('hasClass called with invalid arguments');
            }
            return ret;
        },
        addClass: function(el, className){
            var ret = false, current;
            if (el && className) {
                current = this.getAttribute(el, CLASS_NAME) || EMPTY;
                if (!this.hasClass(el, className)) {
                    this.setAttribute(el, CLASS_NAME, this.trim(current + SPACE + className));
                    ret = true;
                }
            }
            else {
                throw new Error('addClass called with invalid arguments');
            }
            return ret;
        },
        removeClass: function(el, className){
            var ret = false, current, newClass, attr;
            if (el && className) {
                current = this.getAttribute(el, CLASS_NAME) || EMPTY;
                this.setAttribute(el, CLASS_NAME, current.replace(this.getClassRegex(className), EMPTY));
                newClass = this.getAttribute(el, CLASS_NAME);
                if (current !== newClass) {
                    this.setAttribute(el, CLASS_NAME, this.trim(newClass));
                    ret = true;
                    if (this.getAttribute(el, CLASS_NAME) === '') {
                        attr = (el.hasAttribute && el.hasAttribute(_CLASS)) ? _CLASS : CLASS_NAME;
                        el.removeAttribute(attr);
                    }
                }
            }
            else {
                throw new Error('removeClass called with invalid arguments');
            }
            return ret;
        },
        replaceClass: function(el, classObj){
            var className, from, to, ret = false, current;
            if (el && classObj) {
                from = classObj.from;
                to = classObj.to;
                if (!to) {
                    ret = false;
                }
                else {
                    if (!from) {
                        ret = this.addClass(el, classObj.to);
                    }
                    else {
                        if (from !== to) {
                            current = this.getAttribute(el, CLASS_NAME) || EMPTY;
                            className = (SPACE + current.replace(this.getClassRegex(from), SPACE + to)).split(this.getClassRegex(to));
                            className.splice(1, 0, SPACE + to);
                            this.setAttribute(el, CLASS_NAME, this.trim(className.join(EMPTY)));
                            ret = true;
                        }
                    }
                }
            }
            else {
                throw new Error('replaceClass called with invalid arguments');
            }
            return ret;
        },
        setAttribute: function(el, attr, val){
            attr = CUSTOM_ATTRIBUTES[attr] || attr;
            el.setAttribute(attr, val);
        },
        getAttribute: function(el, attr){
            attr = CUSTOM_ATTRIBUTES[attr] || attr;
            return el.getAttribute(attr);
        },
        getClassRegex: function(className){
            var re;
            if (className !== undefined) {
                if (className.exec) {
                    re = className;
                }
                else {
                    re = reCache[className];
                    if (!re) {
                        className = className.replace(patterns.CLASS_RE_TOKENS, '\\$1');
                        re = reCache[className] = new RegExp(C_START + className + C_END, _G);
                    }
                }
            }
            return re;
        },
        getElByClassName: function(className, tag, rootTag){
            var elems = [], i, tempCnt = this.getEl(rootTag).getElementsByTagName(tag), len = tempCnt.length;
            for (i = 0; i < len; ++i) {
                if (this.hasClass(tempCnt[i], className)) {
                    elems.push(tempCnt[i]);
                }
            }
            if (elems.length < 1) {
                return false;
            }
            else {
                return elems;
            }
        },
        getStyle: function(el, property){
            if (defaultView && defaultView.getComputedStyle) {
                var value = null;
                if (property === 'float') {
                    property = 'cssFloat';
                }
                var computed = defaultView.getComputedStyle(el, '');
                if (computed) {
                    value = computed[this.toCamel(property)];
                }
                return el.style[property] || value;
            }
            else {
                if (documentElement.currentStyle && this.userAgent.ie) {
                    switch (this.toCamel(property)) {
                        case 'opacity':
                            var val = 100;
                            try {
                                val = el.filters['DXImageTransform.Microsoft.Alpha'].opacity;
                            } 
                            catch (e) {
                                try {
                                    val = el.filters('alpha').opacity;
                                } 
                                catch (e) {
                                }
                            }
                            return val / 100;
                            break;
                        case 'float':
                            property = 'styleFloat';
                        default:
                            var value = el.currentStyle ? el.currentStyle[property] : null;
                            return (el.style[property] || value);
                    }
                }
                else {
                    return el.style[property];
                }
            }
        },
        setStyle: function(el, property, val){
            if (this.userAgent.ie) {
                switch (property) {
                    case 'opacity':
                        if (this.isString(el.style.filter)) {
                            el.style.filter = 'alpha(opacity=' + val * 100 + ')';
                            if (!el.currentStyle || !el.currentStyle.hasLayout) {
                                el.style.zoom = 1;
                            }
                        }
                        break;
                    case 'float':
                        property = 'styleFloat';
                    default:
                        el.style[property] = val;
                }
            }
            else {
                if (property === 'float') {
                    property = 'cssFloat';
                }
                el.style[property] = val;
            }
        },
        setStyles: function(el, propertys){
            var p;
            for (p in propertys) {
                this.setStyle(el, p, propertys[p]);
            }
            return el;
        },
        getElementsBy: function(method, tag, root){
            tag = tag || "*";
            var m = [];
            if (root) {
                root = this.getEl(root);
                if (!root) {
                    return m;
                }
            }
            else {
                root = D;
            }
            var oElem = root.getElementsByTagName(tag);
            if (!oElem.length && (tag === "*" && root.all)) {
                oElem = root.all;
            }
            for (var n = 0, j = oElem.length; n < j; ++n) {
                if (method(oElem[n])) {
                    m[m.length] = oElem[n];
                }
            }
            return m;
        },
        getDocumentWidth: function(){
            var k = this.getScrollWidth();
            var j = Math.max(k, this.getViewportWidth());
            return j;
        },
        getDocumentHeight: function(){
            var k = this.getScrollHeight();
            var j = Math.max(k, this.getViewportHeight());
            return j;
        },
        getScrollWidth: function(){
            var j = (D.compatMode === "CSS1Compat") ? body.scrollWidth : D.Element.scrollWidth;
            return j;
        },
        getScrollHeight: function(){
            var j = (D.compatMode === "CSS1Compat") ? body.scrollHeight : documentElement.scrollHeight;
            return j;
        },
        getXScroll: function(){
            var j = self.pageXOffset || documentElement.scrollLeft || body.scrollLeft;
            return j;
        },
        getYScroll: function(){
            var j = self.pageYOffset || documentElement.scrollTop || body.scrollTop;
            return j;
        },
        getViewportWidth: function(){
            var j = self.innerWidth, k = D.compatMode;
            if (k || c) {
                j = (k === "CSS1Compat") ? documentElement.clientWidth : body.clientWidth;
            }
            return j;
        },
        getViewportHeight: function(){
            var j = self.innerHeight, k = D.compatMode;
            if ((k || c) && !this.userAgent.opera) {
                j = (k === "CSS1Compat") ? documentElement.clientHeight : body.clientHeight;
            }
            return j;
        },
        getPageXY: function(el){
            var x = this.getPageX(el), y = this.getPageY(el);
            return [x, y];
        },
        getPageX: function(el){
            var box = null, parentNode = null, left = 0;
            if (el.getBoundingClientRect) {
                box = el.getBoundingClientRect();
                left = box.left + Math.max(D.documentElement.scrollLeft, D.body.scrollLeft);
            }
            else {
                left = el.offsetLeft;
                parentNode = el.offsetParent;
                if (parentNode != el) {
                    while (parentNode) {
                        left += parentNode.offsetLeft;
                        parentNode = parentNode.offsetParent;
                    }
                }
            }
            return left;
        },
        getPageY: function(el){
            var box = null, parentNode = null, top = 0;
            if (el.getBoundingClientRect) {
                box = el.getBoundingClientRect();
                top = box.top + Math.max(D.documentElement.scrollTop, D.body.scrollTop);
            }
            else {
                top = el.offsetTop;
                parentNode = el.offsetParent;
                if (parentNode != el) {
                    while (parentNode) {
                        top += parentNode.offsetTop;
                        parentNode = parentNode.offsetParent;
                    }
                }
            }
            return top;
        },
        removeChildren: function(j){
            var parent = null;
            if (!(parent = this.getEl(j))) {
                return false;
            }
            while (j.firstChild) {
                j.firstChild.parentNode.removeChild(j.firstChild);
            }
            return j;
        },
        prependChild: function(k, j){
            if (!(k = this.getEl(k)) || !(j = this.getEl(j))) {
                return false;
            }
            if (k.firstChild) {
                k.insertBefore(j, k.firstChild);
            }
            else {
                k.appendChild(j);
            }
            return k;
        },
        insertBefore: function(Y, G){
            Y = this.getEl(Y);
            G = this.getEl(G);
            if (!Y || !G || !G.parentNode) {
                return null;
            }
            return G.parentNode.insertBefore(Y, G);
        },
        insertAfter: function(l, j){
            var k = j.parentNode;
            if (k.lastChild === j) {
                k.appendChild(l);
            }
            else {
                k.insertBefore(l, j.nextSibling);
            }
        },
        setOpacity: function(el, val){
            this.setStyle(el, 'opacity', val);
        },
        Builder: function(){
            var nidx = 0, NODEMAP = {
                AREA: 'map',
                CAPTION: 'table',
                COL: 'table',
                COLGROUP: 'table',
                LEGEND: 'fieldset',
                OPTGROUP: 'select',
                OPTION: 'select',
                PARAM: 'object',
                TBODY: 'table',
                TD: 'table',
                TFOOT: 'table',
                TH: 'table',
                THEAD: 'table',
                TR: 'table'
            }, ATTR_MAP = {
                'className': 'class',
                'htmlFor': 'for',
                'readOnly': 'readonly',
                'maxLength': 'maxlength',
                'cellSpacing': 'cellspacing'
            }, EMPTY_TAG = /^(?:BR|FRAME|HR|IMG|INPUT|LINK|META|RANGE|SPACER|WBR|AREA|PARAM|COL)$/i;
            return {
                css: function(url, cssId, charset){
                    var c = charset || 'utf-8', link = null;
                    link = this.node('link', {
                        'id': cssId || ('link-' + (nidx++)),
                        'type': 'text/css',
                        'charset': c,
                        'rel': 'stylesheet',
                        'href': url
                    });
                    head.appendChild(link);
                    return link;
                },
                script: function(url, scriptId, charset){
                    var c = charset || 'utf-8';
                    return body.appendChild(this.node('script', {
                        'id': scriptId || ('script-' + (nidx++)),
                        'type': 'text/javascript',
                        'charset': c,
                        'src': url
                    }));
                },
                node: function(tag, attr, children){
                    tag = tag.toUpperCase();
                    var parentTag = NODEMAP[tag] || 'div', parentElement = D.createElement(parentTag), elem = null;
                    try {
                        if (EMPTY_TAG.test(tag)) {
                        }
                        else {
                            parentElement.innerHTML = "<" + tag + "></" + tag + ">";
                        }
                    } 
                    catch (e) {
                    }
                    elem = parentElement.firstChild;
                    if (elem && (elem.tagName.toUpperCase() != tag)) {
                        elem = elem.getElementsByTagName(tag)[0];
                    }
                    if (!elem) {
                        if (YAO.isString(tag)) {
                            elem = D.createElement(tag);
                        }
                    }
                    if (!elem) {
                        return;
                    }
                    else {
                        if (attr) {
                            this.attributes(elem, attr);
                        }
                        if (children) {
                            this.child(elem, children);
                        }
                        return elem;
                    }
                },
                text: function(str){
                    return D.createTextNode(str);
                },
                child: function(parent, child){
                    if (child.tagName) {
                        parent.appendChild(child);
                        return false;
                    }
                    if (YAO.isArray(child)) {
                        var i, length = child.length;
                        for (i = 0; i < length; i += 1) {
                            if (child[i].tagName) {
                                parent.appendChild(child[i]);
                            }
                            else {
                                if (YAO.isString(child[i])) {
                                    parent.appendChild(this.text(child[i]));
                                }
                            }
                        }
                    }
                    else {
                        if (YAO.isString(child)) {
                            parent.appendChild(this.text(child));
                        }
                    }
                },
                attributes: function(elem, attr){
                    var attrName = '', i;
                    for (i in attr) {
                        if (attr[i] && YAO.hasOwnProperty(attr, i)) {
                            attrName = i in ATTR_MAP ? ATTR_MAP[i] : i;
                            if (attrName === 'class') {
                                elem.className = attr[i];
                            }
                            else {
                                elem.setAttribute(attrName, attr[i]);
                            }
                        }
                    }
                    return elem;
                }
            }
        }(),
        loadScript: function(url, callback){
            var script = this.Builder.script(url);
            if (script.readyState) {
                script.onreadystatechange = function(){
                    if (script.readyState === "loaded" || script.readyState === "complete") {
                        script.onreadystatechange = null;
                        callback();
                    }
                };
            }
            else {
                script.onload = function(){
                    callback();
                };
            }
        },
        isAncestor: function(Y, x){
            var G = false;
            Y = this.getEl(Y);
            x = this.getEl(x);
            if ((Y && x) && (Y[nt] && x[nt])) {
                if (Y.contains && Y !== x) {
                    G = Y.contains(x);
                }
                else {
                    if (Y.compareDocumentPosition) {
                        G = !!(Y.compareDocumentPosition(x) & 16);
                    }
                }
            }
            else {
                return false;
            }
            return G;
        },
        batch: function(el, method, o, override){
            var id = el, that = this;
            el = that.getEl(el);
            var scope = (override) ? o : window;
            if (!el || el.tagName || !el.length) {
                if (!el) {
                    return false;
                }
                return method.call(scope, el, o);
            }
            var collection = [];
            for (var i = 0, len = el.length; i < len; ++i) {
                if (!el[i]) {
                    id = el[i];
                }
                collection[collection.length] = method.call(scope, el[i], o);
            }
            return collection;
        },
        fadeUp: function(elem){
            if (elem) {
                var level = 0, that = this, fade = function(){
                    var timer = null;
                    level += 0.05;
                    if (timer) {
                        clearTimeout(timer);
                        timer = null;
                    }
                    if (level > 1) {
                        that.setOpacity(elem, 1);
                        return false;
                    }
                    else {
                        that.setOpacity(elem, level);
                    }
                    timer = setTimeout(fade, 50);
                };
                fade();
            }
        },
        zebra: function(){
            var j, length = arguments.length, that = this;
            for (j = 0; j < length; ++j) {
                (function(config){
                    var root = that.getEl(config.rootTag) || (config.root || null), rows = root.getElementsByTagName(config.rowTag) || (config.rows || null), i, len = rows.length, lastClass = [];
                    if (root && rows && len > 1) {
                        for (var i = 0; i < len; ++i) {
                            rows[i].className = i % 2 === 0 ? 'even' : 'odd';
                            lastClass[i] = rows[i].className;
                            that.on(rows[i], 'mouseover', function(index){
                                return function(){
                                    that.replaceClass(this, lastClass[index], 'hover');
                                }
                            }(i), rows[i], true);
                            that.on(rows[i], 'mouseout', function(index){
                                return function(){
                                    that.replaceClass(this, 'hover', lastClass[index]);
                                }
                            }(i), rows[i], true);
                        }
                    }
                    else {
                        return false;
                    }
                })(arguments[j]);
            }
        },
        moveElement: function(element, finalX, finalY, speed, callback){
            var elem = this.isString(element) ? this.getEl(element) : element, style = null, xpos = 0, ypos = 0, dist = 0, that = this;
            if (elem) {
                if (elem.movement) {
                    clearTimeout(elem.movement);
                }
                if (!this.getStyle(elem, 'left')) {
                    this.setStyle(elem, 'left', 0);
                }
                if (!this.getStyle(elem, 'top')) {
                    this.setStyle(elem, 'top', 0);
                }
                xpos = parseInt(this.getStyle(elem, 'left'), 10);
                ypos = parseInt(this.getStyle(elem, 'top'), 10);
                if (xpos === finalX && ypos === finalY) {
                    if (callback) {
                        callback();
                        return true;
                    }
                    else {
                        return true;
                    }
                }
                if (xpos < finalX) {
                    dist = Math.ceil((finalX - xpos) / 10);
                    xpos += dist;
                }
                else {
                    if (xpos > finalX) {
                        dist = Math.ceil((xpos - finalX) / 10);
                        xpos -= dist;
                    }
                }
                if (ypos < finalY) {
                    dist = Math.ceil((finalY - ypos) / 10);
                    ypos += dist;
                }
                else {
                    if (ypos > finalY) {
                        dist = Math.ceil((ypos - finalY) / 10);
                        ypos -= dist;
                    }
                }
                this.setStyle(elem, 'left', (xpos + 'px'));
                this.setStyle(elem, 'top', (ypos + 'px'));
                elem.movement = setTimeout(function(){
                    that.moveElement(element, finalX, finalY, speed, callback);
                }, speed);
            }
        },
        fixPosition: function(elem, pos, elemWidth, elemHeight, isScroll){
            var IE6 = this.userAgent.ie === 6 ? true : false, left = 0, top = 0, position = pos.toUpperCase(), documentWidth = this.getDocumentWidth(), documentHeight = this.getDocumentHeight(), viewportWidth = this.getViewportWidth(), viewportHeight = this.getViewportHeight(), xScroll = this.getXScroll(), yScroll = this.getYScroll();
            if (position === 'RIGHT') {
                left = xScroll + (viewportWidth - elemWidth);
                if (IE6) {
                    top = yScroll + (viewportHeight - elemHeight);
                }
                else {
                    top = viewportHeight - elemHeight;
                }
                if (elemWidth > viewportWidth) {
                    left = 0;
                    top = 0;
                }
            }
            else {
                if (position === 'LEFT') {
                    left = 0;
                    if (IE6) {
                        top = yScroll + (viewportHeight - elemHeight);
                    }
                    else {
                        top = viewportHeight - elemHeight;
                    }
                    if (elemHeight > viewportHeight) {
                        top = 0;
                    }
                }
                else {
                    if (position === 'CENTER') {
                        left = xScroll + ((viewportWidth - elemWidth) / 2);
                        if (IE6) {
                            top = yScroll + ((viewportHeight - elemHeight) / 2);
                        }
                        else {
                            top = (viewportHeight - elemHeight) / 2;
                        }
                        if (elemWidth > viewportWidth) {
                            if ((elemWidth < documentWidth) && ((elemWidth + xScroll) < documentWidth)) {
                                left = xScroll;
                                top = yScroll;
                            }
                            else {
                                left = documentWidth - elemWidth;
                                top = documentHeight - elemHeight;
                            }
                        }
                        else {
                            if (elemWidth > documentWidth) {
                                left = 0;
                                top = 0;
                            }
                        }
                    }
                }
            }
            if (isScroll && position !== 'CENTER') {
                this.setStyles(elem, {
                    margin: '0',
                    left: left + 'px',
                    top: (top + elemHeight) + 'px'
                });
            }
            else {
                this.setStyles(elem, {
                    margin: '0',
                    left: left + 'px',
                    top: top + 'px'
                });
            }
            if (!IE6) {
                this.setStyle(elem, 'position', 'fixed');
            }
        },
        ajaxRequest: function(config){
            var oXhr, method = config.method ? config.method.toUpperCase() : 'GET', url = config.url || '', fn = config.fn || null, postData = config.data || null, elem = config.id ? YAO.getEl(config.id) : (config.element || null), load = config.loadFn ? config.loadFn : (config.loading || ' 正在获取数据，请稍后...'), that = this;
            if (!url) {
                return;
            }
            if (window.XMLHttpRequest) {
                oXhr = new XMLHttpRequest();
            }
            else {
                if (window.ActiveXObject) {
                    oXhr = new ActiveXObject("Microsoft.XMLHTTP");
                }
            }
            if (oXhr) {
                try {
                    oXhr.open(method, url, true);
                    oXhr.onreadystatechange = function(){
                        if (oXhr.readyState !== 4) {
                            return false
                        }
                        if (oXhr.readyState === 4) {
                            if (oXhr.status === 200 || location.href.indexOf('http') === -1) {
                                if (fn) {
                                    fn.success(oXhr);
                                }
                                else {
                                    elem.innerHTML = oXhr.responseText;
                                }
                            }
                            else {
                                if (fn) {
                                    fn.failure(oXhr.status);
                                }
                                else {
                                    if (that.isFunction(load)) {
                                        load();
                                    }
                                    else {
                                        elem.innerHTML = load;
                                    }
                                }
                            }
                        }
                    };
                    oXhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                    if (postData) {
                        oXhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
                    }
                    oXhr.send(postData);
                } 
                catch (e) {
                    throw new Error(e);
                    return false;
                }
            }
            else {
                throw new Error("Your browser does not support XMLHTTP.");
                return false;
            }
        },
        JSON: function(){
            function f(n){
                return n < 10 ? '0' + n : n;
            }
            Date.prototype.toJSON = function(){
                return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate()) + 'T' + f(this.getUTCHours()) + ':' + f(this.getUTCMinutes()) + ':' + f(this.getUTCSeconds()) + 'Z';
            };
            function stringify(value, whitelist){
                var a, i, k, l, r = /["\\\x00-\x1f\x7f-\x9f]/g, v, that = this;
                switch (typeof value) {
                    case 'string':
                        return r.test(value) ? '"' + value.replace(r, function(a){
                            var c = specialChar[a];
                            if (c) {
                                return c;
                            }
                            c = a.charCodeAt();
                            return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
                        }) + '"' : '"' + value + '"';
                    case 'number':
                        return isFinite(value) ? String(value) : 'null';
                    case 'boolean':
                    case 'null':
                        return String(value);
                    case 'object':
                        if (!value) {
                            return 'null';
                        }
                        if (that.isFunction(value.toJSON)) {
                            return stringify(value.toJSON());
                        }
                        a = [];
                        if (that.isNumber(value.length) && !(value.propertyIsEnumerable('length'))) {
                            l = value.length;
                            for (i = 0; i < l; i += 1) {
                                a.push(stringify(value[i], whitelist) || 'null');
                            }
                            return '[' + a.join(',') + ']';
                        }
                        if (whitelist) {
                            l = whitelist.length;
                            for (i = 0; i < l; i += 1) {
                                k = whitelist[i];
                                if (that.isString(k)) {
                                    v = stringify(value[k], whitelist);
                                    if (v) {
                                        a.push(stringify(k) + ':' + v);
                                    }
                                }
                            }
                        }
                        else {
                            for (k in value) {
                                if (that.isString(k)) {
                                    v = stringify(value[k], whitelist);
                                    if (v) {
                                        a.push(stringify(k) + ':' + v);
                                    }
                                }
                            }
                        }
                        return '{' + a.join(',') + '}';
                }
            }
            return {
                stringify: stringify,
                parse: function(text, filter){
                    var j;
                    function walk(k, v){
                        var i, n;
                        if (v && that.isObject(v)) {
                            for (i in v) {
                                if (OP.hasOwnProperty.apply(v, [i])) {
                                    n = walk(i, v[i]);
                                    if (n !== undefined) {
                                        v[i] = n;
                                    }
                                    else {
                                        delete v[i];
                                    }
                                }
                            }
                        }
                        return filter(k, v);
                    }
                    if (/^[\],:{}\s]*$/.test(text.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
                        j = eval('(' + text + ')');
                        return that.isFunction(filter) ? walk('', j) : j;
                    }
                    throw new SyntaxError('parseJSON');
                }
            };
        }()
    };
    YAO.on(window, "unload", YAO._unload);
}();