/*
 * Copyright (C) 2009 ZYG
 */
(function($){
    if (typeof cy == 'undefined') {
        cy = {};
        cy.ume = {};
    }
    
    /* extend */
    (function(){
        cy.extend = function(target, source){
            if (source == null) return;
            var tos = typeof source;
            if (tos == 'undefinded') {
                return null;
            } else if (tos == 'number' || tos == 'string' || tos == 'boolean' || tos == 'function') {
                target = source;
            } else { // object
                if (source.constructor == Array) { // Array
                    target = source;
                } else {
                    for (var item in source) {
                        target[item] = cy.extend(target[item], source[item]);
                    }
                }
            }
            
            return target;
        }
    })();
    
    /* effect */
    (function(){
        if (typeof cy.effect == 'undefined') {
            cy.effect = {};
        }
        
        /* tween */
        (function(){
            cy.effect.Tween = {
                Linear: function(t, b, c, d){
                    return c * t / d + b;
                },
                Quad: {
                    easeIn: function(t, b, c, d){
                        return c * (t /= d) * t + b;
                    },
                    easeOut: function(t, b, c, d){
                        return -c * (t /= d) * (t - 2) + b;
                    },
                    easeInOut: function(t, b, c, d){
                        if ((t /= d / 2) < 1) return c / 2 * t * t + b;
                        return -c / 2 * ((--t) * (t - 2) - 1) + b;
                    }
                },
                Cubic: {
                    easeIn: function(t, b, c, d){
                        return c * (t /= d) * t * t + b;
                    },
                    easeOut: function(t, b, c, d){
                        return c * ((t = t / d - 1) * t * t + 1) + b;
                    },
                    easeInOut: function(t, b, c, d){
                        if ((t /= d / 2) < 1) return c / 2 * t * t * t + b;
                        return c / 2 * ((t -= 2) * t * t + 2) + b;
                    }
                },
                Quart: {
                    easeIn: function(t, b, c, d){
                        return c * (t /= d) * t * t * t + b;
                    },
                    easeOut: function(t, b, c, d){
                        return -c * ((t = t / d - 1) * t * t * t - 1) + b;
                    },
                    easeInOut: function(t, b, c, d){
                        if ((t /= d / 2) < 1) return c / 2 * t * t * t * t + b;
                        return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
                    }
                },
                Quint: {
                    easeIn: function(t, b, c, d){
                        return c * (t /= d) * t * t * t * t + b;
                    },
                    easeOut: function(t, b, c, d){
                        return c * ((t = t / d - 1) * t * t * t * t + 1) + b;
                    },
                    easeInOut: function(t, b, c, d){
                        if ((t /= d / 2) < 1) return c / 2 * t * t * t * t * t + b;
                        return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
                    }
                },
                Sine: {
                    easeIn: function(t, b, c, d){
                        return -c * Math.cos(t / d * (Math.PI / 2)) + c + b;
                    },
                    easeOut: function(t, b, c, d){
                        return c * Math.sin(t / d * (Math.PI / 2)) + b;
                    },
                    easeInOut: function(t, b, c, d){
                        return -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b;
                    }
                },
                Expo: {
                    easeIn: function(t, b, c, d){
                        return (t == 0) ? b : c * Math.pow(2, 10 * (t / d - 1)) + b;
                    },
                    easeOut: function(t, b, c, d){
                        return (t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b;
                    },
                    easeInOut: function(t, b, c, d){
                        if (t == 0) return b;
                        if (t == d) return b + c;
                        if ((t /= d / 2) < 1) return c / 2 * Math.pow(2, 10 * (t - 1)) + b;
                        return c / 2 * (-Math.pow(2, -10 * --t) + 2) + b;
                    }
                },
                Circ: {
                    easeIn: function(t, b, c, d){
                        return -c * (Math.sqrt(1 - (t /= d) * t) - 1) + b;
                    },
                    easeOut: function(t, b, c, d){
                        return c * Math.sqrt(1 - (t = t / d - 1) * t) + b;
                    },
                    easeInOut: function(t, b, c, d){
                        if ((t /= d / 2) < 1) return -c / 2 * (Math.sqrt(1 - t * t) - 1) + b;
                        return c / 2 * (Math.sqrt(1 - (t -= 2) * t) + 1) + b;
                    }
                },
                Elastic: {
                    easeIn: function(t, b, c, d, a, p){
                        if (t == 0) return b;
                        if ((t /= d) == 1) return b + c;
                        if (!p) p = d * 0.3;
                        if (!a || a < Math.abs(c)) {
                            a = c;
                            var s = p / 4;
                        } else var s = p / (2 * Math.PI) * Math.asin(c / a);
                        return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
                    },
                    easeOut: function(t, b, c, d, a, p){
                        if (t == 0) return b;
                        if ((t /= d) == 1) return b + c;
                        if (!p) p = d * 0.3;
                        if (!a || a < Math.abs(c)) {
                            a = c;
                            var s = p / 4;
                        } else var s = p / (2 * Math.PI) * Math.asin(c / a);
                        return (a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b);
                    },
                    easeInOut: function(t, b, c, d, a, p){
                        if (t == 0) return b;
                        if ((t /= d / 2) == 2) return b + c;
                        if (!p) p = d * (0.3 * 1.5);
                        if (!a || a < Math.abs(c)) {
                            a = c;
                            var s = p / 4;
                        } else var s = p / (2 * Math.PI) * Math.asin(c / a);
                        if (t < 1) return -0.5 * (a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
                        return a * Math.pow(2, -10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p) * 0.5 + c + b;
                    }
                },
                Back: {
                    easeIn: function(t, b, c, d, s){
                        if (s == undefined) s = 1.70158;
                        return c * (t /= d) * t * ((s + 1) * t - s) + b;
                    },
                    easeOut: function(t, b, c, d, s){
                        if (s == undefined) s = 1.70158;
                        return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
                    },
                    easeInOut: function(t, b, c, d, s){
                        if (s == undefined) s = 1.70158;
                        if ((t /= d / 2) < 1) return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
                        return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
                    }
                },
                Bounce: {
                    easeIn: function(t, b, c, d){
                        return c - Tween.Bounce.easeOut(d - t, 0, c, d) + b;
                    },
                    easeOut: function(t, b, c, d){
                        if ((t /= d) < (1 / 2.75)) {
                            return c * (7.5625 * t * t) + b;
                        } else if (t < (2 / 2.75)) {
                            return c * (7.5625 * (t -= (1.5 / 2.75)) * t + 0.75) + b;
                        } else if (t < (2.5 / 2.75)) {
                            return c * (7.5625 * (t -= (2.25 / 2.75)) * t + 0.9375) + b;
                        } else {
                            return c * (7.5625 * (t -= (2.625 / 2.75)) * t + 0.984375) + b;
                        }
                    },
                    easeInOut: function(t, b, c, d){
                        if (t < d / 2) return Tween.Bounce.easeIn(t * 2, 0, c, d) * 0.5 + b;
                        else                             
                            return Tween.Bounce.easeOut(t * 2 - d, 0, c, d) * 0.5 + c * 0.5 + b;
                    }
                }
            };
        })();
        
        /* highlight */
        (function(){
            cy.effect.highlight = function(id, effect){
                if (id == null || typeof id != 'string' || id == '') {
                    return;
                }
                if (effect == null || typeof effect != 'function') {
                    effect = cy.effect.Tween.Sine.easeInOut;
                }
                
                function init(){
                    var tar = $("#" + id);
                    if (tar.length == 0) {
                        return;
                    }
                    
                    switch (tar[0].tagName) {
                        case "IMG":
                            _initImg(tar);
                            break;
                        default:
                            break;
                    }
                }
                init();
                
                function _initImg(tar){
                    var pos = tar.offset();
                    var size = {
                        width: tar.width(),
                        height: tar.height()
                    };
                    
                    var html = "<div style='position: absolute; background-color: #ffffff; left: " +
                    pos.left +
                    "px; top: " +
                    pos.top +
                    "px; width: " +
                    size.width +
                    "px; height: " +
                    size.height +
                    "px; z-index: " +
                    cy.ui.zIndex.getLatest() +
                    ";'></div>";
                    
                    var divEffect = $(html).appendTo("body");
                    
                    var b = 0.3, c = 0.7, d = 20, t = 0;
                    var timer;
                    function executeEffect(){
                        t++;
                        var co = effect(t, b, c, d);
                        
                        divEffect.css("opacity", co);
                        if (t > d) {
                            clearTimeout(timer);
                            divEffect.remove();
                        } else {
                            timer = setTimeout(executeEffect, 10);
                        }
                    }
                    executeEffect();
                }
                
                return false;
            }
        })();
    })();
    
    /* cy.ui */
    (function(){
        if (typeof cy.ui == 'undefined') {
            cy.ui = {};
        }
        
        if (typeof cy.ume.ui == 'undefined') {
            cy.ume.ui = {};
        }
        
        /* z-index */
        (function(){
            cy.ui.zIndex = {};
            var _cy_ui_zIndex = 1000;
            
            cy.ui.zIndex.reset = function(){
                _cy_ui_zIndex = 1000;
            };
            cy.ui.zIndex.getLatest = function(){
                return ++_cy_ui_zIndex;
            };
        })();
        
        /* screen */
        (function(){
            cy.ui.screen = {};
            
            /*
             * get page fit size.
             */
            cy.ui.screen.getFitSize = function(){
                var body = $("body");
                var bodyW = body.outerWidth(true);
                var bodyH = body.outerHeight(true);
                
                var win = $(window);
                var winW = win.width();
                var winH = win.height();
                
                var doc = $(document);
                var docW = doc.width();
                var docH = doc.height();
                
                var maskW = (bodyW > winW) ? bodyW : winW;
                var maskH = (bodyH > winH) ? (bodyH > docH ? bodyH : docH) : (winH > docH ? winH : docH);
                
                return {
                    width: maskW,
                    height: maskH
                }
            }
            
            cy.ui.screen.getScrollPos = function(){
                var win = $(window);
                return {
                    left: win.scrollLeft(),
                    top: win.scrollTop()
                }
            }
            
            cy.ui.screen.getWinCenterPos = function(size){
                /*
                 * size: size of div that to be centered in a format {width: 100, height: 100}
                 * return: left-top pos.
                 */
                if (size == null || !size.width || !size.height) {
                    return {
                        left: 0,
                        top: 0
                    };
                }
                
                var pos = {
                    left: 0,
                    top: 0
                };
                var posP = {
                    left: 0,
                    top: 0
                };
                
                var scrollPos = cy.ui.screen.getScrollPos();
                var win = $(window);
                var winW = win.width();
                var winH = win.height();
                
                if (size.width > winW) {
                    pos.left = scrollPos.left;
                } else {
                    pos.left = parseInt((winW - size.width) / 2, 10) + scrollPos.left;
                }
                
                if (size.height > winH) {
                    pos.top = scrollPos.top;
                } else {
                    pos.top = parseInt((winH - size.height) / 2, 10) + scrollPos.top;
                }
                
                if (parent && (parent !== self) && parent.cy && parent.cy.ui && parent.cy.ui.screen && parent.cy.ui.screen.getWinCenterPos) {
                    posP = parent.cy.ui.screen.getWinCenterPos(size);
                    pos.top = posP.top;
                    
                    if (parent.frameTop && !isNaN(parent.frameTop)) {
                        pos.top = pos.top - parent.frameTop;
                        if (pos.top < 0) {
                            pos.top = 0;
                        }
                    }
                }
                
                return pos;
            }
            
            cy.ui.screen.getCurrentViewBound = function(){
                /*
                 * Get current view bound
                 */
                var scrollPos = cy.ui.screen.getScrollPos();
                var win = $(window);
                var winW = win.width();
                var winH = win.height();
                
                return {
                    left: scrollPos.left,
                    top: scrollPos.top,
                    width: winW,
                    height: winH
                };
            }
        })();
        
        /* dragable */
        (function(){
            cy.ui.dragable = function(tarId, ctrlId, options){
                if (tarId == null || (typeof tarId != 'string') || (tarId == '')) {
                    return;
                }
                if (ctrlId == null || (typeof ctrlId != 'string') || (ctrlId == '')) {
                    ctrlId = tarId;
                }
                
                var settings = {
                    begin: null,
                    moving: null,
                    dropped: null
                }
                cy.extend(settings, options ||
                {});
                
                var _enabled = true;
                var _orgPos = {
                    left: 0,
                    top: 0
                }; // 原位置
				var _offset = {
					left: 0,
					top: 0
				}; // 偏移量
				var _tarPos = {
					left: 0,
					top: 0
				}; // 存储被拖动目标的位置,省得每次都去取offset
                var _moving = false;
                
                function init(){
                    var ctrl = $("#" + ctrlId);
                    var tar = $("#" + tarId);
                    
                    if (ctrl.length == 0 || tar.length == 0) return;
                    
                    var drop = function(e){
                        if (!_enabled) return;
                        
                        _moving = false;
                        _offset = {
							left: 0,
                            top: 0
						};
						_tarPos = {
							left: 0,
                            top: 0
						};
						_orgPos = {
                            left: 0,
                            top: 0
                        };
                        
                        if (settings.dropped) {
                            settings.dropped();
                        }
                        ctrl.css({
                            cursor: ''
                        });
                    }
                    
                    ctrl.mousedown(function(e){
                        if (!_enabled) return;
                        
                        _moving = true;
                        
                        $(this).css({
                            cursor: 'move'
                        });
						
						_orgPos = tar.offset();
						_tarPos.left = _orgPos.left;
						_tarPos.top = _orgPos.top;

						var ctrlOffset = $(this).offset();
                        var curPos = {
                            left: e.pageX,
                            top: e.pageY
                        };
                            
                        _offset = {
                            left: curPos.left - ctrlOffset.left,
                            top: curPos.top - ctrlOffset.top
                        };
                        
                        if (settings.begin) {
                            settings.begin();
                        }
                    }).mousemove(function(e){
                        if (_moving && _enabled) {
							var curPos = {
                            	left: e.pageX,
                            	top: e.pageY
                        	};
                            _tarPos = {
                                left: curPos.left - _offset.left,
                                top: curPos.top - _offset.top
                            }
							
							// 这里可以设置拖动的边界,默认为不超出左边与上边
							if (_tarPos.left < 0) {
								_tarPos.left = 0;
							}
							if (_tarPos.top < 0) {
								_tarPos.top = 0;
							}

                            tar.css(_tarPos);
                            
                            if (settings.moving) {
                                settings.moving();
                            }
                        }
                    });
					$(document).mouseup(drop);
                }
                init();
                
                function enable(){
                    _enabled = true;
                }
                
                function disable(){
                    _enabled = false;
                }
                
                return {
                    enable: enable,
                    disable: disable
                };
            }
        })();
        
        /* big iframe */
        (function(){
            cy.ui.bigiframe = function(targetId, options){
                if (typeof targetId !== 'string' || $.trim(targetId) === '') {
                    return null;
                }
                
                if ($.browser.msie && /6.0/.test(navigator.userAgent)) {
                    var s = cy.extend({
                        top: 'auto', // auto == .currentStyle.borderTopWidth
                        left: 'auto', // auto == .currentStyle.borderLeftWidth
                        width: 'auto', // auto == offsetWidth
                        height: 'auto', // auto == offsetHeight
                        opacity: true,
                        src: 'javascript:false;'
                    }, options ||
                    {});
                    
                    var prop = function(n){
                        return n && n.constructor == Number ? n + 'px' : n;
                    };
                    
                    var buildHtml = function(){
                        var html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="' + s.src + '"' +
                        'style="display:block;position:absolute;z-index:-1;' +
                        (s.opacity !== false ? 'filter:Alpha(Opacity=\'0\');' : '') +
                        'top:' +
                        (s.top == 'auto' ? 'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')' : prop(s.top)) +
                        ';' +
                        'left:' +
                        (s.left == 'auto' ? 'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')' : prop(s.left)) +
                        ';' +
                        'width:' +
                        (s.width == 'auto' ? 'expression(this.parentNode.offsetWidth+\'px\')' : prop(s.width)) +
                        ';' +
                        'height:' +
                        (s.height == 'auto' ? 'expression(this.parentNode.offsetHeight+\'px\')' : prop(s.height)) +
                        ';' +
                        '"/>';
                        
                        return html;
                    }
                    
                    var init = function(){
                        var html = buildHtml();
                        if ($('#' + targetId + '> iframe.bgiframe').length == 0) {
                            $("#" + targetId).prepend(html);
                        }
                    }
                    init();
                    
                    var validate = function(){
                        var html = buildHtml();
                        $('#' + targetId + '> iframe.bgiframe').remove();
                        $("#" + targetId).prepend(html);
                    }
                    
                    return {
                        validate: validate
                    };
                }
                
                return null;
            }
        })();
        
        /* menu */
        (function(){
            cy.ui.menu = function(id, options){
                var settings = {
                    id: '',
                    triggerId: '',
                    items: [{
                        name: '',
                        html: '',
                        clicked: function(/*trigger#id*/){
                        }
                    }]
                };
                if (options != null) {
                    cy.extend(settings, options);
                }
                settings.id = id;
                
                /*
                 * init menu
                 */
                var init = function(){
                    var menuHtml = "<div id='" + id + "' class='menu-box' style='left: -5000px; z-index: " + cy.ui.zIndex.getLatest() + ";'><ul class='menu-list'>";
                    for (var i = 0; i < settings.items.length; i++) {
                        menuHtml += "<li class='menu-list-item' id='" + id + "-item-" + settings.items[i].name + "'><a href='javascript:;' class='menu-item'>";
                        menuHtml += settings.items[i].html;
                        menuHtml += "</a></li>"
                    }
                    menuHtml += "</ul></div>";
                    
                    $(menuHtml).find("a").each(function(index, ele){
                        $(this).click(function(e){
                            settings.items[index].clicked(settings.triggerId);
                            hide();
                        })
                    }).end().appendTo("body");
                };
                init();
                
                /*
                 * offset: {left:Int, top:Int} - required
                 */
                function show(offset, triggerId){
                    $("#" + settings.id).css({
                        left: offset.left + "px",
                        top: offset.top + "px"
                    });
                    settings.triggerId = triggerId;
                }
                
                function hide(){
                    $("#" + settings.id).css({
                        left: "-5000px",
                        top: "0px"
                    });
                    settings.triggerId = '';
                }
                
                return {
                    id: id,
                    show: show,
                    hide: hide
                }
            }
        })();
        
        /* tree */
        (function(){
            cy.ui.tree = function(id, options){
                if (id == null || $.trim(id) == '' || $("#" + id).length == 0) {
                    return null;
                }
                
                var settings = {
                    id: '',
                    itemClicked: null, /*function(jquery-li, event){},*/
                    itemDBClicked: null, /*function(jquery-li, event){},*/
                    menu: {
                        show: false,
                        context: false,
                        id: '',
                        items: [/* {name: '', html: '', clicked: function(){} }*/]
                    },
                    withCheck: false
                };
                if (options != null) {
                    cy.extend(settings, options);
                }
                settings.liCount = settings.ulCount = 0;
                settings.id = id;
                
                function buildMenu(){
                    if (settings.menu && settings.menu.show) {
                        settings.menu.id = id + "-menu";
                        var menu = cy.ui.menu(settings.menu.id, settings.menu);
                        $(document).click(function(){
                            menu.hide();
                        });
                        
                        return menu;
                    } else {
                        return null;
                    }
                }
                var menu = buildMenu();
                
                /*
                 * load events by passing the ul#id
                 */
                function initTree(id){
                    $("#" + id).addClass('unselectable').attr("unselectable", "on").find("li>div.tree-node").each(function(index, ele){
                        settings.liCount += 1;
                        settings.ulCount += 1;
                        
                        /* set li#id */
                        var liEle = $(this).parent(); // li
                        if (liEle.attr("id") == null || $.trim(liEle.attr("id")) == '') {
                            liEle.attr("id", settings.id + '-li-' + settings.liCount);
                        }
                        
                        /* set child ul nodes */
                        var ul = liEle.children("ul");
                        if (ul.length == 0) {
                            $("<ul id='" + settings.id + "-ul-" + settings.ulCount + "'></ul>").appendTo(liEle);
                        } else {
                            if (ul.attr("id") == null || $.trim(ul.attr("id")) == '') {
                                ul[0].id = settings.id + "-ul-" + settings.ulCount;
                            }
                        }
                        
                        /* bind tree node click event */
                        $(this).click(function(e){
                            liEle.toggleClass("open").toggleClass("close");
                        }).dblclick(function(e){
                            if (settings.itemDBClicked) {
                                settings.itemDBClicked(liEle, e);
                            }
                        });
                        
                        $(this).find(">span").attr("unselectable", "on").click(function(e){
                            $("#" + settings.id).find(".selected").removeClass("selected");
                            liEle.addClass("selected");
                            $(this).addClass("selected");
                            if (menu != null && !settings.menu.context) {
                                menu.show({
                                    left: e.pageX,
                                    top: e.pageY
                                }, liEle.attr("id"));
                                e.stopPropagation();
                            } else {
                                if (menu == null && settings.itemClicked) {
                                    settings.itemClicked(liEle, e);
                                }
                            }
                        }).bind("contextmenu", function(e){
                            if (menu != null && settings.menu.context) {
                                e.stopPropagation();
                                e.preventDefault();
                                
                                $("#" + settings.id).find(".selected").removeClass("selected");
                                liEle.addClass("selected");
                                $(this).addClass("selected");
                                
                                menu.show({
                                    left: e.pageX,
                                    top: e.pageY
                                }, liEle.attr("id"));
                                
                                return false;
                            } else {
                                return true;
                            }
                        });
                        
                        if (settings.withCheck) {
                            var cb = $(this).find(":checkbox");
                            
                            if (cb.length == 0) {
                                var html = "<input type='checkbox' id='" + settings.id + "-cb-" + settings.liCount + "' />";
                                cb = $(html);
                                cb.prependTo($(this));
                            }
                            
                            cb.click(function(e){
                                if ($(this).attr("checked")) {
                                    liEle.find(":checkbox").attr("checked", "checked");
                                } else {
                                    liEle.find(":checkbox").attr("checked", "");
                                }
                                e.stopPropagation();
                            })
                        }
                    })
                }
                initTree(id);
                
                /*
                 * unload events by passing ul#id
                 */
                function unloadEvent(id){
                    $("#" + id).find("li>div.tree-node").each(function(index, elem){
                        $(this).unbind("click").unbind("dblclick");
                        $(this).find(">span").unbind("click");
                        if (settings.withCheck) {
                            $(this).find(":checkbox").unbind("click");
                        }
                    });
                }
                
                /*
                 * node: {id: 'node li#id', name: 'new-name'}
                 */
                function renameNode(node){
                    $("#" + node.id, "#" + settings.id).find(">div.tree-node>span").html(node.name);
                }
                
                /*
                 * node: {id: 'optional', name: 'required'}
                 * liId: parent node li#id, default root#id.
                 */
                function addNode(node, liId, miscAttributes){
                    if (node == null) {
                        return;
                    }
                    if (typeof node.name !== 'string') {
                        return;
                    }
                    if ($.trim(node.name).length === 0) {
                        return;
                    }
                    
                    var rootMode = (liId == null) || ($.trim(liId) == '');
                    var liEle;
                    if (!rootMode) liEle = $("#" + liId);
                    
                    var ulId;
                    if (rootMode) {
                        ulId = settings.id;
                    } else {
                        if (liId.length == 0) {
                            return;
                        }
                        
                        ulId = $("#" + liId).children("ul").attr("id");
                    }
                    
                    unloadEvent(ulId);
                    
                    settings.liCount += 1;
                    
                    var html = "<li id='";
                    if (typeof node.id == 'undefined' || $.trim(node.id).length == 0) html += settings.id + "-li-" + settings.liCount;
                    else html += node.id;
                    
                    html += "' class='close' ";
                    
                    if (miscAttributes != null) {
                        for (var attr in miscAttributes) {
                            html += attr + "='" + miscAttributes[attr] + "' ";
                        }
                    }
                    
                    html += ">";
                    html += "<div class='tree-node'>";
                    
                    if (settings.withCheck) {
                        html += "<input type='checkbox' id='" + settings.id + "-cb-" + settings.liCount + "'";
                        
                        if (!rootMode) {
                            if (liEle.find(">div.tree-node>input:checkbox").attr("checked")) {
                                html += " checked='checked' ";
                            }
                        }
                        html += "/>"
                    }
                    
                    html += "<span unselectable='on'>";
                    html += node.name;
                    html += "</span></div>";
                    html += "<ul id='" + settings.id + "-ul-" + settings.liCount + "'></ul>";
                    html += "</li>"
                    
                    $(html).appendTo("#" + ulId)
                    
                    initTree(ulId);
                }
                
                /*
                 * liId: node li#id
                 */
                function removeNode(liId){
                    $("#" + liId, "#" + settings.id).remove();
                }
                
                /*
                 * Add sibling
                 */
                function addSibling(node, liId, miscAttributes){
                    if (liId == null || $.trim(liId) == '') {
                        return;
                    }
                    
                    addNode(node, $("#" + liId).parent().parent().attr("id"), miscAttributes);
                }
                
                function emptyChildren(liId){
                    $("#" + liId, "#" + settings.id).find(">ul").empty();
                }
                
                return {
                    id: id,
                    menu: menu,
                    renameNode: renameNode,
                    addChild: addNode,
                    addSibling: addSibling,
                    removeNode: removeNode,
                    emptyChildren: emptyChildren
                };
            }
        })();
        
        /* mask */
        (function(){
            var _maskCount = 0;
            
            cy.ui.mask = function(options){
                var settings = {
                    id: '',
                    autoShow: false,
                    bound: null /*{left: 0,top: 0,width: 100,height: 100}*/
                };
                if (options != null) {
                    cy.extend(settings, options);
                }
                var bigiframe = null;
                
                function init(){
                    var zIndex = cy.ui.zIndex.getLatest();
                    
                    settings.id = "mask-" + ++_maskCount;
                    var html = "<div id='" + settings.id + "' class='mask' style='width: ";
                    if (settings.bound) {
                        html += settings.bound.width + "px; left: " + settings.bound.left + "px; top: " + settings.bound.top + "px; height: " + settings.bound.height;
                    } else {
                        var size = cy.ui.screen.getFitSize();
                        html += size.width + "px; left: 0px; top: 0px; height: " + size.height;
                    }
                    html += "px; z-index: " + zIndex + ";display: none;'></div>";
                    
                    $(html).appendTo("body");
                    bigiframe = cy.ui.bigiframe(settings.id);
                    
                    if (!settings.bound) {
                        $(window).resize(function(){
                            resize(cy.ui.screen.getFitSize());
                            if (bigiframe !== null) {
                                //bigiframe.validate();
                            }
                        });
                    }
                }
                init();
                
                function show(){
                    if (settings.bound) {
                        $("#" + settings.id).css({
                            display: 'block',
                            left: settings.bound.left + 'px',
                            top: settings.bound.top + 'px',
                            width: settings.bound.width + 'px',
                            height: settings.bound.height + 'px'
                        });
                    } else {
                        var size = cy.ui.screen.getFitSize();
                        $("#" + settings.id).css({
                            display: 'block',
                            width: size.width,
                            height: size.height
                        });
                    }
                }
                
                function hide(){
                    $("#" + settings.id).css({
                        display: 'none'
                    });
                }
                
                function resize(size){
                    /*
                     * size: {width: 10, height: 10}
                     */
                    $("#" + settings.id).css(size);
                }
                
                function setBound(bound){
                    if (bound) {
                        settings.bound = bound;
                        $("#" + settings.id).css({
                            left: settings.bound.left + 'px',
                            top: settings.bound.top + 'px',
                            width: settings.bound.width + 'px',
                            height: settings.bound.height + 'px'
                        });
                    }
                }
                
                if (settings.autoShow) {
                    show();
                }
                return {
                    show: show,
                    hide: hide,
                    setBound: setBound
                }
            }
        })();
        
        /* window */
        (function(){
            var _winCount = 0;
            
            cy.ui.window = function(eleId, options){
                if (eleId == null || $.trim(eleId).length == 0) {
                    return null;
                }
                var domEle = $("#" + eleId);
                
                if (domEle.length == 0) return null;
                
                var settings = {
                    id: '', // window id
                    eleId: '',
                    title: '',
                    width: 400,
                    height: 300,
                    autoShow: false,
                    widhMask: true,
                    moveable: false,
                    headerclose: true,
                    buttons: [/*{id: '', name: '关闭', clicked: function(){ }, attributes: { className: 'button' } }*/],
                    args: {} // 附加窗口的参数
                };
                if (options != null) {
                    cy.extend(settings, options);
                }
                settings.eleId = eleId;
                
                // build mask
                var mask;
                if (settings.widhMask) {
                    mask = cy.ui.mask({
                        autoShow: settings.autoShow
                    });
                }
                
                var drag; // drag
                var bigiframe = null;
                function init(){
                    settings.winWidth = settings.width + 12;
                    settings.winHeight = settings.height + 28;
                    
                    var pos = cy.ui.screen.getWinCenterPos({
                        width: settings.winWidth,
                        height: settings.winHeight
                    });
                    var zIndex = cy.ui.zIndex.getLatest();
                    
                    settings.id = 'win-' + ++_winCount;
                    
                    var html = "<div class='win' id='" + settings.id +
                    "' style='left: " +
                    pos.left +
                    "px; top: " +
                    pos.top +
                    "px; width: " +
                    settings.winWidth +
                    "px; height: " +
                    settings.winHeight +
                    "px; " +
                    "z-index: " +
                    zIndex +
                    "; display: none;";
                    
                    html += "'>";
                    
                    html += "<div class='win-body'><div class='win-body-r'>";
                    html += "<div class='win-body-con' style='width: " + settings.width + "px; height: " + settings.height + "px;'>";
                    html += "</div></div></div>";
                    
                    html += "</div>";
                    
                    domEle.wrap(html);
                    
                    var win = $("#" + settings.id);
                    
                    // head
                    html = "<div class='win-title'><div class='win-title-tr'><div class='win-title-con' id='" + settings.id + "-title'>";
                    if (settings.headerclose) {
                        html += "<div class='close'></div>";
                    }
                    html += "<span>";
                    html += settings.title;
                    html += "</span></div></div></div>";
                    $(html).find("div.close").click(function(){
                        hide();
                    }).end().prependTo(win);
                    
                    // foot
                    html = "<div class='win-foot'><div class='win-foot-br'><div class='win-foot-con'>";
                    
                    if (settings.buttons && settings.buttons.length > 0) {
                        for (var i = 0; i < settings.buttons.length; i++) {
                            html += "<input type='button' id='";
                            
                            if ($.trim(settings.buttons[i].id) == '') {
                                settings.buttons[i].id = settings.id + "-btn-" + i;
                            }
                            
                            html += settings.buttons[i].id;
                            html += "' value='";
                            
                            if (settings.buttons[i].name == '') {
                                html += settings.buttons[i].id;
                            } else {
                                html += settings.buttons[i].name;
                            }
                            
                            html += "' ";
                            
                            for (var attr in settings.buttons[i].attributes) {
                                if (attr == 'className') {
                                    html += "class='" + settings.buttons[i].attributes[attr] + "' ";
                                } else {
                                    html += attr + "='" + settings.buttons[i].attributes[attr] + "' ";
                                }
                            }
                            
                            html += "/>&nbsp;";
                        }
                    }
                    
                    html += "</div></div></div>";
                    
                    if (settings.buttons && settings.buttons.length > 0) {
                        $(html).find(":button").each(function(index, domEle){
                            if (settings.buttons[index].clicked) $(this).click(settings.buttons[index].clicked);
                        }).end().appendTo(win);
                    } else {
                        win.append(html);
                    }
                    
                    if (settings.moveable) {
                        drag = cy.ui.dragable(settings.id, settings.id + '-title');
                    }
                    
                    bigiframe = cy.ui.bigiframe(settings.id);
                }
                init();
                
                var isShow = false;
                function show(){
                    if (mask != null) {
                        mask.show();
                    }
                    isShow = true;
                    var pos = cy.ui.screen.getWinCenterPos({
                        width: settings.winWidth,
                        height: settings.winHeight
                    });
                    
                    $("#" + settings.id).css({
                        display: 'block',
                        left: pos.left,
                        top: pos.top
                    });
                }
                
                function hide(){
                    if (mask != null) {
                        mask.hide();
                    }
                    isShow = false;
                    $("#" + settings.id).css({
                        display: 'none'
                    });
                }
                
                function setArgs(args){
                    if (args != null) {
                        settings.args = args;
                    }
                }
                
                function getArgs(){
                    return settings.args;
                }
                
                function clearArgs(){
                    settings.args = {};
                }
                
                function setTitle(title){
                    $("#" + settings.id).find("div.win-title-con>span").html(title);
                }
                
                function ReSize(fwidth, fheight){
                
                    var window = $("#" + settings.id);
                    
                    settings.winWidth = fwidth;
                    settings.winHeight = fheight;
                    
                    var footHeight = window.find("div.win-foot").height();
                    
                    window.find("div.win-body-con").css({
                        width: fwidth - 12,
                        height: fheight - 28
                    });
                    window.css({
                        width: fwidth,
                        height: fheight
                    });
                    
                    var pos = cy.ui.screen.getWinCenterPos({
                        width: settings.winWidth,
                        height: settings.winHeight
                    });
                    
                    window.css({
                        display: 'block',
                        left: pos.left,
                        top: pos.top
                    });
                    
                    if (mask != null) {
                        mask.hide();
                        mask.show();
                    }
                    
                    if (drag) {
                        drag.disable();
                    }
                }
                
                function maximize(){
                    var size = cy.ui.screen.getCurrentViewBound();
                    var window = $("#" + settings.id);
                    
                    var footHeight = window.find("div.win-foot").height();
                    
                    window.find("div.win-body-con").css({
                        width: size.width - 12,
                        height: size.height - footHeight - 28
                    });
                    window.css(size);
                    
                    if (drag) {
                        drag.disable();
                    }
                }
                
                if (settings.autoShow) {
                    show();
                }
                return {
                    show: show,
                    hide: hide,
                    setArgs: setArgs,
                    getArgs: getArgs,
                    clearArgs: clearArgs,
                    setTitle: setTitle,
                    mask: mask,
                    drag: drag,
                    maximize: maximize,
                    ReSize: ReSize,
                    isShow: isShow
                }
            }
        })();
        
        /* tabs */
        (function(){
            var _tabsCount = 0;
            
            cy.ui.tabs = function(options){
                var settings = {
                    id: '',
                    containerId: '',
                    width: 400,
                    height: 300,
                    closeable: false,
                    tabs: [/*{id: '', name: '', activated: function(){}}*/]
                };
                if (options != null) cy.extend(settings, options);
                
                settings.id = 'tabs-' + ++_tabsCount;
                var _itemsCount = 0;
                var tabs = [];
                
                function init(){
                    var html = "<div class='tabs' id='" + settings.id + "'><div class='tabs-head'><div class='tabs-head-con'>";
                    html += "<ul class='tabs-head-ctrl clearfix'>";
                    html += "</ul>"
                    html += "</div></div>";
                    html += "<div class='tabs-body'>";
                    html += "</div>";
                    html += "</div>";
                    
                    $(html).appendTo((settings.containerId && (settings.containerId != '')) ? "#" + settings.containerId : "body");
                    
                    for (var i = 0; settings.tabs[i]; i++) {
                        addTab(settings.tabs[i]);
                    }
                    
                    settings.tabs = null;
                    switchToTab(0, true);
                }
                init();
                
                function addTab(tab){
                    /*
                     * tab: {id: '', name: '', activated: function(){}}
                     */
                    var exist = false;
                    for (var i = 0; tabs[i]; i++) {
                        if (tabs[i].id == tab.id) {
                            exist = true;
                            break;
                        }
                    }
                    if (!exist) tabs.push(tab);
                    else                         
                        return;
                    
                    tab.ctrlId = settings.id + "-tab-ctrl-" + ++_itemsCount;
                    tab.conId = settings.id + "-tab-con-" + _itemsCount;
                    
                    var ctrlHead = "<li id='" + settings.id + "-tab-ctrl-" + _itemsCount + "'>";
                    
                    if (tab.closeable) {
                        ctrlHead += "<a class='tab-close' onclick='return false;'/>";
                    }
                    
                    ctrlHead += "<a style='cursor: pointer;'><em><span class='tabs-head-ctrl-inner'><span class='tabs-head-ctrl-con'>";
                    ctrlHead += tab.name;
                    ctrlHead += "</span></span></em></a></li>";
                    
                    $(ctrlHead).find("a[class!='tab-close']").click(function(){
                        switchToTab(tab.id);
                    }).end().find("a.tab-close").click(function(){
                        closeTab(tab.id);
                    }).end().appendTo($("#" + settings.id).find("ul.tabs-head-ctrl"));
                    
                    var con = "<div id='" + tab.conId + "' class='tabs-con' style='display: none;'></div>";
                    $(con).append($("#" + tab.id)).appendTo($("#" + settings.id).find("div.tabs-body"));
                }
                
                function closeTab(){
                    /*
                     * close tab.
                     * arguments[0]: zero-based index number or content#id
                     */
                    var arg = arguments[0];
                    if (arg == null || arg == '' && arg != 0) return;
                    
                    var index = parseInt(arg);
                    var curActive = false;
                    
                    if (!isNaN(index)) { // index based
                        if (index > -1 && index < tabs.length) {
                            var tab = tabs[index];
                            curActive = tab.active;
                            
                            $("#" + tab.ctrlId, "#" + settings.id).remove();
                            $("#" + tab.conId, "#" + settings.id).remove();
                            
                            var left = [];
                            if (index > 0) left = tabs.slice(0, index);
                            var right = [];
                            if (index < tabs.length - 1) right = tabs.slice(index + 1, tabs.length);
                            
                            tabs = left.concat(right);
                        }
                    } else {
                        for (var i = 0; tabs[i]; i++) {
                            if (tabs[i].id == arg) {
                                var tab = tabs[i];
                                curActive = tab.active;
                                
                                $("#" + tab.ctrlId, "#" + settings.id).remove();
                                $("#" + tab.conId, "#" + settings.id).remove();
                                
                                var left = [];
                                if (i > 0) left = tabs.slice(0, i)
                                var right = [];
                                if (i < tabs.length - 1) right = tabs.slice(i + 1, tabs.length);
                                
                                tabs = left.concat(right);
                                
                                break;
                            }
                        }
                    }
                    
                    if (curActive) {
                        switchToTab(0, true);
                    }
                }
                
                function switchToTab(){
                    /*
                     * change to the specificated tab.
                     * arguments[0]: zero-based index number or content#id
                     * arguments[1]: slience, true for not trigger event
                     */
                    var arg = arguments[0];
                    var silence = arguments[1];
                    if (arg == null || (arg == '' && arg != 0)) return;
                    
                    var index = parseInt(arg);
                    
                    var _activatedIndex = -1; // 被激活的tab-index
                    if (!isNaN(index)) { // index based
                        if (index > -1 && index < tabs.length) {
                            if (tabs[index].active) return;
                            
                            for (var i = 0; tabs[i]; i++) {
                                if ((i != index) && tabs[i].active) {
                                    tabs[i].active = false;
                                    $("#" + tabs[i].ctrlId, "#" + settings.id).removeClass("active");
                                    $("#" + tabs[i].conId, "#" + settings.id).css({
                                        display: "none"
                                    });
                                    break;
                                }
                            }
                            
                            $("#" + tabs[index].ctrlId, "#" + settings.id).addClass("active");
                            $("#" + tabs[index].conId, "#" + settings.id).css({
                                display: "block"
                            });
                            tabs[index].active = true;
                            
                            _activatedIndex = index;
                        }
                    } else {
                        for (var i = 0; tabs[i]; i++) {
                            if (!tabs[i].active) {
                                if (tabs[i].id == arg) {
                                    $("#" + tabs[i].ctrlId, "#" + settings.id).addClass("active");
                                    $("#" + tabs[i].conId, "#" + settings.id).css({
                                        display: "block"
                                    });
                                    tabs[i].active = true;
                                    
                                    _activatedIndex = i;
                                }
                            } else {
                                if (tabs[i].id != arg) {
                                    $("#" + tabs[i].ctrlId, "#" + settings.id).removeClass("active");
                                    $("#" + tabs[i].conId, "#" + settings.id).css({
                                        display: "none"
                                    });
                                    tabs[i].active = false;
                                }
                            }
                        }
                    }
                    
                    if ((_activatedIndex != -1) && tabs[_activatedIndex].activated && !silence) {
                        tabs[_activatedIndex].activated();
                    }
                }
                
                return {
                    addTab: addTab,
                    switchTo: switchToTab,
                    closeTab: closeTab
                }
            }
        })();
    })();
    
    (function(){
        cy.iframe = {};
        
        var getFFVersion = navigator.userAgent.substring(navigator.userAgent.indexOf("Firefox")).split("/")[1];
        var FFextraHeight = parseFloat(getFFVersion) >= 0.1 ? 16 : 0; //extra height in px to add to iframe in FireFox 1.0+ browsers
        cy.iframe.fit = function(obj, min){
            var h;
            var bobo = obj;
            if (bobo && !window.opera) {
                if (bobo.contentDocument && bobo.contentDocument.body.offsetHeight) {
                    h = bobo.contentDocument.body.offsetHeight + FFextraHeight;
                } else if (bobo.Document && bobo.Document.body.scrollHeight) {
                    h = bobo.Document.body.scrollHeight;
                }
            }
            
            if (h) {
                if (min !== null) {
                    h = h < min ? min : h;
                }
                bobo.height = h;
            }
        }
        
        cy.iframe.autoFitHeight = function(id, min){
            var iframe = document.getElementById(id);
            if (!iframe) {
                return;
            }
            
            if (window.attachEvent && !window.addEventListener) {
                iframe.attachEvent("onload", function(){
                    cy.iframe.fit(iframe, min);
                });
            } else if (window.addEventListener) {
                iframe.addEventListener("load", function(){
                    cy.iframe.fit(iframe, min);
                }, false);
            }
        }
    })();
    
    /* ume.ui.paging */
    (function(){
        cy.ume.ui.paging = function(options){
            var settings = {
                id: '',
                lang: {
                    firstPageText: '第一页',
                    lastPageText: '最后页',
                    prePageText: '前一页',
                    nextPageText: '后一页'
                },
                totalRecords: 98,
                pageSize: 10,
                curPage: -1,
                num: {
                    enabled: true, // 是否显示数字
                    preNumber: 3,
                    nextCount: 3
                },
                pageChanging: null, /* function(curPageNum, newPageNum){ return true; } */
                pageChanged: null /* function(pageNum){} */
            };
            cy.extend(settings, options ||
            {});
            var initialized = false;
            
            if (settings.id == '') {
                return null;
            } else if ($("#" + settings.id).length == 0) {
                return null;
            }
            
            function buildPageCount(){
                var pageCount = 1; // 总页数
                settings.curPage = settings.curPage < 1 ? 1 : settings.curPage;
                settings.pageSize = settings.pageSize < 1 ? 10 : settings.pageSize;
                settings.totalRecords = settings.totalRecords < 0 ? 0 : settings.totalRecords;
                
                var mod = settings.totalRecords % settings.pageSize;
                if (mod == 0) {
                    pageCount = settings.totalRecords / settings.pageSize;
                    if (pageCount == 0) { // 总纪录数为0
                        pageCount = 1;
                    }
                } else {
                    pageCount = (settings.totalRecords - mod) / settings.pageSize + 1;
                }
                
                settings.pageCount = pageCount;
                initialized = false;
            }
            buildPageCount();
            
            function redirectTo(pageNum, isSilent){
                var pn = 1;
                if (!pageNum) {
                    pn = 1;
                } else {
                    pn = parseInt(pageNum);
                    if (isNaN(pn)) {
                        pn = 1;
                    } else if (pn < 1) {
                        pn = 1;
                    } else if (pn > settings.pageCount) {
                        pn = settings.pageCount;
                    } else {
                        pn = pageNum;
                    }
                }
                
                if (isSilent == null) {
                    isSilent = false;
                }
                
                if (pn == settings.curPage) {
                    if (!initialized) {
                        initialized = true;
                    } else {
                        return;
                    }
                } else {
                    if (!isSilent && settings.pageChanging && (typeof settings.pageChanging == 'function')) {
                        if (!settings.pageChanging(settings.curPage, pn)) {
                            return;
                        }
                    }
                }
                
                $("#" + settings.id).empty();
                
                if (pn > 1) {
                    $('<li class="page_hove floatl marginl2"><a class="font12 fontblue">' + settings.lang.firstPageText + '</a></li>').find("a").click(function(){
                        redirectTo(1);
                    }).end().appendTo("#" + settings.id);
                    $('<li class="page_hove floatl marginl2"><a class="font12 fontblue">' + settings.lang.prePageText + '</a></li>').find("a").click(function(){
                        redirectTo(pn - 1);
                    }).end().appendTo("#" + settings.id);
                }
                
                if (settings.num && settings.num.enabled) {
                    for (var i = pn - settings.num.preNumber; i < pn; i++) {
                        if (i > 0) {
                            (function(pn){
                                $('<li class="page_hove floatl marginl2"><a class="font12 fontblue">' + pn + '</a></li>').find("a").click(function(){
                                    redirectTo(pn);
                                }).end().appendTo("#" + settings.id);
                            })(i);
                        }
                        
                    }
                    $('<li class="page_hove floatl marginl2"><a class="font12 fontblue current">' + pn + '</a></li>').appendTo("#" + settings.id);
                    for (var i = pn + 1; i < pn + settings.num.nextCount + 1; i++) {
                        if (i < settings.pageCount + 1) {
                            (function(pn){
                                $('<li class="page_hove floatl marginl2"><a class="font12 fontblue">' + pn + '</a></li>').find("a").click(function(){
                                    redirectTo(pn);
                                }).end().appendTo("#" + settings.id);
                            })(i);
                        }
                    }
                }
                
                if (pn < settings.pageCount) {
                    $('<li class="page_hove floatl marginl2"><a class="font12 fontblue">' + settings.lang.nextPageText + '</a></li>').find("a").click(function(){
                        redirectTo(pn + 1);
                    }).end().appendTo("#" + settings.id);
                    $('<li class="page_hove floatl marginl2"><a class="font12 fontblue">' + settings.lang.lastPageText + '</a></li>').find("a").click(function(){
                        redirectTo(settings.pageCount);
                    }).end().appendTo("#" + settings.id);
                }
                
                settings.curPage = pn;
                if (!isSilent && settings.pageChanged && (typeof settings.pageChanged == 'function')) {
                    settings.pageChanged(settings.curPage);
                }
            }
            
            function setTotalRecords(count, slient){
                if ((count === null) || isNaN(count) || (count < 0)) {
                    return;
                }
                settings.totalRecords = count;
                buildPageCount();
                redirectTo(settings.curPage, slient);
            }
            
            function setPageSize(size){
                if (!size || isNaN(size) || (size < 1)) {
                    return;
                }
                
                settings.pageSize = size;
                buildPageCount();
            }
            
            redirectTo(settings.curPage, true);
            
            return {
                redirectTo: redirectTo,
                setTotalRecords: setTotalRecords,
                setPageSize: setPageSize
            }
        }
    })();
})(jQuery);
