/*
jsLinb 2.2
Copyright(c) 2009 Yingbo Li(www.linb.net, linb.net[at]gmail.com)
Open Source under LGPL (http://www.gnu.org/licenses/lgpl-3.0-standalone.html)
Contact linb.net[at]gmail.com for Commercial issues
*/
//speed up references
var undefined,

//global: time stamp
_=window._=function(){return +new Date()},
//global: name space
Namespace=window.Namespace=function(key){
    var a=key.split('.'),w=window;
    return _.get(w, a) || _.set(w, a, {});
},
//global: class
Class=window.Class=function(key, pkey, obj){
    var _Static, _parent=[], self=Class, w=window, env=self._fun, reg=self._reg, parent0, _this,i,t,_t;
    obj=obj||{};
    //exists?
    if(t=_.get(w, key.split('.')))return t;

    //multi parents mode
    pkey = ( !pkey?[]:typeof pkey=='string'?[pkey]:pkey);
    for(i=0; t=pkey[i]; i++)
        if(!(_parent[i]=(_.get(w, t.split('.')) || (linb&&linb.SC&&linb.SC(t)))))
            throw new Error('errNoParent:'+ t);
    if(obj.Dependency)
        for(i=0; t=obj.Dependency[i]; i++)
            if(!(_.get(w, t.split('.')) || (linb&&linb.SC&&linb.SC(t))))
                throw new Error('errNoDependency:'+ t);
    parent0=_parent[0];

    // collect items
    _Static=obj.Static||{};
    t={};
    for(i in _Static)
        if(reg[i])t[i]=1;
    for(i in t)
        delete _Static[i];

    //before and after will pass to children
    _Static.Before = obj.Before || (parent0&&parent0.Before);
    _Static.After = obj.After || (parent0&&parent0.After);
    _Static.$End = obj.$End || (parent0&&parent0.$End);
    _Static.__gc = obj.__gc || _Static.__gc || (parent0&&parent0.__gc) || function(){Class.__gc(this.$key)};

    /*set constructor first and create _this
    upper is the first parent Class
    */
    if(typeof obj.Constructor == 'function'){
        _this = env(obj.Constructor, 'Constructor', key, parent0||_.fun());
        _this.Constructor = String(obj.Constructor);
    }else{
        if(parent0){
            // Constructor is for opera, in opear fun.toString can't get arguments sometime
            var f=_.fun(),str = parent0.Constructor;
            if(str)f=new Function(str.slice(str.indexOf("(") + 1, str.indexOf(")")).split(','), str.slice(str.indexOf("{") + 1, str.lastIndexOf("}")));
            _this = env(f, 'Constructor', key, parent0.upper);
            _this.Constructor = str;
        }else
            _this = _.fun();
    }

    //collect parent items, keep the last one
    _t=_.fun();
    for(i=_parent.length-1; t=_parent[i--];){
        _.merge(_t,t);
        _.merge(_t.prototype,t.prototype);
    }
    //set keys
    _this.KEY=_this.$key=_this.prototype.KEY=_this.prototype.$key=key;
    //envelop
    //  from Static
    self._wrap(_this,_Static,0,_t);
    //  from Instance
    if(t=obj.Instance)
        self._wrap(_this.prototype,t,1,_t.prototype);
    //inherite from parents
    self._inherit(_this,_t);
    self._inherit(_this.prototype,_t.prototype);
    _t=null;

    //exe before functoin
    if(_.tryF(_this.Before, arguments, _this)===false)
        return false;

    //add child key to parents
    for(i=0; t=_parent[i]; i++){
        t=(t.$children || (t.$children=[]));
        for(var j=0,k=t.length,b;j<k;j++)
            if(t[k]==key){
                b=true;
                break;
            }
        if(!b)t[t.length]=key;
    }

    //set symbol
    _this.$linb$ = 1;
    _this.$children = [];
    _this.$parent = _parent;

    //set constructor
    _this.prototype.constructor = _this;
    //set key
    _this[key] = _this.prototype[key] = true;

    //attached to global
    _.set(w, key.split('.'), _this);
    //exe after function
    _.tryF(_this.After, [], _this);
    //exe ini function
    _.tryF(obj.Initialize, [], _this);
    _.tryF(_this.$End, [], _this);

    _.breakO([obj.Static, obj.Instance, obj],2);

    //return Class
    return _this;
},
//global: linb
linb=window.linb=function(nodes,flag){return linb.Dom.pack(nodes, flag)};

//window.onerror will be redefined in linb.Debugger
//window.onerror=function(){return true};

/*merge hash from source to target
  target:hash
  source:hash
  type:'all', 'with', 'without'[default], or function <return true will trigger merge>
  return: merged target
*/
_.merge=function(target, source, type){
    var i,f;
    if(typeof type == "function"){
        f=type;
        type='fun';
    }
    switch(type){
        case 'fun':
            for(i in source)if(true===f(source[i],i))target[i]=source[i];
            break;
        case 'all':
            for(i in source)target[i]=source[i];
            break;
        case 'with':
            for(i in source)if(i in target)target[i]=source[i];
            break;
        default:
            for(i in source)if(!(i in target))target[i]=source[i];
    }
    return target;
};
_.merge(_,{
    fun:function(){return function(){}},
    exec:function(script){
        var me=this,
            d=document,
            h=d.getElementsByTagName("head")[0] || d.documentElement,
            s=d.createElement("script");
        s.type = "text/javascript";
        if(linb.browser.ie)
            s.text=script;
        else
            s.appendChild(d.createTextNode(script));
        h.insertBefore(s, h.firstChild);
        h.removeChild(s);
    },
    /*
    get something from deep hash
    hash:target hash
    arr:path array,
    example:
    _.get({a:{b:{c:1}}},['a','b']) => {c:1};
        _.get({a:{b:{c:1}}},['a','b','c']) => 1;
        _.get({a:{b:{c:1}}},['a','b','c','d']) => undefined;
    */
    get:function(hash,path){
        if(!path) return hash;
        else if(typeof path=='string') return hash[path];
        else{
            for(var i=0,l=path.length;i<l;)
                if(!hash || (hash=hash[path[i++]])===undefined )return;
            return hash;
        }
    },
    /*
    set/unset a value to deep hash
    example:
        _.set({a:{b:{c:1}}},['a','b','c'],2) => {a:{b:{c:2}}}
        _.set({a:{b:{c:1}}},['a','b','c']) => {a:{b:{}}}
    */
    set:function(hash,path,value){
        if(typeof path!='string'){
            var v,i=0,m,last=path.length-1;
            for(;i<last;){
                v=path[i++];
                if(hash[v]&&((m=typeof hash[v])=='object' || m=='function')) hash=hash[v];
                else hash=hash[v]={};
            }
            path=path[last];
        }
        if(value===undefined){
            if(hash.hasOwnProperty && hash.hasOwnProperty(path))
                delete hash[path];
            else hash[path]=undefined;
        }else
            return hash[path]=value;
    },
    /* try to excute a function
    fun:target function
    args:arguments for fun
    scope:[this] pointer for fun
    df:default return vale
    */
    tryF:function(fun, args, scope, df){
        return (fun && typeof fun=='function') ? fun.apply(scope||null, args||[]) : df
    },
    /*asynchronous run function
    fun:target function
    defer: setTimeout defer time
    args: arguments for fun
    scope: [this] pointer for fun
    */
    asyRun:function(fun, defer, args, scope){
        //defer must set in opera
        return setTimeout(typeof fun=='string' ? fun : function(){fun.apply(scope,args||[]);fun=args=null;}, defer||0);
    },
    isEmpty:function(hash){for(var i in hash)return false; return true},

    /*
    this will always run newer function
    key: for identify
    fun: to run
    defer: setTimeout defer time
    args: arguments for fun
    scope: 'this' for fun
    */
    resetRun:function(key, fun, defer ,args, scope){
        var me=arguments.callee, k=key, cache = me.$cache || (me.$cache = {});
        if(cache[k]){clearTimeout(cache[k])}
        if(typeof fun=='function')
            cache[k] = setTimeout(function(){delete cache[k];fun.apply(scope||null,args||[])},defer||0);
        else delete cache[k];
    },
    //Dependency: linb.Dom linb.Thread
    observableRun:function(tasks,onEnd,threadid){
        linb.Thread.observableRun(tasks,onEnd,threadid);
    },

    /*break object memory link
    target: target object
    n: depth, default 1
    */
    breakO:function(target,depth){
        var n=depth||1, l=1+(arguments[2]||0), self=arguments.callee, _t='___gc_', i;
        if(target && (typeof target=='object' || typeof target=='function') && target!==window&&target!==document&&target.nodeType!==1){
            if(target.hasOwnProperty(_t))return; else try{target[_t]=null}catch(e){return}
            for(i in target){
                if(target.hasOwnProperty(i) && target[i]){
                    if(typeof target[i]=='object' || typeof target[i]=='function')
                        if(l<n)
                            self(target[i],n,l);
                    try{target[i]=null}catch(e){}
                }
            }
            if(target.length)target.length=0;
            delete target[_t];
        }
    },

    /*each function for hash
    fun: fun to exec, if return false, stop the $iterator
    scope: 'this' pointer;
    */
    each:function(hash,fun,scope){
        scope = scope||hash;
        for(var i in hash)
            if(false===fun.call(scope, hash[i], i, hash))
                break;
        return hash;
    },
    /*shadow copy for hash/array
    * var a=[]; a.b='b'; a.b will not be copied
    */
    copy:function(hash,filter){
        return _.clone(hash,filter,1);
    },
    /*deep copy for hash/array, and hash/array only
    * var a=[]; a.b='b'; a.b will not be cloned
    *be careful for dead lock
    */
    clone:function(hash,filter,deep){
        if(hash && typeof hash=='object'){
            var c=hash.constructor,a=c==Array;
            if(a||c==Object){
                var me=arguments.callee,h=a?[]:{},v,i=0,l;
                if(!deep){
                    if(deep===0)return hash;
                    else deep=100;
                }
                if(a){
                    l=hash.length;
                    for(;i<l;i++){
                        if(typeof filter=='function'&&false===filter.call(hash,hash[i],i))continue;
                        h[h.length]=((v=hash[i]) && deep && typeof v=='object')?me(v,filter,deep-1):v;
                    }
                }else{
                    for(i in hash){
                        if(filter===true?i.charAt(0)=='_':typeof filter=='function'?false===filter.call(hash,hash[i],i):0)
                            continue;
                        h[i]=((v=hash[i]) && deep && typeof v=='object')?me(v,filter,deep-1):v;
                    }
                }
                return h;
            }else return hash;
        }else return hash;
    },
    /*filter hash/array
    filter: filter function(will delete "return false")
    */
    filter:function(obj, filter, force){
        if(!force && obj && obj.constructor == Array){
            var i,l,v,a=[],o;
            for(i=0, l=obj.length; i<l; i++)a[a.length]=obj[i];
            obj.length=0;
            for(i=0, l=a.length; i<l; i++)
                if(typeof filter=='function'?false!==filter.call(a,a[i],i):1)
                    obj[obj.length]=a[i];
        }else{
            var i, bak={};
            for(i in obj)
                if(filter===true?i.charAt(0)=='_':typeof filter=='function'?false===filter.call(obj,obj[i],i):0)
                    bak[i]=1;

            for(i in bak)
                delete obj[i];
        }
        return obj;
    },
    /*convert iterator to Array
    value: something can be iteratorred
    _.toArr({a:1},true) => [a];
    _.toArr({a:1},false) => [1];
    _.toArr('a,b') => ['a','b'];
    _.toArr('a;b',';') => ['a','b'];
    */
    toArr:function(value, flag){
        if(!value)return [];
        var arr=[];
        //hash
        if(typeof flag == 'boolean')
            for(var i in value)
                arr[arr.length]=flag?i:value[i];
        //other like arguments
        else{
            if(typeof value=='string')
                arr=value.split(flag||',');
            else
                for(var i=0,l=value.length; i<l; ++i)
                    arr[i]=value[i];
        }
        return arr;
    },
    toUTF8:function(str){
        return str.replace(/[^\x00-\xff]/g, function(a,b) {
            b=a.charCodeAt();
            return '\\u' + Math.floor(b/16).toString(16)+(b%16).toString(16);
        })
    },
    fromUTF8:function(str){
        return str.replace(/\\u([0-9a-f]{3})([0-9a-f])/g,function(a,b,c){return String.fromCharCode((parseInt(b,16)*16+parseInt(c,16)))})
    },
    urlEncode:function(hash){
        var a=[],i,o;
        for(i in hash){
            o=hash[i];
            a.push(encodeURIComponent(i)+'='+encodeURIComponent(typeof o=='string'?o:_.serialize(o)));
        }
        return a.join('&');
    },
    urlDecode:function(str, key){
        if(!str)return key?'':{};
        var arr,hash={},a=str.split('&'),o;
        for(var i=0,l=a.length;i<l;i++){
            o=a[i];
            arr=o.split('=');
            hash[decodeURIComponent(arr[0])]=decodeURIComponent(arr[1]);
        }
        return key?hash[key]:hash;
    },

    // type detection
    isDefined:function(target)  {return target!==undefined},
    isNull:function(target)  {return target===null},
    isObj:function(target)   {return !!target  && (typeof target == 'object' || typeof target == 'function')},
    isBool:function(target)  {return typeof target == 'boolean'},
    isNumb:function(target)  {return typeof target == 'number' && isFinite(target)},
    isDate:function(target)  {return Object.prototype.toString.call(target)==='[object Date]'},
    isFun:function(target)   {return Object.prototype.toString.call(target)==='[object Function]'},
    isArr:function(target)   {return Object.prototype.toString.call(target)==='[object Array]'},
    //object in the current window only
    isHash:function(target)  {return !!target && typeof target == 'object' && target.constructor == Object},
    isReg:function(target)   {return Object.prototype.toString.call(target)==='[object RegExp]'},
    isStr:function(target)   {return typeof target == "string"},
    isArguments:function(target)   {return !!(target && target.callee && target.callee.arguments===target)},
    //for handling String
    str:{
        startWith:function(str,sStr){
            return str.indexOf(sStr) === 0;
        },
        endWith:function (str,eStr) {
            var l=str.length-eStr.length;
            return l>=0 && str.lastIndexOf(eStr) === l;
        },
        repeat:function(str,times){
            return new Array(times+1).join(str);
        },
        initial:function(str){
            return str.charAt(0).toUpperCase() + str.substring(1);
        },
        trim:function(str){
            return this.ltrim(this.rtrim(str));
        },
        ltrim:function(str){
            return str.replace(/^ */,"");
        },
        rtrim:function(str){
            return str.replace(/ *$/,"");
        },
/*
        blen : function(s){
            var _t=s.match(/[^\x00-\xff]/ig);
            return s.length+(null===_t?0:_t.length);
        },
*/
        //Dependency: linb.Dom
        toDom:function(str){
            var p=linb.$getGhostDiv(), r=[];
            p.innerHTML=str;
            for(var i=0,t=p.childNodes,l=t.length;i<l;i++)r[r.length]=t[i];
            p=null;
            return linb(r);
        }
    },
    //for handling Array
    arr:{
        subIndexOf:function(arr,key,value){
            if(value===undefined)return -1;
            for(var i=0, l=arr.length; i<l; i++)
                if(arr[i] && arr[i][key] === value)
                    return i;
            return -1;
        },
        removeFrom:function(arr, index,length){
            arr.splice(index, length || 1);
            return arr;
        },
        removeValue:function(arr, value){
            for(var l=arr.length,i=l-1; i>=0; i--)
                if(arr[i]===value)
                    arr.splice(i,1);
            return arr;
        },
        /*
         insert something to array
         arr: any
         index:default is length-1
         flag: is add array

         For example:
         [1,2].insertAny(3)
            will return [1,2,3]
         [1,2].insertAny(3,0)
            will return [3,1,2]
         [1,2].insertAny([3,4])
            will return [1,2,3,4]
         [1,2].insertAny([3,4],3,true)
            will return [1,2,[3,4]]
        */
        insertAny:function (arr, target,index, flag) {
            var l=arr.length;
            flag=target.constructor!=Array || flag;
            if(index===0){
                if(flag)
                    arr.unshift(target);
                else
                    arr.unshift.apply(arr, target);
            }else{
                var a;
                if(!index || index<0 || index>l)index=l;
                if(index!=l)
                    a=arr.splice(index,l-index);
                if(flag)
                    arr[arr.length]=target;
                else
                    arr.push.apply(arr, target);
                if(a)
                    arr.push.apply(arr, a);
            }
            return index;
        },
        indexOf:function(arr, value) {
            for(var i=0, l=arr.length; i<l; i++)
                if(arr[i] === value)
                    return i;
            return -1;
        },
        /*
        fun: fun to apply
        desc: true - max to min , or min to max
        atarget: for this
        */
        each:function(arr,fun,scope,desc){
            var i, l, a=arr;
            if(!a)return a;
            if(a.constructor!=Array){
                if((a=a._nodes) || a.constructor!=Array)
                    throw new Error('errNotArray');
                if(desc===undefined)
                    desc=1;
            }
            l=a.length;
            scope = scope||arr;
            if(!desc){
                for(i=0; i<l; i++)
                    if(fun.call(scope, a[i], i, a)===false)
                        break;
            }else
                for(i=l-1; i>=0; i--)
                    if(fun.call(scope, a[i], i, a)===false)
                        break;
            return arr;
        }
    }
});
_.merge(_.fun,{
    body:function(fun){
        with (String(fun))return slice(indexOf("{") + 1, lastIndexOf("}"));
    },
    args:function(fun){
        with (String(fun)) return slice(indexOf("(") + 1, indexOf(")")).split(',');
    },
    clone:function(fun){
        return new Function(_.fun.args(fun),_.fun.body(fun));
    }
});

_.merge(Class, {
    _reg:{$key:1,$parent:1,$children:1,KEY:1,Static:1,Instance:1,Constructor:1,Initialize:1},
    _reg2:{'constructor':1,'prototype':1,'toString':1,'valueOf':1},
    /*envelop a function by some keys
    */
    _fun:function(fun, name, original, upper){
        fun.$name$=name;
        fun.$original$=original;
        if(upper)fun.upper = upper;
        return fun;
    },
    _other:["toString", "valueOf"],
    /*envelop object's item from an object
    target: target object
    src: from object
     i: key in hash
    limit: envelop values in a hash
    */
    _o:{},
    //inherit from parents
    _inherit:function (target, src, instance){
        var i, o, r=this._reg;
        for(i in src){
            if(i in target || (!instance && r[i]) || i.charAt(0)=='$')continue;
            o=src[i];
            if(o && o.$linb$)continue;
            target[i]=o;
        }
    },
    //wrap
    _wrap:function (target, src, instance, parent){
        var self=this, i,j,o,k=target.KEY,r=self._reg,r2=self._reg2,f=self._fun,oo=self._other;
        for(i in src){
            if(r2[i] || (!instance && r[i]))continue;
            o=src[i];
            target[i] = (typeof o != 'function') ? o : f(o, i, k, typeof parent[i]=='function'&&parent[i]);
        }
        for(j=0;i=oo[j++];){
            o=src[i];
            if(o && (o == self._o[i]))continue;
            target[i] = (typeof o != 'function') ? o : f(o, i, k, typeof parent[i]=='function'&&parent[i]);
        }
    },
    __gc:function(key){
        if(typeof key=='object')key=key.KEY||"";
        var t = _.get(window, key.split('.')),s,i,j;
        if(t){
            //remove from SC cache
            if(s=_.get(window,['linb','$cache','SC']))delete s[key];

            //remove parent link
            if(t.$parent)
                t.$parent.length=0;

            //remove chidlren link
            //gc children
            if(s=t.$children){
                //destroy children
                for(var i=0,o; o=s[i];i++)
                    if(o=_.get(window,o.split('.')))
                        o.__gc();
                s.length=0;
            }

            //break function links
            for(i in t)
                if(i!='upper' && typeof t[i]=='function')
                    for(j in t[i])
                        if(t[i].hasOwnProperty(j))
                           delete t[i][j];
            _.breakO(t);

            t=t.prototype;
            for(i in t)
                if(i!='upper' && typeof t[i]=='function')
                    for(j in t[i])
                        if(t[i].hasOwnProperty(j))
                            delete t[i][j];
            _.breakO(t);

            //remove it out of window
            _.set(window, key.split('.'));
        }
    },
    destroy:function(key){Class.__gc(key)}
});

//function dependency: linb.Dom linb.Thread
_.merge(linb,{
    Locale:{en:{}},
    $cache:{
        thread:{},
        SC:{},
        hookKey:{},
        snipScript:{},

        //ghost divs
        ghostDiv:[],

        //cache purge map for dom element
        domPurgeData:{},
        //cache DomProfile or UIProfile
        profileMap:{},
        //cache the reclaim serial id for UIProfile
        reclaimId:{},
        //cache built template for UIProfile
        template:{},
        //cache [key]=>[event handler] map for UIProfile
        UIKeyMapEvents:{}
    },

    $lang:'en',
    $href:'javascript:;',
    $langId:'linblangkey',
    setAppLangKey:function(key){linb.$appLangKey=key},
    getAppLangKey:function(key){return linb.$appLangKey},
    getLang:function(){return linb.$lang},
    setLang:function(key,callback){
        var l=linb.Locale,g=linb.getRes,t,v,i,j,f,m,z,a=[];
        linb.$lang=key;
        v = linb.browser.ie ? document.all.tags('span') : document.getElementsByTagName('span');
        for(i=0;t=v[i];i++)if(t.id==linb.$langId)a[a.length]=t;
        f=function(){
            (function(){
                j=a.splice(0,100);
                for(i=0;t=j[i];i++)
                    if(typeof(v=g(t.className))=='string')
                        t.innerHTML=v;
                if(a.length)
                    setTimeout(arguments.callee,0);
                _.tryF(callback);
            }())
        },
        z = 'linb.Locale.' + key,
        m=function(){
            var k=linb.$appLangKey;
            if(k)linb.include(z+'.'+k,linb.getPath('Locale.' + key, '.js'),f,f);
            else f();
        };
        linb.include(z,linb.getPath(z, '.js'),m,m);
    },
    _r:/\x24(\d+)/g,
    getRes:function(id){
        var d,
            b= id.indexOf('-')!=-1?((d=id.split('-'))&&(id=d[0])&&d):arguments ,
            c=_.get(linb.Locale[linb.$lang], id.split('.'));
        return (d=typeof c)=='string'
               ? c.replace(linb._r,function(z,id){return b[parseInt(id)+1]||z})
               : d=='function'
               ? c.apply(null,b) :
               c ? c : id.substr(id.lastIndexOf('.')+1)
    },
    wrapRes:function(id){
        var i=id, s,r;
        if(i.charAt(0)=='$')arguments[0]=i.substr(1,i.length-1);
        s=id;
        r= linb.getRes.apply(null,arguments);
        if(s==r)r=i;
        return '<span id="'+linb.$langId+'" class="'+s+'">'+r+'</span>';
    },
    request:function(uri, query, onSuccess, onFail, threadid, options){
        return ((options&&options.method.toLowerCase()=='post')?linb.absIO.isCrossDomain(uri)?linb.IAjax:linb.Ajax:linb.absIO.isCrossDomain(uri)?linb.SAjax:linb.Ajax).apply(null, arguments).start()
    },
    include:function(id,path,onSuccess,onFail){if(id&&linb.SC.get(id))_.tryF(onSuccess); else linb.SAjax(path,'',onSuccess,onFail,0,{rspType:'script',checkKey:id}).start()},
    /*
    set application main function
    example:
        linb.main(function(){
            ...
        });
    */
    _m:[],
    main:function(fun){linb._m.push(fun)},
    /*
    key: linb.UI.xxx
    tag: file tag
    add: appearance or bahavior
    example:
        linb.getPath('linb.UI.Button','','appearance') => linb.ini.path + /appearance/UI/Button/
        linb.getPath('linb.UI.Button','.gif','appearance') => linb.ini.path + /appearance/UI/Button.gif
        linb.getPath('a.b','','appearance') => linb.ini.appPath + /a/appearance/b/"
        linb.getPath('a.b','.gif','appearance') => linb.ini.appPath + /a/appearance/b.gif"
    */
    getPath : function(key, tag, folder){
        key=key.split('.');
        if(folder){
            var a=[key[0],folder];
            for(var i=1,l=key.length;i<l;i++)
                a.push(key[i]);
            key.length=0;
            key=a;
        }

        var pre,ini=linb.ini;
        if(key[0]=='linb'){
            pre=ini.path;
            key.shift();
            if(key.length==(folder?1:0))key.push('linb');
        }else{
            pre=ini.appPath;
            if(key.length==((folder?1:0)+1) && tag=='.js')key.push('index');
            if(ini.verPath) pre += ini.verPath + '/';
            if(ini.ver) pre += ini.ver + '/';
        }
        return pre + key.join('\/') + (tag||'\/');
    },
    log:_.fun(),
    message:_.fun(),

    //profile object cache
    _pool:[],
    getObject:function(id){return linb._pool['$'+id]},




    _ghostDivId:"linb.ghost::",
    $getGhostDiv:function(){
        var pool=linb.$cache.ghostDiv,
            i=0,l=pool.length,p;
        do{p=pool[i++]}while(i<l && (p&&p.firstChild))
        if(!p || p.firstChild){
            p=document.createElement('div');
            p.id=linb._ghostDivId;
            pool.push(p);
        }
        return p;
    },
//for handling dom element 
    $linbid:0,
    $registerNode:function(o){
        //get id from cache or id
        var id,v,purge=linb.$cache.domPurgeData;
        if(!(o.$linbid && (v=purge[o.$linbid]) && v.element==o)){
            id='!'+linb.$linbid++;
            v=purge[id]||(purge[id]={});
            v.element=o;
            o.$linbid=v.$linbid=id;
        }
        o=null;
        return v;
    },
    getId:function(node){
        if(typeof node=='string')node=document.getElementById(node);
        return node ? window===node?"!window":document===node?"!document":(node.$linbid||'') : '';
    },
    getNodeData:function(node,path){
        if(!node)return;
        return _.get(linb.$cache.domPurgeData[typeof node=='string'?node:linb.getId(node)],path);
    },
    setNodeData:function(node,path,value){
        if(!node)return;
        return _.set(linb.$cache.domPurgeData[typeof node=='string'?node:linb.getId(node)],path,value);
    },
    $purgeChildren:function(node){
        var cache=linb.$cache,
            proMap=cache.profileMap,
            ch=cache.UIKeyMapEvents,
            pdata=cache.domPurgeData,
            children=node.getElementsByTagName('*'),
            l=children.length,
            bak=[],
            i,j,o,t,v,w,id;
         for(i=0;i<l;i++){
            if(!(v=children[i]))continue;
            if(t=v.$linbid){
                if(o=pdata[t]){
                    if(w=o.eHandlers)
                        for(j in w)
                            v[j]=null;

                    for(j in o)
                        o[j]=null;

                    delete pdata[t];
                }

                //remove the only var in dom element
                if(linb.browser.ie)
                    v.removeAttribute('$linbid');
                else
                    delete v.$linbid;
            }

            //clear event handler
            if(id=v.id){
                //clear dom cache
                //trigger object __gc
                if(id in proMap){
                     o=proMap[id];
                     if(!o)continue;
                     t=o.renderId;
                     if('!window'===t||'!document'===t)continue;

                     //don't trigger any innerHTML or removeChild in __gc()
                     o.__gc();
                     //clear the cache
                     bak[bak.length]=i;
                     //clear the cache shadow
                     if(o.$domId && o.$domId!=o.domId)
                        bak[bak.length]=o.$domId;
                }
            }
         }
         //clear dom cache
         for(i=0;i<bak.length;)
             delete proMap[bak[i++]];
         //clear dom content
		 //while(node.firstChild)
		 //   node.removeChild(node.firstChild);
         node.innerHTML='';
    },

    //create:function(tag, properties, events, host){
    create:function(tag){
        var arr,o,t,me=arguments.callee,r1=me.r1||(me.r1=/</);
        if(typeof tag == 'string'){
            //Any class inherited from linb.absBox
            if(t=linb.absBox.$type[tag]){
                arr=[];
                //shift will crash in opera
                for(var i=1,l=arguments.length;i<l;i++)
                    arr[i-1]=arguments[i];
                o =new (linb.SC(t))(false);
                if(o._ini)o._ini.apply(o, arr);
            //from HTML string
            }else if(r1.test(tag))
                o = _.str.toDom(tag);
            //from HTML element tagName
            else{
                o=document.createElement(tag);
                o.id = typeof id=='string'?id:_.id();
                o=linb(o);
            }
        //Any class inherited from linb.absBox
        }else
            o =new (linb.SC(tag.key))(tag);
        return o;
    },
    use:function(linbid){
        var c=linb._tempBox||(linb._tempBox=linb()), n=c._nodes;
        n[0]=linbid;
        if(n.length!=1)n.length=1;
        return c;
    }
});

/* linb.ini linb.browser dom ready
*/
new function(){
    //browser sniffer
    var w=window, u = navigator.userAgent.toLowerCase(), d=document, b=linb.browser={
        kde:/webkit/.test(u),
        opr:/opera/.test(u),
        ie:/msie/.test(u) && !/opera/.test(u),
        gek:/mozilla/.test(u) && !/(compatible|webkit)/.test(u),

        isWin:/(windows|win32)/.test(u),
        isMac:/(macintosh|mac os x)/.test(u),
        isAir:/adobeair/.test(u),
        isLinux:/linux/.test(u),
        isSecure:location.href.toLowerCase().indexOf("https")==0
    },v=function(k,s){return k + (b.ver=u.split(s)[1].split('.')[0])};
    _.filter(b,function(o){return !!o});
    if(b.ie){
        b[v('ie','msie ')]=true;
        if(b.ie6){
            //ex funs for ie6
            try {document.execCommand('BackgroundImageCache', false, true)}catch(e){}
            w.XMLHttpRequest = function(){return new ActiveXObject("Msxml2.XMLHTTP")};
        }
    }else if(b.gek)
        b[v('gek','firefox/')]=true;
    else if(b.opr)
        b[v('opr','opera/')]=true;
    else if(b.kde)
        b[v('kde','webkit/')]=true;

    b.contentBox = function(n){
        return (b.ie||b.opr) ?
                !/BackCompat|QuirksMode/.test(d.compatMode) :
                (n = (n=n||d.documentElement).style["-moz-box-sizing"] || n.style["box-sizing"]) ? (n=="content-box") : true;
    }();

    var ini=linb.ini={};
    //special var
    if(window.linb_ini)
        _.merge(ini,window.linb_ini);

    if(!ini.path){
        var s,arr = document.getElementsByTagName('script'), reg = /js\/linb(-[\w]+)?\.js$/,l=arr.length;
        while(--l>=0){
            s=arr[l].src;
            if(s.match(reg)){
                ini.path = s.replace(reg,'');
                break;
            }
        }
    }
    _.merge(ini,{
        appPath:location.href.split('?')[0].replace(/[^\\\/]+$/,''),
        file_bg:ini.path+'bg.gif',
        dummy_tag:'$_dummy_$'
    });
    if(!ini.path)
        ini.path=ini.appPath+'/jsLinb';


    //for dom ready
    var f = function(){
        if(d.addEventListener && !b.kde)
            d.removeEventListener("DOMContentLoaded",arguments.callee,false);
        try{
            for(var i=0,l=linb._m.length;i<l;i++)
                _.tryF(linb._m[i])
            linb._m.length=0;
            linb.isDomReady=true;
        }catch(e){
            _.asyRun(function(){throw e})
        }
    };

    /* for Mozilla/Opera9 */
    if (d.addEventListener && !b.kde)
        d.addEventListener("DOMContentLoaded", f, false);
    //for ie
    else if (b.ie)
        (function(){try{
            //for ie7 iframe(doScroll is always ok)
            d.activeElement.id;
            d.documentElement.doScroll('left');f()}catch(e){setTimeout(arguments.callee,1)}})();
    //kde
    else
        (function(){/loaded|complete/.test(d.readyState)?f():setTimeout(arguments.callee,1)})()
};

/*linb.Thread
*  dependency: _ ; Class ; linb
parameters:
id: id of this thread, if input null, thread will create a new id
tasks: [task,task,task ...] or [{},{},{} ...]
    task: function
    or
    {
      task,      //function
      args,      //args array for task
      scope,     //this object for task
      delay ,    //ms number
      callback   //function for callback
   }
delay:default delay time;
callback:default calback function;
onStart: on start function
onEnd: on end function
cycle: is the thread circular
*/
Class('linb.Thread',null,{
    Constructor:function(id, tasks, delay, callback, onStart, onEnd, cycle){
        //for api call directly
        var self=this,me=arguments.callee,t=linb.$cache.thread;
        // linb.Thread() => self.constructor!==me
        // in an inner method => !!self.id is true
        if(self.constructor!==me || !!self.id)
            return new me(id, tasks, delay, callback, onStart, onEnd, cycle);

        if(typeof id!='string')id='$' + (self.constructor.$linbid++);
        self.id=id;
        //thread profile
        self.profile = t[id] || (t[id] = {
            id:id,
            _start:false,
            time:0,
            _left:0,
            _asy:-1,
            //sleep_flag:-1,
            index:0,

            tasks:tasks||[],
            delay: delay || 0,
            callback:callback,
            onStart:onStart,
            onEnd:onEnd,
            cache:{},
            status:"run",
            cycle:!!cycle
        });
    },
    Instance:{
        _fun:_.fun(),
        __gc:function(){
            var m=linb.$cache.thread,t=m[this.id];
            if(t){
                delete m[this.id];
                t.tasks.length=0;
                for(var i in t)t[i]=null;
            }
        },
        _task:function(){
            var self=this,p=self.profile,t={args:[]}, value=p.tasks[p.index],r,i,type=typeof value;
            p._asy=-1;

            //maybe aborted
            if(!p.status)return;

            //function
            if(type=='function') t.task=value;
            //hash
            else if(type=='object')
                for(i in value) t[i]=value[i];
            //others, give all default

            //defalut task
            if(typeof t.task!='function')t.task=self._fun;
            //default callback
            if(typeof t.callback!='function')t.callback=p.callback

            //last arg is threadid
            t.args.push(p.id);
            //to next pointer
            p.index++;
            p.time=_();
            //if error raise in the process, abort the thread
            //try{
                r = _.tryF(t.task, t.args || [p.id], t.scope||self, null);
                //called abort in [task]
                if(!p.status)return;

                //cache return value
                if(t.id)p.cache[t.id] = r;
                // call back function
                // if callback return false, stop.
                if(t.callback)
                    if(false===_.tryF(t.callback, [p.id], self, true)){
                      self.abort();
                      return;
                    }
                //called suspend in [task]
                if(p.status!=="run")return;
            //}catch(e){
           //     self.abort();
            //    linb.Debugger && linb.Debugger.trace(e);
           // }
            // if set Sleep at t.task or t.callback , stop continue running
            if(!p || p.status!=="run")return;
            self.start();
        },
        start:function(time){
            var self=this, p=self.profile, task,delay;
            if(p._start===false){
                p._start=true;
                //call onstart
                if(false===_.tryF(p.onStart,[p.id],self))
                    return self.abort();
            }
            if(!p.tasks.length)return self.abort();
            if(p.index>=p.tasks.length)
                if(p.cycle===true)
                    self.profile.index = 0;
                else
                    return self.abort();
            task=p.tasks[p.index];

            delay=typeof task=='number'?task:typeof task.delay=='number'?task.delay:p.delay;
            p._left= (time || time===0)?time:delay;

            if(p._asy!=-1)clearTimeout(p._asy);
            p._asy = _.asyRun(self._task, p._left, [], self);
            p.time=_();
            return self;
        },
        suspend:function(){
            var n,p=this.profile;
            if(p.status=="pause")return;
            p.status="pause";
            if(p._asy!==-1){
                clearTimeout(p._asy);
                if(p.index>0)p.index--;
            }
            n=p._left-(_() - p.time);

            p._left=(n>=0?n:0);
            return this;
        },
        /*time
        number:set timeout to number
        true:set timeout to default
        false:set timeout to 0
        undefined: timetou to left
        */
        resume:function(time){
            var self=this;
            if(self.profile.status=="run")return;

            time = time===undefined ? self.profile._left :
                        time===true ? self.profile.delay :
                        time===false ? 0 :
                        (Number(time) || 0);

            self.profile.status="run";
            self.start(time);
            return self;
        },
        abort:function(){
            var t=this.profile;
            t.status="stop";
            clearTimeout(t._asy);
            _.tryF(t.onEnd, [t.id]);
            this.__gc();
        },
        links:function(thread){
            var p=this.profile, onEnd=p.onEnd, id=p.id;
            p.onEnd=function(){_.tryF(onEnd,[id]); thread.start()};
            return this;
        },
        insert:function(arr, index){
            var self=this,o=self.profile.tasks,l=o.length,a;
            if(arr.constructor!=Array)arr=[arr];
            index= index || self.profile.index;
            if(index<0 || index>l)index=l;
            a=o.splice(index,l-index);
            o.push.apply(o, arr);
            o.push.apply(o, a);
            return self;
        },
        getCache:function(key){
            return this.profile.cache[key];
        },
        setCache:function(key,value){
            this.profile.cache[key] = value;
            return this;
        },
        isAlive:function(){
            return !!linb.$cache.thread[this.id];
        }
    },
    After:function(){
        /*
        give shortcut to some functions
        */
        var self=this, f=function(i){
            self[i]=function(id){
                var t;
                if(linb.$cache.thread[id])
                    (t=linb.Thread(id))[i].apply(t,Array.prototype.slice.call(arguments,1));
            }
        },
        a = 'start,suspend,resume,abort'.split(',');
        for(var i=0,l=a.length;i<l;i++)f(a[i]);
    },
    Static:{
        $linbid:1,
        __gc : function(){
            linb.$cache.thread={};
        },
        isAlive:function(id){
            return !!linb.$cache.thread[id];
        },
        //Dependency: linb.Dom
        observableRun:function(tasks,onEnd,threadid){
            var thread=linb.Thread, dom=linb.Dom;
            if(!_.isArr(tasks))tasks=[tasks];
            //if thread exists, just inset task to the next positiong
            if(linb.$cache.thread[threadid]){
                if(typeof onEnd=='function')
                    tasks.push(onEnd);
                thread(threadid).insert(tasks);
            //if does not exist, create a new thread
            }else{
                thread(threadid, tasks,
                    0,null,
                    //set busy status to UI
                    function(threadid){
                        if(dom)dom.busy(threadid)
                    },
                    //set free status to UI
                    function(threadid){
                        _.tryF(onEnd,arguments,this);
                        if(dom)dom.free(threadid)
                    }
                ).start();
            }
        },
        /*group thread run once
        group: hash include thread or threadid
        callback: call after a thread finish
        onStart:before all threads start
        onEnd:after all threads end
        */
        group:function(id, group, callback,onStart,onEnd){
            var bak={},
                thread=linb.Thread,
                f=function(o,i,threadid){
                    if(typeof o == 'string')o=thread(o);
                    if(o){
                        var f = function(){
                            var me=arguments.callee;
                            _.tryF(me.onEnd,arguments,this);
                            me.onEnd=null;
                            delete bak[i];
                            //call callback here
                            _.tryF(callback,[i, threadid],this);
                            if(_.isEmpty(bak))
                                thread.resume(threadid);
                        };
                        f.onEnd = o.profile.onEnd;
                        o.profile.onEnd = f;
                        o.start();
                    }
                };
            for(var i in group)bak[i]=1;
            return thread(id, [function(threadid){
                if(!_.isEmpty(group)){
                    thread.suspend(threadid);
                    for(var i in group)f(group[i],i, threadid);
                }
            }],0,null,onStart,onEnd);
        },
        repeat:function(task, interval, onStart, onEnd){
            return linb.Thread(null,[_.fun()],interval||0,task,onStart,onEnd,true).start();
        }
    }
});


/*linb.absIO/ajax
*  dependency: _ ; Class ; linb ; linb.Thread
*/
/*
        get     post    get(cross domain)   post(corss domain)  post file   return big data(corss domain)
ajax    +       +       -                   -                   -           -
sajax   +       -       +                   -                   -           *
iajax   +       +       +                   *                   *           *
*/
Class('linb.absIO',null,{
    Constructor:function(uri, query, onSuccess, onFail, threadid, options){
        //get properties
        if(typeof uri=='object')
            options=uri;
        else{
            options=options||{};
            _.merge(options, {
                uri:uri,
                query:query,
                onSuccess:onSuccess,
                onFail:onFail,
                threadid:threadid
            });
        }
        //for cache
        var self=this,  me=arguments.callee,con=self.constructor;
        if((con !== me) || self.id)
            return new me(options);

        //give defalut value to those members
        _.merge(options,{
            id : options.id || (_()+ '' +(con._id++)),
            uri : options.uri||'',
            query : options.query||'',
            asy : options.asy!==false,
            method : 'POST'==(options.method||con.method).toUpperCase()?'POST':'GET'
        },'all');
        var a='retry,timeout,reqType,rspType,customQS'.split(',');
        for(var i=0,l=a.length;i<l;i++)
            options[a[i]] = (a[i] in options)?options[a[i]]:con[a[i]];

        _.merge(self, options, 'all');

        if(self.reqType=='xml')
            self.method="POST";

        if(con.events)
            _.merge(self, con.events);

        self.query = self.customQS(self.query);

        if(!self._useForm && typeof self.query!='string' && self.reqType!="xml")
            self.query = con._buildQS(self.query, self.reqType=="json",self.method=='POST');

        return self;
    },
    Instance:{
        _fun:_.fun(),
        _flag:0,
        _response:'',
        _retryNo:0,
        inProcessing:false,

        _time:function() {
            var self=this,c=self.constructor;
            self._clear();
            if (self._retryNo < self.retry) {
                self._retryNo++;
                _.tryF(self.onRetry,[self._retryNo],self);
                self.start();
            }else{
                _.tryF(self.onTimeout,[],self);
                self._onError(new Error("errTimout"));
            }
        },
        _onEnd:function(){
            var self=this;
            if(!self._end){
                self._end=true;
                if(self._flag>0){
                    clearTimeout(self._flag);
                    self._flag=0
                }
                linb.Thread.resume(self.threadid);
                _.tryF(self.onEnd,[],self);
                self._clear();
            }
        },
        _onStart:function(){
            var self=this;
            linb.Thread.suspend(self.threadid);
            _.tryF(self.onStart,[],self);
        },
        _onResponse:function(){
            var self=this;
            if(false!==_.tryF(self.beforeSuccess,[self._response, self.rspType, self.threadid], self))
                _.tryF(self.onSuccess,[self._response, self.rspType, self.threadid], self);
            self._onEnd();
        },
        _onError:function(e){
            var self=this;
            if(false!==_.tryF(self.beforeFail,[e, self.threadid],self))
                _.tryF(self.onFail,[String(e), self.rspType, self.threadid], self);
            self._onEnd();
        },
        isAlive:function(){
            return !this._end;
        },
        abort:function(){
            this._onEnd();
        }
    },
    Static:{
        $abstract:true,
        _id:1,
        method:'GET',
        retry:2,
        timeout:60000,
        //form, xml, or json
        reqType:'form',
        //text or xml
        rspType:'text',

        //paras in request object
        type:'type',
        randkey:'id',
        callback:'callback',

        _buildQS:function(hash, flag, post){
            return flag?((flag=_.serialize(hash))&&(post?flag:encodeURIComponent(flag))):_.urlEncode(hash);
        },
        customQS:function(obj){
            return obj;
        },
        _if:function(doc,id,onLoad){
            var e=linb.browser.ie,n = doc.createElement(e?"<iframe name='"+id+"' "+(onLoad?"onload='linb.IAjax._o(\""+id+"\")'":"")+">":"iframe"),w;
            if(id)n.id=n.name=id;
            if(!e&&onLoad)n.onload=onLoad;
            n.style.display = "none";
            doc.body.appendChild(n);
            w=frames[frames.length-1];
            return [n,w,w.document];
        },
        isCrossDomain:function(uri){
            uri=uri||'';
            var me=arguments.callee,
                r=me.r || (me.r=/(http(s)?\:\/\/)?([\w\.]+(:[\d]+)?)(.*)/),t;
            if((t=uri.indexOf(':'))==-1||t>uri.indexOf('/'))return false;
            if(uri.indexOf('file:')===0)return !!location.host;
            return  location.host != uri.replace(r,'$3')
        },
        //get multi ajax results once
        groupCall:function(hash, callback, onStart, onEnd, threadid){
            var i,f=function(o,i,hash){
                hash[i]=linb.Thread(null,[function(threadid){
                    o.threadid=threadid;
                    o.start();
                }]);
            };
            for(i in hash)f(hash[i],i,hash);
            return linb.Thread.group(null, hash, callback, function(){
                linb.Thread(threadid).suspend();
                _.tryF(onStart,arguments,this);
            }, function(){
                _.tryF(onEnd,arguments,this);
                linb.Thread(threadid).resume();
            }).start();
        }
    }
});
Class('linb.Ajax','linb.absIO',{
    Instance:{
        _XML:null,
        start:function() {
            var self=this;
            if(false===_.tryF(self.beforeStart,[],self)){
                self._onEnd();
                return;
            }
            if (!self._retryNo)
                self._onStart();
            try {
                with(self){
                    //must use "self._XML", else opera will not set the new one
                   self._XML = new window.XMLHttpRequest();
                   if(asy)
                       self._XML.onreadystatechange = function(){
                           if(self && self._XML && self._XML.readyState==4) {
                               /*//Checking responseXML for Terminated unexpectedly in firfox
                               if(linb.browser.gek && !self._XML.responseXML)
                                    self._onError(new Error('errXMLHTTP:Terminated unexpectedly!'));
                               else*/
                                   self._complete.apply(self);
                               //must clear here, else memory leak
                               self._clear();
                           }
                       };

                    if (!_retryNo && method != "POST"){
                        if(query)
                            uri = uri.split("?")[0] + "?" + query;
                        query=null;
                    }

                    self._XML.open(method, uri, asy);
                    
                    if(method=="POST")
                        self._XML.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
                        
                    self._XML.setRequestHeader("X-Requested-With", "XMLHttpRequest");

                    

                    //for firefox syc GET bug
                    try{self._XML.send(query);}catch(e){}

                    if(asy){
                      if(self._XML&&timeout > 0)
                        _flag = _.asyRun(function(){if(self && !self._end){self._time()}}, self.timeout);
                    }else
                        _complete();
                }
            }catch(e){
                self._onError(e);
            }
            return self;
        },
        abort:function(){
            var self=this;
            if(self._XML){
                self._XML.onreadystatechange=self._fun;
                self._XML.abort();
                self._XML=null;
            }
            arguments.callee.upper.call(self);
        },
        _clear:function(){
            var self=this;
            if(self._XML){
                self._XML.onreadystatechange=self._fun;
                self._XML=null;
            }
        },
        _complete:function() {
            with(this){
                //this is for opera
                var ns=this,status = ns._XML.status;
                _response = rspType=='text'?ns._XML.responseText:ns._XML.responseXML;
                if(status===undefined || status===0 || status==304 || (status >= 200 && status < 300 ))
                    _onResponse();
                else
                    _onError(new Error('errXMLHTTP:' +status));
            }
        }
    }
});
Class('linb.SAjax','linb.absIO',{
    Instance:{
        start:function(){
            var self=this,id,c=self.constructor, t, n, ok=false;
            if(false===_.tryF(self.beforeStart,[],self)){
                self._onEnd();
                return;
            }
            if(!self._retryNo)
                self._onStart();
            //dont retry for loading script
            if(self.rspType=='script')
                self.retry=0;

            //first
            id=self.id;
            if(c._pool[id])
                c._pool[id].push(self);
            else
                c._pool[id]=[self];

            var w=c._n=document,
                _cb=function(){
                    if(!ok){
                        ok=true;
                        if(self.rspType=='script'){
                            if(typeof self.checkKey=='string')
                                _.asyRun(function(){
                                    _.exec("if(linb.SC.get('"+self.checkKey+"'))linb.SAjax._pool['"+id+"'][0]._onResponse();" +
                                        "else linb.SAjax._pool['"+id+"'][0]._loaded();");
                                });
                            else
                                self._onResponse();
                        }else
                            self._loaded();
                    }
                };
            n = self.node = w.createElement("script");
            n.src = self.uri + (self.query?'?'+self.query:'');
            n.type= 'text/javascript';
            n.charset='utf-8';
            n.id='linb:script:'+self.id;
            n.onload = n.onreadystatechange = function(){
                if(ok)
                    return;
                var t=this.readyState;
                if(!t || t == "loaded" || t == "complete")
                    _cb();

                if(t=='interactive' && linb.browser.opr){
                    linb.Thread.repeat(function(){
                        if(ok)
                            return false;
                        if (/loaded|complete/.test(document.readyState)) {
                            _cb();
                            return false;
                        }
                    },50);
                }
            };

            if(linb.browser.gek)
                n.onerror=_cb;

            //w.getElementsByTagName("head")[0].appendChild(n);
            w.body.appendChild(n);

            n=null;

            //set timeout
            if(self.timeout > 0)
                self._flag = _.asyRun(function(){if(self && !self._end){self._time()}}, self.timeout);
        },
        _clear:function(){
            var self=this, n=self.node, c=self.constructor,_pool=self.constructor._pool;
            _pool.length=0;
            delete _pool[self.id];
            if(n){
                self.node=n.id=n.onload=n.onreadystatechange=n.onerror=null;

                var div=c._n.createElement('div');
                //in ie + add script with url(remove script immediately) + add the same script(remove script immediately) => crash
                //so, always clear it later
                div.appendChild(n.parentNode&&n.parentNode.removeChild(n)||n);
                if(linb.browser.ie)
                    _.asyRun(function(){div.innerHTML=n.outerHTML='';n=div=null;});
                else{
                    div.innerHTML='';
                    n=div=null;
                }
            }
        },
        _loaded:function(){
            var self=this;
            _.asyRun(function(){
                if(self.id && self.constructor._pool[self.id])
                    self._onError(new Error("errInData"));
            },500);
        }
    },
    Static : {
        _pool:{},
        $response:function(obj) {
            var self=this;
            try{
                if(obj && (o = self._pool[obj[self.randkey]])){
                    for(var i=0,l=o.length;i<l;i++){
                        o[i]._response=obj;
                        o[i]._onResponse();
                    }
                }else
                    self._onError(new Error("errInData:"+obj));
            }catch(e){
                linb.Debugger && linb.Debugger.trace(e);
            }
        },
        customQS:function(obj){
            var c=this.constructor, t=c.type, k=c.randkey, b=c.callback,nr=(this.rspType!='script'),rand=nr?k + '=' + this.id + '&type=script&':'';
            if(typeof obj=='string')
                return (obj && obj + '&') + rand + (nr?b + '=linb.SAjax.$response':'');
            else{
                if(nr){
                    obj[t]='script';
                    obj[k]=this.id;
                    obj[b]="linb.SAjax.$response";
                }
                return obj;
            }
        }
    }
});
Class('linb.IAjax','linb.absIO',{
    Instance:{
        _useForm:true,
        $e:function(s){this._onError(new Error("errInData:"+s));},
        start:function(){
            var self=this,c=self.constructor, i, id, t, n, k, o, b, form,onload;
            if(false===_.tryF(self.beforeStart,[],self)){
                self._onEnd();
                return;
            }
            if (!self._retryNo)
                self._onStart();

            //first
            id=self.id;
            if(c._pool[id])
                c._pool[id].push(self);
            else
                c._pool[id]=[self];
            //use window.name
            self._onload = onload = function(id){
                //in some situation, this function will be triggered twice.
                //in IE/opera, "setting an image file as dummy" will trigger the second onload event with 'self.node == null'
                if(!self.node)return;
                var w=self.node.contentWindow,c=linb.IAjax,o,t;
                //in opera, "set location" will trigger location=='about:blank' at first
                if(linb.browser.opr)try{if(w.location=='about:blank')return}catch(e){}
                try{
                    w.location=c._getDummy()+'#'+linb.ini.dummy_tag;
                    if(w.name==self.id)
                        self.$e('no response');
                    else{
                        try{
                            o=_.unserialize(decodeURIComponent(w.name));
                            if(o&&(t=c._pool[o[c.randkey]]))
                                for(var i=0,l=t.length;i<l;i++){
                                    t[i]._response=o;
                                    t[i]._onResponse();
                                }
                            else
                                self.$e(w.name);
                         }catch(a){
                            self.$e(w.name);
                         }
                    }
                }catch(e){}
            };

            //create form
            var a=c._if(document,id, onload);
            self.node=a[0];
            self.frm=a[1];
            //create form
            form = self.form = document.createElement('form');
            form.style.display='none';
            form.action=self.uri;
            form.method=self.method;
            form.target=id;

            k=self.query||{};
            for(i in k){
                if(k[i] && k[i].nodeName=="INPUT"){
                    k[i].id=k[i].name=i;
                    form.appendChild(k[i]);
                    b=true;
                }else{
                    t=document.createElement('input');
                    t.id=t.name=i;
                    t.value= typeof k[i]=='string'?k[i]:_.serialize(k[i]);
                    form.appendChild(t);
                }
            }
            if(self.method=='POST' && b){
                form.enctype = 'multipart/form-data';
                if(form.encoding)
                    form.encoding = form.enctype;
            }
            document.body.appendChild(form);
            //submit
            form.submit();

            t=form=null;
            //set timeout
            if(self.timeout > 0)
                self._flag = _.asyRun(function(){if(self && !self._end){self._time()}}, self.timeout);
        },
        _clear:function(){
            var self=this, n=self.node,f=self.form, c=self.constructor, div=document.createElement('div');
			if(linb.browser.gek&&n)try{n.onload=null;var d=n.contentWindow.document;d.write(" ");d.close()}catch(e){}
            self.form=self.node=self.frm=null;
            clearTimeout(self._tf);
            if(n)div.appendChild(n.parentNode.removeChild(n));
            if(f)div.appendChild(f.parentNode.removeChild(f));
            div.innerHTML='';
            f=div=null;
        }
    },
    Static : {
        method:'POST',
        _pool:{},
        _o:function(id){
            var self=this,p=self._pool[id],o=p[p.length-1];
            _.tryF(o._onload);
        },
        _getDummy:function(win){
            win=win||window;
            var ns=this,
                arr,o,
                d=win.document,
                ini=linb.ini,
                b=linb.browser,
                f=ns.isCrossDomain;
            if(ns.dummy)return ns.dummy;
            //can get from linb.ini;
            if(ini.dummy)return ns.dummy=ini.dummy;
            if(b.gek){
                arr=d.getElementsByTagName("link");
                for(var i=0,j=arr.length; i<j; i++){
                    o = arr[i];
                    if (o.rel == "stylesheet" && !f(o.href))
                        return ns.dummy=o.href.split('#')[0];
                }
            }
            if(!f(ini.path)){
                //not for 'ex-domain include jslinb' case
                if(!d.getElementById('linb:img:bg')){
                    o=d.createElement('img');
                    o.id='linb:img:bg';
                    o.src=ini.file_bg;
                    o.style.display='none';
                    d.body.appendChild(o);
                    o=null;
                }
            }
            arr=d.getElementsByTagName("img");
            for(var i=0,j=arr.length; i<j; i++){
                o = arr[i];
                if(!f(o.src))
                    return ns.dummy=o.src.split('#')[0];
            }
            //get from parent, not for opera in this case
            try{
                if(win!=win.parent)
                    if((win=win.parent) && !f(''+win.document.location.href))
                        return ns._getDummy(win);
            }catch(e){}
            //for the last change, return a file name whether it existes or does not exist, and not cache it.
            return '/favicon.ico';
        },
        customQS:function(obj){
            var s=this,c=s.constructor,t=c.type;
            obj[t]='iframe';
            obj[c.randkey]=s.id;
            return obj;
        }
    }
});

/*linb.SC for straight call
*  dependency: _ ; Class ; linb ; linb.Thread ; linb.absIO/ajax
*/
Class('linb.SC',null,{
    Constructor:function(path, callback, isAsy, threadid, options){
        var p = linb.$cache.SC,r;
        if(r=p[path]||(p[path]=_.get(window,path.split('.'))))
            _.tryF(callback,[path,null,threadid],r);
        else{
            options=options||{};
            options.$cb=callback;
            if(isAsy)options.threadid=threadid;
            r=p[path]=linb.SC._call(path||'', options, isAsy);
        }
        return r;
    },
    Static:{
        __gc:function(k){
            linb.$cache.SC={};
        },

        //get object from obj string
        get : function (path, obj){
            return _.get(obj||window,(path||'').split('.'));
        },
        /* function for "Straight Call"
        *   asy     loadSnips use
        *   true    true    ajax
        *   true    false   sajax
        *   false   ture    ajax
        *   false   false   ajax
        */
        _call : function (s, options, isAsy){
            isAsy = !!isAsy;
            var i,t,r,o,funs=[],ep=linb.SC.get,ct=linb.$cache.snipScript,
            f= function(text,n,threadid){
                var self=this;
                if(text){
                    //test again when asy end.
                    if(!ep(s)){
                        //loadSnips only
                        if(self.$p)
                            (self.$cache || ct)[self.$tag]=text;
                        else
                            //for sy xmlhttp ajax
                            try{_.exec(text)}catch(e){throw new Error('errInEval:"'+e + self.$tag)}
                    }
                }
                _.tryF(self.$cb,[self.$tag,text,threadid],ep(s)||{});
            },fe=function(text){
                var self=this;
                //for loadSnips resume with error too
                _.tryF(self.$cb,[null,null,self.threadid],self);
            };
            //get from object first
            if(!(r=ep(s))){
                //if script in cache
                if(t=ct[s]){
                    isAsy=false;
                    f.call({$cb: options.$cb},t);
                    //delete it
                    delete ct[s];
                }
                //get from object second
                if(!(r=ep(s))){
                     //load from sy ajax
                     o=linb.getPath(s,'.js','js');
                     options = options ||{};
                     options.$tag = s;
                     var ajax;
                     //asy and not for loadSnips
                     if(isAsy && !options.$p){
                        options.rspType="script";
                        ajax=linb.SAjax;
                     }else{
                        options.asy=isAsy;
                        ajax=linb.Ajax;
                    }
                    //get text from sy ajax
                    ajax(o, "", f, fe, null, options).start();
                    //for asy once only
                    if(!isAsy)
                        r=ep(s);
                }
            }else
                if(options.$cb)
                    f.call(options);
            return r;
        },
        /*
        arr: key array, ['linb.UI.Button','linb.UI.Input']
        callback: fire this function after all js loaded
        */
        loadSnips:function(pathArr,cache,callback,onEnd,threadid){
            if(!pathArr || !pathArr.length){
                _.tryF(onEnd,[threadid]);
                return;
            }
            var bak={}, options={$p:1,$cache:cache||linb.$cache.snipScript};
            for(var i=0,l=pathArr.length;i<l;i++)
                bak[pathArr[i]]=1;

            if(callback||onEnd){
                options.$cb=function(path){
                    //give callback call
                    if(callback)_.tryF(callback,arguments,this);
                    delete bak[path||this.$tag];
                    if(_.isEmpty(bak)){
                        _.tryF(onEnd,[threadid]);
                        onEnd=null;
                        linb.Thread.resume(threadid);
                    }
                };
            }
            linb.Thread.suspend(threadid);
            for(var i=0,s; s=pathArr[i++];)
                this._call(s, _.merge({$tag:s},options), true);
        },
        runInBG:function(pathArr, callback, onStart, onEnd){
            var i=0,j,t,self=this,fun=function(threadid){
                while(pathArr.length>i && (t=self.get(j=pathArr[i++])));
                if(!t)
                    self._call(j, {threadid:threadid},true);
                //set abort function to the next step
                if(pathArr.length<i)
                    linb.Thread(threadid).abort();
                if(pathArr.length==i)i++;
            };
            linb.Thread(null, [fun], 1000, callback, onStart, onEnd, true).start();
        },
        execSnips:function(cache){
            var i,h=cache||linb.$cache.snipScript;
            for(i in h)
                try{_.exec(h[i])}catch(e){throw new Error('errInEval:"'+e)}
            h={};
        },
        //asy load multi js file, whatever dependency
        /*
        *1.busy UI
        *3.linb.SC.groupCall some js/class
        *4.resume thread
        *5.linb.SC.loadSnips other js/class
        *6.execute other ..
        *7.free UI
        */
        groupCall:function(pathArr, callback, onEnd, threadid){
            if(pathArr){
                //clear first
                var self=this;
                self.execSnips();
                linb.Thread.suspend(threadid);
                self.loadSnips(pathArr, 0, callback, function(){
                    self.execSnips();
                    _.tryF(onEnd,[threadid]);
                    onEnd=null;
                    linb.Thread.resume(threadid);
                });
            }else
                _.tryF(onEnd,[threadid]);
        }
    }
});

/*serialize/unserialize
*/
new function(){
    var
    max,
    M ={
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '"' : '\\"',
        '\\': '\\\\'
    },
    H={'@window':'window','@this':'this'},
    A=/[\x00-\x1f\x7f-\x9f\\\"]/g,
    C=/^\s*\x7b/, // /^\s*\{/,
    D=/^(-\d+|\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?((?:[+-](\d{2}):(\d{2}))|Z)?$/,
    E=function(t,i,a,v,m,n){
        for(i in t)
            if((a=typeof (v=t[i]))=='string' && (v=D.exec(v))){
                m=v[8]&&v[8].charAt(0);
                if(m!='Z')n=(m=='-'?-1:1)*((+v[9]||0)*60)+(+v[10]||0);
                else n=0;
                m=new Date(+v[1],+v[2]-1,+v[3],+v[4],+v[5],+v[6],+v[7]||0);
                n-=m.getTimezoneOffset();
                if(n)m.setTime(m.getTime()+n*60000);
                t[i]=m;
            }else if(a=='object' &&a.constructor===Object) E(t[i]);
        return t;
    },
    R=function(n){return n<10?'0'+n:n},

    F='function',
    N='number',
    L='boolean',
    S='string',
    O='object',
    T={},
    S16=function(b){return Math.floor(b/16).toString(16)+(b%16).toString(16)},
    MS=function(x,s){return '.'+((s=x[s]())?s<10?'00'+s:s<100?'0'+s:s:'000')},
    Z=(function(a,b){a=-(new Date).getTimezoneOffset()/60; b=a>0?'+':'-'; a=''+Math.abs(a); return b+a+(a.length==1?'0':'')+':00'})();
    T['undefined']=function(){return 'undefined'};
    T[L]=function(x){return String(x)};
    T[N]=function(x){return isFinite(x) ? String(x) : 'null'};
    T[S]=function(x){
        return H[x] ||
            '"' +
            (
            A.test(x)
            ?
            x.replace(A, function(a,b) {
                if(b=M[a])return b;
                b=a.charCodeAt();
                return '\\u00' + S16(b)
            })
            :
            x
            )
            + '"'
    };
    T[O]=function(x,filter,dateformat,deep){
        var me=arguments.callee, map = me.map || (me.map={prototype:1,constructor:1,toString:1,valueOf:1});
        deep=deep||1;
        if(deep>99||max>9999)return '"too much recursion!"';
        max++;
        if (x){
            var a=[], b=[], c=x.constructor, f, i, l, v;
            if(x===window)return "window";
            if(x===document)return "document";
            //for ie alien
            if((typeof x==O || typeof x==F) && typeof c != F)
                return x.nodeType? "document.getElementById('"+x.id+"')" :"$alien";
            else if(c==Array){
                a[0] = '[';
                l = x.length;
                for(i=0;i<l;++i){
                    if(typeof filter=='function' && false==filter.call(x,x[i],i))continue;

                    if(f=T[typeof (v=x[i])])
                        if(typeof (v=f(v,filter,dateformat,deep+1))==S)
                            b[b.length]=v;
                }
                a[2]=']';
            }else if(c==Date){
                if(dateformat=='utc')
                    return '"'+ x.getUTCFullYear() + '-' +
                        R(x.getUTCMonth() + 1) + '-' +
                         R(x.getUTCDate()) + 'T' +
                         R(x.getUTCHours()) + ':' +
                         R(x.getUTCMinutes()) + ':' +
                         R(x.getUTCSeconds()) +
                         MS(x,'getUTCMilliseconds')+
                         'Z"';
                else if(dateformat=='gmt')
                    return '"'+ x.getFullYear() + '-' +
                        R(x.getMonth() + 1) + '-' +
                         R(x.getDate()) + 'T' +
                         R(x.getHours()) + ':' +
                         R(x.getMinutes()) + ':' +
                         R(x.getSeconds()) +
                         MS(x,'getMilliseconds')+
                         Z+'"';
                else
                    return 'new Date('+[x.getFullYear(),x.getMonth(),x.getDate(),x.getHours(),x.getMinutes(),x.getSeconds(),x.getMilliseconds()].join(',')+')';
            }else if(c==RegExp){
                return String(x);
            }else{
                if(typeof x.serialize == F)
                    x = x.serialize();
                if(typeof x==O){
                    if(x.nodeType){
                        return "document.getElementById('"+x.id+"')";
                    }else{
                        a[0] = '{';
                        for(i in x){
                            if(map[i] ||
                                (filter===true?i.charAt(0)=='_':typeof filter=='function'?false===filter.call(x,x[i],i):0))
                                continue;
                            if (f=T[typeof (v=x[i])])
                                if (typeof (v=f(v,filter,dateformat,deep+1))==S)
                                    b[b.length] = T.string(i) + ':' + v;
                        }
                        a[2]='}';
                    }
                }else return String(x);
            }
            a[1]=b.join(', ');
            return a[0]+a[1]+a[2];
        }
        return 'null'
    };
    T[F]=function(x){return x.$path?x.$path:String(x)};

    //serialize object to string (bool/string/number/array/hash/simple function)
    _.serialize = function (obj,filter,dateformat){
        max=0;
        return T[typeof obj](obj,filter,dateformat)||'';
    };
    //unserialize string to object
    _.unserialize = function(str, dateformat){
        try{
            str=eval(C.test(str) ? '('+str+')' : str);
            if(dateformat){if(typeof str==='object')E(str);else if(typeof str==='string')return E({a:str}).a}
            return str;
        }catch(e){
            return false;
        }
    };
};

/*26 based id, some number id can crash opera9
*/
_.id=function(){
    var self=this, me=arguments.callee;
    if(self.constructor!==me || self.a)
        return (me._ || (me._= new me)).next();
    self.a=[-1];
    self.b=[''];
    self.value='';
};
_.id.prototype = {
    constructor:_.id,
    _chars  :"abcdefghijklmnopqrstuvwxyz".split(''),
    next : function(i){
        with(this){
            var m,k,l,i = (i||i===0)?i:b.length-1;
            if((m=a[i]) >= 25){
                m=0;
                if(i===0){
                    a.splice(0,0,1);
                    b.splice(0,0,'a');
                    l=a.length;
                    for(k=1;k<l;++k){
                        a[k]=0;
                        b[k]='0';
                    }
                    ++i;
                }else
                  next(i-1);
            }else ++m;
            a[i]=m;
            b[i]=_chars[m];
            return value = b.join('');
        }
    }
};


Class('linb.absProfile',null,{
    Constructor:function(){
        if(!this.$linbid)this.$linbid=linb.absProfile.$linbid.next();
    },
    Instance:{
        getId:function(){
            return this.$linbid;
        },
        link:function(obj,id,target){
            var self=this,
                //avoid Number;
                uid='$'+self.$linbid;

            target = target||self;
            if(obj[uid])self.unLink(id);

            //double link
            obj[uid]=target;
            if(_.isArr(obj))obj.push(target);

            //antilink track
            self._links[id]=obj;
            return self;
        },
        unLink:function(id){
            var self=this,
                o,
                //avoid Number;
                uid='$'+self.$linbid;
            if(!self._links)return;
            if(!(o=self._links[id]))return;

            //remove from target
            if(_.isArr(o))_.arr.removeValue(o,o[uid]);
            delete o[uid];

            //remove from self
            delete self._links[id];

            return self;
        },
        unLinkAll:function(){
            var self=this,
                id='$'+self.$linbid,
                l=self._links,
                o,i;
            for(i in l){
                o=l[i];
                if(_.isArr(o))_.arr.removeValue(o,o[id]);
                delete o[id];
            }
            self._links={};
            return self;
        }
    },
    Static:{
        $linbid:new _.id,
        $abstract:true
    }
});
(linb.Locale.en||(linb.Locale.en={})).inline={
    ok:'O K',
    cancel:'Cancel',
    set:'SET',
    today:'Today',
    yes:'Yes',
    no:'No'
};
linb.Locale.en.date={
    WEEKS:{
        '0':'Su',
        '1':'Mo',
        '2':'Tu',
        '3':'We',
        '4':'Th',
        '5':'Fr',
        '6':'Sa',
        '7':'WK'
    },
    VIEWS:{
        '10 ms':'10 millisecond',
        '100 ms':'100 milliseconds',
        '1 s':'1 second',
        '10 s':'10 seconds',
        '1 n':'1 minute',
        '5 n':'5 minutes',
        '10 n':'10 minutes',
        '30 n':'30 minutes',
        '1 h':'1 hour',
        '2 h':'2 hours',
        '6 h':'6 hours',
        '1 d':'1 day',
        '1 w':'1 week',
        '15 d':'15 days',
        '1 m':'1 month',
        '1 q':'1 quarter',
        '1 y':'1 year',
        '1 de':'10 years',
        '1 c':'1 century'
    },
    MONTHS:{
        '1':'Jan.',
        '2':'Feb.',
        '3':'Mar.',
        '4':'Apr.',
        '5':'May.',
        '6':'Jun.',
        '7':'Jul.',
        '8':'Aug.',
        '9':'Sep.',
        '10':'Oct.',
        '11':'Nov.',
        '12':'Dec.'
    },
    MS:'ms',
    S:'s',
    N:'n',
    H:'h',
    D:'d',
    W:'w',
    M:'m',
    Q:'q',
    Y:'y',
    DE:'de',
    C:'c',
    HN:function(n,a,b){return a+":"+b},
    DHN:function(n,a,b,c){return a +'th '+ b + ":" +c },
    MDHN:function(n,a,b,c,d){return b+ 'th ' + linb.getRes('date.MONTHS.'+a) + " " + c + ":" + d},
    HNS:function(n,a,b,c){return a+":"+b+":"+c},
    HNSMS:function(n,a,b,c,d){return a+":"+b+":"+c + ' ' +d},
    YM:function(n,a,b){return linb.getRes('date.MONTHS.'+b)+' '+a},
    YQ:function(n,a,b){return b+'Q ' + a},
    YMD:function(n,a,b,c){return b+'/'+c+'/'+a},
    YMD2:function(n,a,b,c){return linb.getRes('date.MONTHS.'+b)+' '+c+', '+a},
    MD:function(n,a,b){return linb.getRes('date.MONTHS.'+a) + " "+ b},
    YMDH:function(n,a,b,c,d){return c+'/'+b+'/'+a + ' ' +d+':00'},
    YMDHN:function(n,a,b,c,d,e){return b+'/'+c+'/'+a + ' ' +d+":"+e},
    YMDHNS:function(n,a,b,c,d,e,f){return b+'/'+c+'/'+a + ' ' +d+":"+e+":"+f},
    ALL:function(n,a,b,c,d,e,f,g){return b+'/'+c+'/'+a + ' ' +d+":"+e+":"+f +" " +g}
};
linb.Locale.en.color={
  LIST:{
    "FFFFFF":"White",
    "FFFFF0":"Ivory",
    "FFFFE0":"Light Yellow",
    "FFFF00":"Yellow",
    "FFFAFA":"Snow",
    "FFFAF0":"Floral White",
    "FFFACD":"Lemon Chiffon",
    "FFF8DC":"Cornislk",
    "FFF5EE":"Sea Shell",
    "FFF0F5":"Lavender Blush",
    "FFEFD5":"Papaya Whip",
    "FFEBCD":"Blanched Almond",
    "FFE4E1":"Misty Rose",
    "FFE4C4":"Bisque",
    "FFE4B5":"Moccasin",
    "FFDEAD":"Navajo White",
    "FFDAB9":"Peach Puff",
    "FFD700":"Gold",
    "FFC0CB":"Pink",
    "FFB6C1 ":"Light Pink",
    "FFA500":"Orange",
    "FFA07A":"Light Salmon",
    "FF8C00":"Dark Orange",
    "FF7F50":"Coral",
    "FF69B4":"Hot Pink",
    "FF6347":"Tomato",
    "FF4500":"Orange Red",
    "FF1493":"Deep Pink",
    "FF00FF":"Magenta",
    "FF00FF":"Fuchsia",
    "FF0000":"Red",
    "FDF5E6":"Old Lace",
    "FAFAD2":"Light Goldenrod Yellow",
    "FAF0E6":"Linen",
    "FAEBD7":"Antique White",
    "FA8072":"Salmon",
    "F8F8FF":"Ghost White",
    "F5FFFA":"Medium Spring Green",
    "F5F5F5":"White Smoke",
    "F5DEB3":"Wheat",
    "F4A460":"Sandy Brown",
    "F0FFFF":"Azure",
    "F0FFF0":"Honeydew",
    "F0F8FF":"Alice Blue",
    "F0E68C":"Khaki",
    "F08080":"Light Coral",
    "EEE8AA":"Pale Godenrod",
    "EE82EE":"Violet",
    "E9967A":"Dark Salmon",
    "E6E6FA":"Lavender",
    "E1FFFF":"Light Cyan",
    "DEB887":"Bruly Wood",
    "DDA0DD":"plum",
    "DCDCDC":"Gainsboro",
    "DC143C":"Crimson",
    "DB7093":"Pale Violet Red",
    "DAA520":"Gold Enrod",
    "DA70D6":"Orchid",
    "D8BFD8":"Thistle",
    "D3D3D3":"Light Grey",
    "D2B48C":"Tan",
    "D2691E":"Chocolate",
    "CD853F":"Peru",
    "CD5C5C":"Indian Red",
    "C71585":"Medium Violet Red",
    "C0C0C0":"Silver",
    "BDB76B":"Dark Khaki",
    "BC8F8F":"Rosy Brown",
    "BA55D3":"Medium Orchid",
    "B22222":"Fire Brick",
    "B0E0E6":"Pow Der Blue",
    "B0C4DE":"Light Steel Blue",
    "AFEEEE":"Pale Turquoise",
    "ADFF2F":"Green Yellow",
    "ADD8E6":"Light BLue",
    "A9A9A9":"Dark Gray",
    "A52A2A":"Brown",
    "A0522D":"Sienna",
    "9932CC":"Dark Orchid",
    "98FB98":"Pale Green",
    "9400D3":"Dark Voilet",
    "9370DB":"Medium Purple",
    "90EE90":"Light Green",
    "8FBC8F":"Dark Sea Green",
    "8B4513":"Saddle Brown",
    "8B008B":"Dark Magenta",
    "8B0000":"Dark Red",
    "8A2BE2":"Blue Violet",
    "87CEFA":"Light Sky Blue",
    "87CEEB":"Sky Blue",
    "808080":"Gray",
    "808000":"Olive",
    "800080":"Purple",
    "800000":"Maroon",
    "7FFFAA":"Auqamarin",
    "7FFF00":"Chartreuse",
    "7CFC00":"Lawn Green",
    "7B68EE":"Medium Slate Blue",
    "778899":"Light Slate Gray",
    "708090":"Slate Gray",
    "6B8E23":"Beige",
    "6A5ACD":"Slate Blue",
    "696969":"Dim Gray",
    "6495ED":"Cornflower Blue",
    "5F9EA0":"Cadet Blue",
    "556B2F":"Olive Drab",
    "4B0082":"Indigo",
    "48D1CC":"Medium Turquoise",
    "483D8B":"Dark Slate Blue",
    "4682B4":"Steel Blue",
    "4169E1":"Royal Blue",
    "40E0D0":"Turquoise",
    "3CB371":"Spring Green",
    "32CD32":"Lime Green",
    "2F4F4F":"Dark Slate Gray",
    "2E8B57":"Sea Green",
    "228B22":"Forest Green",
    "20B2AA":"Light Sea Green",
    "1E90FF":"Doder Blue",
    "191970":"Midnight Blue",
    "00FFFF":"Cyan",
    "00FFFF":"Aqua",
    "00FF7F":"Mint Cream",
    "00FF00":"Lime",
    "00FA9A":"Medium Aquamarine",
    "00CED1":"Dark Turquoise",
    "00BFFF":"Deep Sky Blue",
    "008B8B":"Dark Cyan",
    "008080":"Teal",
    "008000":"Green",
    "006400":"Dark Green",
    "0000FF":"Blue",
    "0000CD":"Medium Blue",
    "00008B":"Dark Blue",
    "000080":"Navy",
    "000000":"Black"
  }
};
linb.Locale.en.editor={
    bold:'Bold',
    italic:'Italic',
    underline:'Underline',
    strikethrough:'Strikethrough',
    subscript:'Subscript',
    superscript:'Superscript',
    forecolor:'Font Color',
    bgcolor:'Background Color',
    left:'Align Left',
    center:'Align Center',
    right:'Align Right',
    justify:'Justify',
    indent:'Indent',
    outdent:'Outdent',
    ol:'Ordered List',
    ul:'Unordered List',
    hr:'Insert Horizontal Rule',
    unlink:'Remove Link',
    removeformat:'Remove Formatting',
    html:"HTML Editor",

    insertimage:'Insert Image',
    insertimage2:'Image URL:',
    createlink:'Insert Link',
    createlink2:'Link URL:',
    fontsize:'Font Size',
    fontname:'Font Family',
    formatblock:'Font Block',
    fontsizeList:'1,1(8pt);2,2(10pt);3,3(12pt);4,4(14pt);5,5(18pt);6,6(24pt);...,...',
    fontnameList:'Arial;Arial Black;Comic Sans MS;Courier New;Impact;Tahoma;Times New Roman;Trebuchet MS;Verdana;...',
    formatblockList:'p,Normal;h1,Heading1;h2,Heading2;h3,Heading3;h4,Heading4;h5,Heading5;h6,Heading6;...,...'
};/* event
*  dependency: base _ ; Class ; linb ;
*/
Class('linb.Event',null,{
    Constructor:function(event,node,fordrag,tid){
        var self = linb.Event,
            dd=0,id,t,
            dragdrop=linb.DragDrop,
            src, type,  pre, obj;

        //get event object , and src of event
        if(!(event=event||window.event) || !(src=node)){
            src=node=null;
            return false;
        }
        node=null;

        //type
        type = event.type;

        //for correct mouse hover problems;
        if('mouseover'==type || 'mouseout'==type){
            dd=(dragdrop&&dragdrop._profile.isWorking)?1:2;
            //for dropable
            if(dd!=1 && fordrag){
                src=null;
                return self.$FALSE;
            }
            //don't return false, here, opera will stop the system event hander => cursor not change
            if(!self._handleMouseHover(event, src, dd==1)){
                src=null;
                return self.$FALSE;
            }
            if(dd==1)
                pre=dragdrop&&dragdrop._dropElement;
        //for tab focusHook
        }else if((obj=self._tabHookStack).length &&
            self._kb[type] &&
            (event.$key || event.keyCode || event.charCode)==9 &&
            false === self._handleTabHook(self.getSrc(event), obj=obj[obj.length-1])){
                src=null;
                return;
            }

        id = tid||self.getId(src);
        //get profile from dom cache
        if(obj = self._getProfile(id)){
            //for setBlurTrigger
            if(type=='mousedown'){
                _.tryF(linb.Dom._blurTrigger,[obj,event]);
            //for resize
            }else if(type=="resize"){
                type='size';
                //for IE, always fire window onresize event after any innerHTML action
                if(linb.browser.ie && window===src){
                    var w=linb.browser.contentBox && document.documentElement.clientWidth || document.body.clientWidth,
                        h=linb.browser.contentBox && document.documentElement.clientHeight || document.body.clientHeight;
                    if(obj._w==w&&obj._h==h){
                        src=null;
                        return;
                    }
                    obj._w=w;obj._h=h;
                }
            }

            var j, f, name, r=true, funs=[];
            //order by: before, on, after
            for(j=0; j<=2; ++j){
                //if in dd, get before Mouse.. only
                if(dd==1 && j!==0 && !event.$force)break;
                //if not in dd, get on/after Mouse.. only
                if(dd==2 && j===0)continue;
                //get event name from event type
                name = self._type[type+j] || ( self._type[type+j] = self._getEventName(type, j));
                /*
                event.$e : called by fireEvent
                event.$all : fire all events of the type: before/on/after
                event.$name : fire one group of event of the type.
                */
                if(!event.$e || event.$all || (name==event.$name))obj._getEV(funs, id, name, src.$linbid);
            }

            /*call function by order
             widget before -> dom before -> widget on -> dom on -> widget after -> dom after
            */
            f=function(a,b){
                for(var i=0,v;v=arguments.callee.tasks[i++];)
                    //if any fun return false, stop event bubble
                    if(false === v(obj, a, b))
                        return false;
                return true;
            };
            f.tasks=funs;
            r = f(event, src.$linbid);

            if(dragdrop){
                //shortcut for onDrag('mousemove')
                if(type=='drag')
                    dragdrop._onDrag=f;
                else if(type=='dragover')
                    dragdrop._onDragover=f;
            }else{
                f.tasks.length=0;
                delete f.tasks;
                f=null;
            }

            if(dd==1){
                //From parent dropable node to child dropable node, fire parent node's mouseout manually
                if('mouseover'==type && dragdrop._dropElement==src.$linbid && pre && pre!=src.$linbid){
                    t=linb.use(pre).get(0);
                    self({
                        type: 'mouseout',
                        target: t,
                        $e:true,
                        $name:'beforeMouseout',
                        preventDefault:function(){this.returnValue=false},
                        stopPropagation:function(){this.cancelBubble=true}
                        },t);
                    dragdrop.setDropElement(src.$linbid);
                }

                //Out of dropable node, 'dragdrop._dropElement' will be set to null in beforeMouseover
                //set _preDropable flag, for parent node is dropable too
                if('mouseout'==type && !dragdrop._dropElement && pre && pre==src.$linbid){
                    self._preDropable=id;
                    _.asyRun(function(){delete linb.Event._preDropable});
                }

                //if fire dd, prevent to fire parent dd
                //notice: this dont trigger cursor changing in opera
                if(src.$linbid==dragdrop._dropElement)
                    r=false;
            }
            if(r===false)self.stopBubble(event);
            src=null;
            return r;
        }
    },
    Static:{
        $FALSE:linb.browser.opr?undefined:false,
        _type:{},
        _kb:{keydown:1,keypress:1,keyup:1},
        _reg:/(-[\w]+)|([\w]+$)/g,
        $eventhandler:function(){return linb.Event(arguments[0],this)},
        $eventhandler2:function(){return linb.Event(arguments[0],this,1)},
        //collection
        _events : ("mouseover,mouseout,mousedown,mouseup,mousemove,click,dblclick,contextmenu," +
                "keydown,keypress,keyup,scroll,"+
                "blur,focus,"+
                "load,unload,"+
                "change,select,submit,error,"+

                //customized handlers:
                //dont use resize in IE
                "move,size," +
                //dragstart dragdrop dragout will not work in IE(using innerHTML)
                "dragbegin,drag,dragstop,dragleave,dragenter,dragover,drop")
                .split(','),
        _getEventName:function(name,pos){
            return (name=this._map1[name]) && ((pos===0||pos==1||pos==2) ? name[pos] : name);
        },
        _getProfile:function(id,a,b){
            return id && ((a=(b=linb.$cache.profileMap)[id])
                            ?
                            a['linb.UIProfile']
                                ?
                                a
                                :
                                (b=b[id.replace(this._reg,'')])
                                    ?
                                    b
                                    :
                                    a
                            :
                            b[id.replace(this._reg,'')]);
        },
        _handleTabHook:function(src, target){
            if(src===document)return true;
            var node=src,r;
            do{
                if(linb.getId(node)==target[0]){
                    node=src=null;
                    return true;
                }
            }while(node && (node=node.parentNode) && node!==document && node!==window)

            r=_.tryF(target[1],[target[0]],src);
            node=src=null;
            return false;
        },
        _handleMouseHover:function(event,target,dd){
            if(target==document){
                target=null;
                return true;
            }
            var node = (event.type=='mouseover'?event.fromElement:event.toElement)||event.relatedTarget;

            //When out of dropable node, if the parent node is dropable return true;
            if(dd && event.type=='mouseover' &&this._preDropable)
                try{
                    do{
                        if(node && node.id && node.id==this._preDropable){
                            target=node=null;
                            return true
                        }
                    }while(node && (node=node.parentNode) && node!==document && node!==window)
                }catch(a){}

            //for firefox wearing anynomous div in input/textarea
            //related to 'div.anonymous-div' always returns true
            if(linb.browser.gek)
                try{
                    do{
                        if(node==target){
                            target=node=null;
                            return false
                        }
                    }while(node && (node=node.parentNode))
                }catch(a){
                    var pos=this.getPos(event),
                        node=linb([target]),
                        p=node.offset(),
                        s=node.cssSize(),
                        out=(pos.left<p.left||pos.left>p.left+s.width||pos.top<p.top||pos.top>p.top+s.height);
                    target=node=null;
                    return event.type=='mouseover'?!out:out;
                }
            else
                do{
                    if(node==target){
                        target=node=null;
                        return false
                    }
                }while(node && (node=node.parentNode))
            target=node=null;
            return true;
        },

        _tabHookStack:[],
        pushTabOutTrigger:function(boundary, trigger){this._tabHookStack.push([linb(boundary)._nodes[0], trigger]);return this},
        popTabOutTrigger:function(flag){if(flag)this._tabHookStack=[];else this._tabHookStack.pop();return this},
        getSrc:function(event){
            var a;
            return ((a=event.target||event.srcElement||null) && linb.browser.kde && a.nodeType == 3)?a.parentNode:a
        },
        getId:function(node){
            return window===node?"!window":document===node?"!document":node.id;
        },
        // only for mousedown and mouseup
        // return 1 : left button, else not left button
        getBtn:function(event){
            return linb.browser.ie ?
                    event.button==4 ?
                        'middle' :
                            event.button==2 ?
                                'right' :
                                    'left' :
                    event.which==2 ?
                        'middle':
                            event.which==3 ?
                                'right':
                                    'left';
        },
        getPos:function(event){
            event = event || window.event;
            if('pageX' in event)
                return {left:event.pageX, top:event.pageY};
            else{
    			var d=document, doc = d.documentElement, body = d.body,
    			_L = (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0),
    			_T = (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
                return {left:event.clientX+_L, top:event.clientY+_T};
            }
        },
        /*return array(key, control, shift, alt)
        ['k','1','',''] : 'k' pressed, 'control' pressed, 'shift' and 'alt' not pressed
        */
        /*
        opear in window:
            ' = right (39)
            - = insert (45)
            . = del (46)
        */
        getKey:function(event){
            event=event||window.event;
            // use keyCode first for newer safari
            var res=[],t, k= event.$key || event.keyCode || event.charCode || 0;
            //from linb event
            if(typeof k == 'string')
                res[0]=k;
            else{
                var key= String.fromCharCode(k),
                    type=event.type;
                if(
                 //visible char
                 (type=='keypress' && k>=33 && k<=128)
                 //0-9, A-Z
                 ||((k>=48&&k<=57) || (k>=65&&k<=90))
                 )res[0]=key;
                else{
                    if(!(t=arguments.callee.map)){
                        t = arguments.callee.map ={};
                        var k,arr =
                        ("3,enter,8,backspace,9,tab,12,numlock,13,enter,19,pause,20,capslock," +
                        "27,esc,32, ,33,pageup,34,pagedown,35,end,36,home,37,left,38,up,39,right,40,down,44,printscreen," +
                        "45,insert,46,delete,50,down,52,left,54,right,56,up," +
                        "91,win,92,win,93,apps," +
                        "96,0,97,1,98,2,99,3,100,4,101,5,102,6,103,7,104,8,105,9," +
                        "106,*,107,+,109,-,110,.,111,/," +
                        "112,f1,113,f2,114,f3,115,f4,116,f5,117,f6,118,f7,119,f8,120,f9,121,f10,122,f11,123,f12," +
                        "144,numlock,145,scroll," +
                        "186,;,187,=,189,-,190,.,191,/,192,`,"+
                        "219,[,220,\\,221,],222,'," +
                        "224,meta,"+ //Apple Meta and Windows key
                        //safari
                        "63289,numlock,63276,pageup,63277,pagedown,63275,end,63273,home,63234,left,63232,up,63235,right,63233,down,63272,delete,63302,insert,63236,f1,63237,f2,63238,f3,63239,f4,63240,f5,63241,f6,63242,f7,63243,f8,63244,f9,63245,f10,63246,f11,63247,f12,63248,print"
                        ).split(',')
                        for(var i=1,l=arr.length; i<l; i=i+2)
                            t[arr[i-1]]=arr[i]
                        arr.length=0;
                        //add
                        t[188]=',';
                    }
                    res[0]= t[k] || key;
                }
            }

            //control
            if((event.modifiers)?(event.modifiers&Event.CONTROL_MASK):(event.ctrlKey||event.ctrlLeft||k==17||k==57391)){
                if(k==17||k==57391)
                    res[0]='';
                res.push('1');
            }else
                res.push('');

            //shift
            if((event.modifiers)?(event.modifiers&Event.SHIFT_MASK):(event.shiftKey||event.shiftLeft||k==16||k==57390)){
                if(k==16||k==57390)
                    res[0]='';
                res.push('1');
            }else
                res.push('');

            //alt
            if((event.modifiers)?false:(event.altKey||event.altLeft||k==18||k==57388)){
                if(k==18||k==57388)
                    res[0]='';
                res.push('1');
            }else
                res.push('');

            return res;
        },
        getEventPara:function(event, mousePos){
            var keys = this.getKey(event), h={
                pageX:mousePos&&mousePos.left,
                pageY:mousePos&&mousePos.top,
                keyCode:keys[0],
                ctrlKey:keys[1],
                shiftKey:keys[2],
                altKey:keys[3]
            };
            for(var i in event)if(i.charAt(0)=='$')h[i]=event[i];
            return h;
        },
        stopBubble:function(event){
            event=event||window.event;
            if(event.stopPropagation)event.stopPropagation();
            event.cancelBubble = true;
            this.stopDefault(event);
        },
        stopDefault:function(event){
            event=event||window.event;
            if(event.preventDefault)event.preventDefault();
            event.returnValue = false;
        },
        //key:control:shift:alt
        keyboardHook:function(key, ctrl, shift, alt, fun,args,scope){
            if(key){
                var p = linb.$cache.hookKey, k = (key||'').toLowerCase() + ":"  + (ctrl?'1':'') + ":"  +(shift?'1':'')+ ":" + (alt?'1':'');
                if(typeof fun!='function')delete p[k];
                else p[k]=[fun,args,scope];
             }
            return this;
        }
    },
    Initialize:function(){
        var ns=this;
        var m1={
                move:null,
                size:null,
    
                drag:null,
                dragstop:null,
                dragover:null,
    
                dragbegin:'onmousedown',
                dragenter:'onmouseover',
                dragleave:'onmouseout',
                drop:'onmouseup'
            },
            a1=['before','on','after'],
            t1,t2,s;

        t1=ns._map1={};
        _.arr.each(ns._events,function(o){
            s=_.str.initial(o);
            t1[o]=[a1[0]+s, a1[1]+s, a1[2]+s];
        });
        
        t1=ns._eventMap={};
        t2=ns._eventHandler={};
        _.arr.each(ns._events,function(o){
            s=_.str.initial(o);
            t1[o]=t1[a1[1]+o]=t1[a1[0]+s]=t1[a1[1]+s]=t1[a1[2]+s]=o;
            t2[o]=t2[a1[1]+o]=t2[a1[0]+s]=t2[a1[1]+s]=t2[a1[2]+s]= (o in m1)?m1[o]:('on'+o);
        });
        
        //add the root resize handler
        window.onresize=ns.$eventhandler;
    }
});Class('linb.Date',null,{
    Initialize:function(){
        var self=this;
        self._mapKeys(self.$TIMEUNIT);
        var a=self._key1,b=self._key2,u=self.$UNIT={};
        for(var i=0,l=a.length;i<l;i++)u[a[i]]=1;
        for(var i=0,l=b.length;i<l;i++)u[b[i]]=1;
        u.w=1;
    },
    Static:{
        _key1:'MILLISECOND,SECOND,MINUTE,HOUR,DAY,WEEK,MONTH,QUARTER,YEAR,DECADE,CENTURY'.split(','),
        _key2:'ms,s,n,h,d,ww,m,q,y,de,c'.split(','),
        // Conversion factors
        $TIMEUNIT : {
            MILLISECOND : 1,
            SECOND      : 1000,           //SECONDS
            MINUTE      : 60000,          //MINUTES 60 * 1000
            HOUR        : 3600000,        //HOURS 60 * 60 * 1000
            DAY         : 86400000,       //DAYS 24 * 60 * 60 * 1000
            WEEK        : 604800000,      //WEEKS 7 * 24 * 60 * 60 * 1000
            MONTH       : 2592000000,     //MONTHS 30 * 24 * 60 * 60 * 1000  (approx = 1 month)
            QUARTER     : 7776000000,     //QUARTERS 90 * 24 * 60 * 60 * 1000  (approx = 3 months)
            YEAR        : 31557600000,    //YEARS 365 * 24 * 60 * 60 * 1000 (approx = 1 year)
            DECADE      : 315576000000,   //DECADES 10 * 365 * 24 * 60 * 60 * 1000 (approx = 1 decade)
            CENTURY     : 3155760000000   //CENTURIES 100 * 365 * 24 * 60 * 60 * 1000 (approx = 1 century)
        },
        $TEXTFORMAT:{
            utciso:function(d,f){f=linb.Date._fix; return d.getUTCFullYear() + '-' +f(d.getUTCMonth() + 1) + '-' +f(d.getUTCDate()) + 'T' +f(d.getUTCHours()) + ':' +f(d.getUTCMinutes()) + ':' +f(d.getUTCSeconds()) + 'Z'},
            iso:function(d,f){f=linb.Date._fix; return d.getFullYear() + '-' +f(d.getMonth() + 1) + '-' +f(d.getDate()) + 'T' +f(d.getHours()) + ':' +f(d.getMinutes()) + ':' +f(d.getSeconds())},
            ms:function(d){return linb.Date._fix(d.getMilliseconds(),3)+ linb.wrapRes('date.MS')},
            s:function(d){return linb.Date._fix(d.getSeconds())+ linb.wrapRes('date.S')},
            n:function(d){return linb.Date._fix(d.getMinutes())+ linb.wrapRes('date.N')},
            h :function(d){return linb.Date._fix(d.getHours())+ linb.wrapRes('date.H')},
            d:function(d){return d.getDate()+ linb.wrapRes('date.D')},
            w : function(d,firstDayOfWeek){return linb.wrapRes('date.WEEKS.'+(d.getDay() - firstDayOfWeek +7)%7 )},
            ww : function(d,firstDayOfWeek){return linb.Date.getWeek(d, firstDayOfWeek) + linb.wrapRes('date.W')},
            m:function(d){return (d.getMonth()+1) + linb.wrapRes('date.M')},
            q : function(d){return (parseInt((d.getMonth()+3)/3-1) + 1) + linb.wrapRes('date.Q')},
            y :function(d){return d.getFullYear() + linb.wrapRes('date.Y')},
            de:function(d){return parseInt(d.getFullYear()/10) + linb.wrapRes('date.DE')},
            c:function(d){return parseInt(d.getFullYear()/100) + linb.wrapRes('date.C')},

            hn:function(d){return linb.wrapRes('date.HN-'+d.getHours()+"-"+d.getMinutes())},
            dhn:function(d){return linb.wrapRes('date.DHN-'+d.getDate()+"-"+d.getHours()+"-"+d.getMinutes())},
            mdhn:function(d){return linb.wrapRes('date.MDHN-'+(d.getMonth()+1)+"-"+d.getDate()+"-"+d.getHours()+"-"+d.getMinutes())},
            hns:function(d){return linb.wrapRes('date.HNS-'+d.getHours()+"-"+d.getMinutes()+"-"+d.getSeconds())},
            hnsms:function(d){return linb.wrapRes('date.HNSMS-'+d.getHours()+"-"+d.getMinutes()+"-"+d.getSeconds()+"-"+d.getMilliseconds())},

            yq:function(d){return linb.wrapRes('date.YQ-'+d.getFullYear()+"-"+(parseInt((d.getMonth()+3)/3-1)+1))},

            ym :   function(d){return linb.wrapRes('date.YM-'+d.getFullYear()+"-"+(d.getMonth()+1))},
            md :  function(d){return linb.wrapRes('date.MD-'+(d.getMonth()+1)+"-"+d.getDate())},
            ymd :  function(d){return linb.wrapRes('date.YMD-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate())},
            ymd2 :  function(d){return linb.wrapRes('date.YMD2-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate())},
            ymdh:  function(d){return linb.wrapRes('date.YMDH-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate()+"-"+d.getHours())},
            ymdhn: function(d){return linb.wrapRes('date.YMDHN-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate()+"-"+d.getHours()+"-"+d.getMinutes())},
            ymdhns:function(d){return linb.wrapRes('date.YMDHNS-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate()+"-"+d.getHours()+"-"+d.getMinutes()+"-"+d.getSeconds())},
            'all' :  function(d){return linb.wrapRes('date.ALL-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate()+"-"+d.getHours()+"-"+d.getMinutes()+"-"+d.getSeconds()+"-"+d.getMilliseconds())}
        },
        $TIMEZONE:[{
            id:"Asia(East,North)",
            sub:[{
                    id:"Brunei",
                    v:"+0800"
                },{
                    id:"Burma",
                    v:"+0630"
                },{
                    id:"Cambodia",
                    v:"+0700"
                },{
                    id:"China",
                    v:"+0800"
                },{
                    id:"China(HK,Macau)",
                    v:"+0800"
                },{
                    id:"China(TaiWan)",
                    v:"+0800"
                },{
                    id:"China(Urumchi)",
                    v:"+0700"
                },{
                    id:"East Timor",
                    v:"+0800"
                },{
                    id:"Indonesia",
                    v:"+0700"
                },{
                    id:"Japan",
                    v:"+0900"
                },{
                    id:"Kazakhstan(Aqtau)",
                    v:"+0400"
                },{
                    id:"Kazakhstan(Aqtobe)",
                    v:"+0500"
                },{
                    id:"Kazakhstan(Astana)",
                    v:"+0600"
                },{
                    id:"Kirghizia",
                    v:"+0500"
                },{
                    id:"Korea",
                    v:"+0900"
                },{
                    id:"Laos",
                    v:"+0700"
                },{
                    id:"Malaysia",
                    v:"+0800"
                },{
                    id:"Mongolia",
                    v:"+0800",
                    tag:"03L03|09L03"
                },{
                    id:"Philippines",
                    v:"+0800"
                },{
                    id:"Russia(Anadyr)",
                    v:"+1300",
                    tag:"03L03|10L03"
                },{
                    id:"Russia(Kamchatka)",
                    v:"+1200",
                    tag:"03L03|10L03"
                },{
                    id:"Russia(Magadan)",
                    v:"+1100",
                    tag:"03L03|10L03"
                },{
                    id:"Russia(Vladivostok)",
                    v:"+1000",
                    tag:"03L03|10L03"
                },{
                    id:"Russia(Yakutsk)",
                    v:"+0900",
                    tag:"03L03|10L03"
                },{
                    id:"Singapore",
                    v:"+0800"
                },{
                    id:"Thailand",
                    v:"+0700"
                },{
                    id:"Vietnam",
                    v:"+0700"
                }]
            },{
                id:"Asia(South,West)",
                sub:[{
                    id:"Afghanistan",
                    v:"+0430"
                },{
                    id:"Arab Emirates",
                    v:"+0400"
                },{
                    id:"Bahrain",
                    v:"+0300"
                },{
                    id:"Bangladesh",
                    v:"+0600"
                },{
                    id:"Bhutan",
                    v:"+0600"
                },{
                    id:"Cyprus",
                    v:"+0200"
                },{
                    id:"Georgia",
                    v:"+0500"
                },{
                    id:"India",
                    v:"+0530"
                },{
                    id:"Iran",
                    v:"+0330",
                    tag:"04 13|10 13"
                },{
                    id:"Iraq",
                    v:"+0300",
                    tag:"04 13|10 13"
                },{
                    id:"Israel",
                    v:"+0200",
                    tag:"04F53|09F53"
                },{
                    id:"Jordan",
                    v:"+0200"
                },{
                    id:"Kuwait",
                    v:"+0300"
                },{
                    id:"Lebanon",
                    v:"+0200",
                    tag:"03L03|10L03"
                },{
                    id:"Maldives",
                    v:"+0500"
                },{
                    id:"Nepal",
                    v:"+0545"
                },{
                    id:"Oman",
                    v:"+0400"
                },{
                    id:"Pakistan",
                    v:"+0500"
                },{
                    id:"Palestine",
                    v:"+0200"
                },{
                    id:"Qatar",
                    v:"+0300"
                },{
                    id:"Saudi Arabia",
                    v:"+0300"
                },{
                    id:"Sri Lanka",
                    v:"+0600"
                },{
                    id:"Syria",
                    v:"+0200",
                    tag:"04 13|10 13"
                },{
                    id:"Tajikistan",
                    v:"+0500"
                },{
                    id:"Turkey",
                    v:"+0200"
                },{
                    id:"Turkmenistan",
                    v:"+0500"
                },{
                    id:"Uzbekistan",
                    v:"+0500"
                },{
                    id:"Yemen",
                    v:"+0300"
                }]
            },{
                id:"North Europe",
                sub:[{
                    id:"Denmark",
                    v:"+0100",
                    tag:"04F03|10L03"
                },{
                    id:"Faroe Is.(DK)",
                    v:"+0100"
                },{
                    id:"Finland",
                    v:"+0200",
                    tag:"03L01|10L01"
                },{
                    id:"Iceland",
                    v:"+0000"
                },{
                    id:"Jan Mayen(Norway)",
                    v:"-0100"
                },{
                    id:"Norwegian",
                    v:"+0100"
                },{
                    id:"Svalbard(NORWAY)",
                    v:"+0100"
                },{
                    id:"Sweden",
                    v:"+0100",
                    tag:"03L01|10L01"
                }]
            },{
                id:"Eastern Europe",
                sub:[{
                    id:"Armenia",
                    v:"+0400"
                },{
                    id:"Austria",
                    v:"+0100",
                    tag:"03L01|10L01"
                },{
                    id:"Azerbaijan",
                    v:"+0400"
                },{
                    id:"Belarus",
                    v:"+0200",
                    tag:"03L03|10L03"
                },{
                    id:"Czech",
                    v:"+0100"
                },{
                    id:"Estonia",
                    v:"+0200"
                },{
                    id:"Georgia",
                    v:"+0500"
                },{
                    id:"Germany",
                    v:"+0100",
                    tag:"03L01|10L01"
                },{
                    id:"Hungarian",
                    v:"+0100"
                },{
                    id:"Latvia",
                    v:"+0200"
                },{
                    id:"Liechtenstein",
                    v:"+0100"
                },{
                    id:"Lithuania",
                    v:"+0200"
                },{
                    id:"Moldova",
                    v:"+0200"
                },{
                    id:"Poland",
                    v:"+0100"
                },{
                    id:"Rumania",
                    v:"+0200"
                },{
                    id:"Russia(Moscow)",
                    v:"+0300",
                    tag:"03L03|10L03"
                },{
                    id:"Slovakia",
                    v:"+0100"
                },{
                    id:"Switzerland",
                    v:"+0100",
                    tag:"03L01|10L01"
                },{
                    id:"Ukraine",
                    v:"+0200"
                },{
                    id:"Ukraine(Simferopol)",
                    v:"+0300"
                }]
            },{
                id:"Western Europe",
                sub:[{
                    id:"Andorra",
                    v:"+0100",
                    tag:"03L01|10L01"
                },{
                    id:"Belgium",
                    v:"+0100",
                    tag:"03L01|10L01"
                },{
                    id:"Channel Is.(UK)",
                    v:"+0000",
                    tag:"03L01|10L01"
                },{
                    id:"France",
                    v:"+0100",
                    tag:"03L01|10L01"
                },{
                    id:"Gibraltar(UK)",
                    v:"+0100",
                    tag:"03L01|10L01"
                },{
                    id:"Ireland",
                    v:"+0000",
                    tag:"03L01|10L01"
                },{
                    id:"Isle of Man(UK)",
                    v:"+0000",
                    tag:"03L01|10L01"
                },{
                    id:"Luxembourg",
                    v:"+0100",
                    tag:"03L01|10L01"
                },{
                    id:"Monaco",
                    v:"+0100"
                },{
                    id:"Netherlands",
                    v:"+0100",
                    tag:"03L01|10L01"
                },{
                    id:"United Kingdom",
                    v:"+0000",
                    tag:"03L01|10L01"
                }]
            },{
                id:"South Europe",
                sub:[{
                    id:"Albania",
                    v:"+0100"
                },{
                    id:"Bosnia",
                    v:"+0100"
                },{
                    id:"Bulgaria",
                    v:"+0200"
                },{
                    id:"Croatia",
                    v:"+0100"
                },{
                    id:"Greece",
                    v:"+0200",
                    tag:"03L01|10L01"
                },{
                    id:"Holy See",
                    v:"+0100"
                },{
                    id:"Italy",
                    v:"+0100",
                    tag:"03L01|10L01"
                },{
                    id:"Macedonia",
                    v:"+0100"
                },{
                    id:"Malta",
                    v:"+0100"
                },{
                    id:"Montenegro",
                    v:"+0100"
                },{
                    id:"Portugal",
                    v:"+0000",
                    tag:"03L01|10L01"
                },{
                    id:"San Marino",
                    v:"+0100"
                },{
                    id:"Serbia",
                    v:"+0100"
                },{
                    id:"Slovenia",
                    v:"+0100"
                },{
                    id:"Span",
                    v:"+0100",
                    tag:"03L01|10L01"
                }]
            },{
                id:"North America",
                sub:[{
                    id:"Canada(AST)",
                    v:"-0400",
                    tag:"04F02|10L02"
                },{
                    id:"Canada(CST)",
                    v:"-0600",
                    tag:"04F02|10L02"
                },{
                    id:"Canada(EST)",
                    v:"-0500",
                    tag:"04F02|10L02"
                },{
                    id:"Canada(MST)",
                    v:"-0700",
                    tag:"04F02|10L02"
                },{
                    id:"Canada(NST)",
                    v:"-0330",
                    tag:"04F02|10L02"
                },{
                    id:"Canada(PST)",
                    v:"-0800",
                    tag:"04F02|10L02"
                },{
                    id:"Greenland(DK)",
                    v:"-0300"
                },{
                    id:"US(Central)",
                    v:"-0600",
                    tag:"03S02|11F02"
                },{
                    id:"US(Eastern)",
                    v:"-0500",
                    tag:"03S02|11F02"
                },{
                    id:"US(Mountain)",
                    v:"-0700",
                    tag:"03S02|11F02"
                },{
                    id:"US(Pacific)",
                    v:"-0800",
                    tag:"03S02|11F02"
                },{
                    id:"US(Alaska)",
                    v:"-0900"
                },{
                    id:"US(Arizona)",
                    v:"-0700"
                }]
            },{
                id:"South America",
                sub:[{
                    id:"Anguilla(UK)",
                    v:"-0400"
                },{
                    id:"Antigua&amp;Barbuda",
                    v:"-0400"
                },{
                    id:"Antilles(NL)",
                    v:"-0400"
                },{
                    id:"Argentina",
                    v:"-0300"
                },{
                    id:"Aruba(NL)",
                    v:"-0400"
                },{
                    id:"Bahamas",
                    v:"-0500"
                },{
                    id:"Barbados",
                    v:"-0400"
                },{
                    id:"Belize",
                    v:"-0600"
                },{
                    id:"Bolivia",
                    v:"-0400"
                },{
                    id:"Brazil(AST)",
                    v:"-0500",
                    tag:"10F03|02L03"
                },{
                    id:"Brazil(EST)",
                    v:"-0300",
                    tag:"10F03|02L03"
                },{
                    id:"Brazil(FST)",
                    v:"-0200",
                    tag:"10F03|02L03"
                },{
                    id:"Brazil(WST)",
                    v:"-0400",
                    tag:"10F03|02L03"
                },{
                    id:"British Virgin Is.(UK)",
                    v:"-0400"
                },{
                    id:"Cayman Is.(UK)",
                    v:"-0500"
                },{
                    id:"Chilean",
                    v:"-0300",
                    tag:"10F03|03F03"
                },{
                    id:"Chilean(Hanga Roa)",
                    v:"-0500",
                    tag:"10F03|03F03"
                },{
                    id:"Colombia",
                    v:"-0500"
                },{
                    id:"Costa Rica",
                    v:"-0600"
                },{
                    id:"Cuba",
                    v:"-0500",
                    tag:"04 13|10L03"
                },{
                    id:"Dominican",
                    v:"-0400"
                },{
                    id:"Ecuador",
                    v:"-0500"
                },{
                    id:"El Salvador",
                    v:"-0600"
                },{
                    id:"Falklands",
                    v:"-0300",
                    tag:"09F03|04F03"
                },{
                    id:"Grenada",
                    v:"-0400"
                },{
                    id:"Guadeloupe(FR)",
                    v:"-0400"
                },{
                    id:"Guatemala",
                    v:"-0600"
                },{
                    id:"Guiana(FR)",
                    v:"-0300"
                },{
                    id:"Guyana",
                    v:"-0400"
                },{
                    id:"Haiti",
                    v:"-0500"
                },{
                    id:"Honduras",
                    v:"-0600"
                },{
                    id:"Jamaica",
                    v:"-0500"
                },{
                    id:"Martinique(FR)",
                    v:"-0400"
                },{
                    id:"Mexico(Mazatlan)",
                    v:"-0700"
                },{
                    id:"Mexico(Tijuana)",
                    v:"-0800"
                },{
                    id:"Mexico(Mexico)",
                    v:"-0600"
                },{
                    id:"Montserrat(UK)",
                    v:"-0400"
                },{
                    id:"Nicaragua",
                    v:"-0500"
                },{
                    id:"Panama",
                    v:"-0500"
                },{
                    id:"Paraguay",
                    v:"-0400",
                    tag:"10F03|02L03"
                },{
                    id:"Peru",
                    v:"-0500"
                },{
                    id:"Puerto Rico(US)",
                    v:"-0400"
                },{
                    id:"So. Georgia&amp;So. Sandwich Is.(UK)",
                    v:"-0200"
                },{
                    id:"St. Kitts&amp;Nevis",
                    v:"-0400"
                },{
                    id:"St. Lucia",
                    v:"-0400"
                },{
                    id:"St. Vincent&amp;Grenadines",
                    v:"-0400"
                },{
                    id:"Suriname",
                    v:"-0300"
                },{
                    id:"Trinidad&amp;Tobago",
                    v:"-0400"
                },{
                    id:"Turks&amp;Caicos Is.(UK)",
                    v:"-0500"
                },{
                    id:"Uruguay",
                    v:"-0300"
                },{
                    id:"Venezuela",
                    v:"-0400"
                },{
                    id:"Virgin Is.(US)",
                    v:"-0400"
                }]
            },{
                id:"Africa(North)",
                sub:[{
                    id:"Algeria",
                    v:"+0100"
                },{
                    id:"Egypt",
                    v:"+0200",
                    tag:"04L53|09L43"
                },{
                    id:"Libyan",
                    v:"+0200"
                },{
                    id:"Morocco",
                    v:"+0000"
                },{
                    id:"Sudan",
                    v:"+0200"
                },{
                    id:"Tunisia",
                    v:"+0100"
                }]
            },{
                id:"Africa(Western)",
                sub:[{
                    id:"Benin",
                    v:"+0100"
                },{
                    id:"Burkina Faso",
                    v:"+0000"
                },{
                    id:"Canary Is.(SP)",
                    v:"-0100"
                },{
                    id:"Cape Verde",
                    v:"-0100"
                },{
                    id:"Chad",
                    v:"+0100"
                },{
                    id:"Gambia",
                    v:"+0000"
                },{
                    id:"Ghana",
                    v:"+0000"
                },{
                    id:"Guinea",
                    v:"+0000"
                },{
                    id:"Guinea-Bissau",
                    v:"+0000"
                },{
                    id:"Ivory Coast",
                    v:"+0000"
                },{
                    id:"Liberia",
                    v:"+0000"
                },{
                    id:"Mali",
                    v:"+0000"
                },{
                    id:"Mauritania",
                    v:"+0000"
                },{
                    id:"Niger",
                    v:"+0100"
                },{
                    id:"Nigeria",
                    v:"+0100"
                },{
                    id:"Senegal",
                    v:"+0000"
                },{
                    id:"Sierra Leone",
                    v:"+0000"
                },{
                    id:"Togo",
                    v:"+0000"
                },{
                    id:"Western Sahara",
                    v:"+0000"
                }]
            },{
                id:"Africa(Central)",
                sub:[{
                    id:"Cameroon",
                    v:"+0100"
                },{
                    id:"Cen.African Rep.",
                    v:"+0100"
                },{
                    id:"Congo,Democratic",
                    v:"+0100"
                },{
                    id:"Congo,Republic",
                    v:"+0100"
                },{
                    id:"Equatorial Guinea",
                    v:"+0100"
                },{
                    id:"Gabon",
                    v:"+0100"
                },{
                    id:"Sao Tome&amp;Principe",
                    v:"+0000"
                }]
            },{
                id:"Africa(East)",
                sub:[{
                    id:"Burundi",
                    v:"+0200"
                },{
                    id:"Comoros",
                    v:"+0300"
                },{
                    id:"Djibouti",
                    v:"+0300"
                },{
                    id:"Eritrea",
                    v:"+0300"
                },{
                    id:"Ethiopia",
                    v:"+0300"
                },{
                    id:"Kenya",
                    v:"+0300"
                },{
                    id:"Madagascar",
                    v:"+0300"
                },{
                    id:"Malawi",
                    v:"+0200"
                },{
                    id:"Mauritius",
                    v:"+0400"
                },{
                    id:"Mayotte(FR)",
                    v:"+0300"
                },{
                    id:"Mozambique",
                    v:"+0200"
                },{
                    id:"Reunion(FR)",
                    v:"+0400"
                },{
                    id:"Rwanda",
                    v:"+0200"
                },{
                    id:"Seychelles",
                    v:"+0300"
                },{
                    id:"Somalia",
                    v:"+0300"
                },{
                    id:"Tanzania",
                    v:"+0300"
                },{
                    id:"Uganda",
                    v:"+0300"
                }]
            },{
                id:"Africa(South)",
                sub:[{
                    id:"Angola",
                    v:"+0100"
                },{
                    id:"Botswana",
                    v:"+0200"
                },{
                    id:"Lesotho",
                    v:"+0200"
                },{
                    id:"Namibia",
                    v:"+0200",
                    tag:"09F03|04F03"
                },{
                    id:"Saint Helena(UK)",
                    v:"-0100"
                },{
                    id:"South Africa",
                    v:"+0200"
                },{
                    id:"Swaziland",
                    v:"+0200"
                },{
                    id:"Zambia",
                    v:"+0200"
                },{
                    id:"Zimbabwe",
                    v:"+0200"
                }]
            },{
                id:"Oceania",
                sub:[{
                    id:"American Samoa(US)",
                    v:"-1100"
                },{
                    id:"Australia(Adelaide)",
                    v:"+0930",
                    sub:"10L03|03L03"
                },{
                    id:"Australia(Brisbane)",
                    v:"+1000"
                },{
                    id:"Australia(Darwin)",
                    v:"+0930"
                },{
                    id:"Australia(Hobart)",
                    v:"+1000",
                    sub:"10L03|03L03"
                },{
                    id:"Australia(Perth)",
                    v:"+0800"
                },{
                    id:"Australia(Sydney)",
                    v:"+1000",
                    sub:"10L03|03L03"
                },{
                    id:"Cook Islands(NZ)",
                    v:"-1000"
                },{
                    id:"Eniwetok",
                    v:"-1200"
                },{
                    id:"Fiji",
                    v:"+1200",
                    sub:"11F03|02L03"
                },{
                    id:"Guam",
                    v:"+1000"
                },{
                    id:"Hawaii(US)",
                    v:"-1000"
                },{
                    id:"Kiribati",
                    v:"+1100"
                },{
                    id:"Marshall Is.",
                    v:"+1200"
                },{
                    id:"Micronesia",
                    v:"+1000"
                },{
                    id:"Midway Is.(US)",
                    v:"-1100"
                },{
                    id:"Nauru Rep.",
                    v:"+1200"
                },{
                    id:"New Calednia(FR)",
                    v:"+1100"
                },{
                    id:"New Zealand",
                    v:"+1200",
                    sub:"10F03|04F63"
                },{
                    id:"New Zealand(CHADT)",
                    v:"+1245",
                    sub:"10F03|04F63"
                },{
                    id:"Niue(NZ)",
                    v:"-1100"
                },{
                    id:"Nor. Mariana Is.",
                    v:"+1000"
                },{
                    id:"Palau",
                    v:"+0900"
                },{
                    id:"Papua New Guinea",
                    v:"+1000"
                },{
                    id:"Pitcairn Is.(UK)",
                    v:"-0830"
                },{
                    id:"Polynesia(FR)",
                    v:"-1000"
                },{
                    id:"Solomon Is.",
                    v:"+1100"
                },{
                    id:"Tahiti",
                    v:"-1000"
                },{
                    id:"Tokelau(NZ)",
                    v:"-1100"
                },{
                    id:"Tonga",
                    v:"+1300",
                    tag:"10F63|04F63"
                },{
                    id:"Tuvalu",
                    v:"+1200"
                },{
                    id:"Vanuatu",
                    v:"+1100"
                },{
                    id:"Western Samoa",
                    v:"-1100"
                },{
                    id:"Data Line",
                    v:"-1200"
                }]
            }
        ],
        //map like: MILLISECOND <=> ms
        _mapKeys:function(obj){
            var self=this, t=self._key2, m=self._key1;
            for(var i=0,l=m.length;i<l;i++)
                obj[t[i]]=obj[m[i]];
        },
        //get valid datepart
        _validUnit:function(datepart){
            return this.$UNIT[datepart]?datepart:'d';
        },
        _isDate:function(target)  {return !!target && target.constructor == Date},
        _date:function(value,df){return this._isDate(value)?value:this._isDate(df)?df:new Date},
        _isNumb:function(target)  {return typeof target == 'number' && isFinite(target)},
        _numb:function(value,df){return this._isNumb(value)?value:this._isNumb(df)?df:0},
        //time Zone like: -8
        _timeZone:-((new Date).getTimezoneOffset()/60),

        /*get specific date datepart
        *
        */
        get:function(date, datepart, firstDayOfWeek){
            var self=this;
            date = self._date(date);
            datepart = self._validUnit(datepart);
            firstDayOfWeek = self._numb(firstDayOfWeek);

            var map = arguments.callee.map || ( arguments.callee.map = {
                    ms:function(d){return d.getMilliseconds()},
                    s:function(d){return d.getSeconds()},
                    n:function(d){return d.getMinutes()},
                    h :function(d){return d.getHours()},
                    d:function(d){return d.getDate()},
                    ww:function(d,fd){return linb.Date.getWeek(d, fd)},
                    w :function(d,fd){return (7+d.getDay()-fd)%7},
                    m:function(d){return d.getMonth()},
                    q:function(d){return parseInt((d.getMonth()+3)/3-1)},
                    y :function(d){return d.getFullYear()},
                    de:function(d){return parseInt(d.getFullYear()/10)},
                    c:function(d){return parseInt(d.getFullYear()/100)}
                });
            return map[datepart](date,firstDayOfWeek);
        },
        /*
        * _fix(1,3,'0') => '100'
        */
        _fix:function(str,len,chr){
            len=len||2;
            chr=chr||'0';
            str+="";
            if(str.length<len)
                for(var i=str.length;i<len;i++)
                    str=chr+str;
            return str;
        },
        /*add specific datepart to date
        *
        */
        add: function(date, datepart, count ){
            var self=this,
                tu=self.$TIMEUNIT,
                map,
                date2;
            date = self._date(date);
            datepart = self._validUnit(datepart);


            if(!(map=arguments.callee.map)){
                map=arguments.callee.map = {
                    MILLISECOND:function(date,count){date.setTime(date.getTime() + count*tu.ms)},
                    SECOND:function(date,count){date.setTime(date.getTime() + count*tu.s)},
                    MINUTE:function(date,count){date.setTime(date.getTime() + count*tu.n)},
                    HOUR:function(date,count){date.setTime(date.getTime() + count*tu.h)},
                    DAY:function(date,count){date.setTime(date.getTime() + count*tu.d)},
                    WEEK:function(date,count){date.setTime(date.getTime() + count*tu.ww)},
                    MONTH:function(date,count){
                        var a=date.getDate(),b;
                        count = date.getMonth() + count;
                        this.YEAR(date, Math.floor(count/12));
                        date.setMonth((count%12+12)%12);
                        if((b=date.getDate())!=a)
                            this.DAY(date, -b)
                    },
                    QUARTER:function(date,count){this.MONTH(date,count*3)},
                    YEAR:function(date,count){
                        var a=date.getDate(),b;
                        date.setFullYear(date.getFullYear() + count)
                        if((b=date.getDate())!=a)
                            this.DAY(date, -b)
                    },
                    DECADE:function(date,count){this.YEAR(date,10*count)},
                    CENTURY:function(date,count){this.YEAR(date,100*count)}
                };
                self._mapKeys(map);
            }
            map[datepart](date2=new Date(date), count);
            return date2;
        },
        /*get specific datepart diff between startdate and date2
        *
        */
        diff:function(startdate, enddate, datepart, firstDayOfWeek) {
            var self=this;
            startdate = self._date(startdate);
            enddate = self._date(enddate);
            datepart = self._validUnit(datepart);
            firstDayOfWeek = self._numb(firstDayOfWeek);

            var tu=self.$TIMEUNIT,
                map;

            if(!(map=arguments.callee.map)){
                map = arguments.callee.map = {
                    MILLISECOND:function(startdate,enddate){return enddate.getTime()-startdate.getTime()},
                    SECOND:function(startdate,enddate){
                        var startdate = self.getTimSpanStart(startdate,'s'),
                            enddate = self.getTimSpanStart(enddate,'s'),
                            t=enddate.getTime()-startdate.getTime();
                        return t/tu.s;
                    },
                    MINUTE:function(startdate,enddate){
                        var startdate = self.getTimSpanStart(startdate,'n'),
                            enddate = self.getTimSpanStart(enddate,'n'),
                            t=enddate.getTime()-startdate.getTime();
                        return t/tu.n;
                    },
                    HOUR:function(startdate,enddate){
                        var startdate = self.getTimSpanStart(startdate,'h'),
                            enddate = self.getTimSpanStart(enddate,'h'),
                            t=enddate.getTime()-startdate.getTime();
                        return t/tu.h;
                    },
                    DAY:function(startdate,enddate){
                        var startdate = self.getTimSpanStart(startdate,'d',1),
                            enddate = self.getTimSpanStart(enddate,'d',1),
                            t=enddate.getTime()-startdate.getTime();
                        return t/tu.d;
                    },
                    WEEK:function(startdate,enddate,firstDayOfWeek){
                        var startdate = self.getTimSpanStart(startdate,'ww',1,firstDayOfWeek),
                            enddate = self.getTimSpanStart(enddate,'ww',1,firstDayOfWeek),
                            t=enddate.getTime()-startdate.getTime();
                        return t/tu.ww;
                    },
                    MONTH:function(startdate,enddate){return (enddate.getFullYear()-startdate.getFullYear())*12 + (enddate.getMonth()-startdate.getMonth())},
                    QUARTER:function(startdate,enddate){return (enddate.getFullYear()-startdate.getFullYear())*4 + parseInt((enddate.getMonth()-startdate.getMonth())/3)},
                    YEAR:function(startdate,enddate){return parseInt((enddate.getFullYear()-startdate.getFullYear()))},
                    DECADE:function(startdate,enddate){return parseInt((enddate.getFullYear()-startdate.getFullYear())/10)},
                    CENTURY:function(startdate,enddate){return parseInt((enddate.getFullYear()-startdate.getFullYear())/100)}
                };
                self._mapKeys(map);
            }
            return map[datepart](new Date(startdate),new Date(enddate),firstDayOfWeek);
        },
        /*get the first datepart begin of certain datepart
        *
        */
        getTimSpanStart: function(date, datepart, count, firstDayOfWeek) {
            var self=this,
                tu=self.$TIMEUNIT,
                map,date2;
            date = self._date(date);
            datepart = self._validUnit(datepart);
            firstDayOfWeek = self._numb(firstDayOfWeek);
            count=self._numb(count,1);
            if(!(map=arguments.callee.map)){
                var clearInDay = function(d) {
                        d.setMilliseconds(0);
                        d.setSeconds(0);
                        d.setMinutes(0);
                        d.setHours(0);
                    },
                    clearInYear = function(d) {
                        clearInDay(d);
                        d.setDate(1);
                        d.setMonth(0);
                    };

                map = arguments.callee.map = {
                    MILLISECOND:function(date,count){
                        var x = date.getMilliseconds();
                        date.setMilliseconds(x - (x % count));
                    },
                    SECOND:function(date,count){
                        date.setMilliseconds(0);
                        var x = date.getSeconds();
                        date.setSeconds(x - (x % count));
                    },
                    MINUTE:function(date,count){
                        date.setMilliseconds(0);
                        date.setSeconds(0);
                        var x = date.getMinutes();
                        date.setTime(date.getTime() - (x % count) * tu.n);
                    },
                    HOUR:function(date,count){
                        date.setMilliseconds(0);
                        date.setSeconds(0);
                        date.setMinutes(0);

                        var x = date.getHours();
                        date.setHours(x - (x % count));
                    },
                    DAY:function(date,count){
                        clearInDay(date);
                        var x=date.getDate();
                        date.setDate(x - (x % count));
                    },
                    WEEK:function(date,count,firstDayOfWeek){
                        clearInDay(date);

                        var d = (date.getDay() + 7 - firstDayOfWeek) % 7,date2,x, a=new Date();
                        date.setTime(date.getTime() - d * tu.d);
                        clearInYear(a);
                        a.setFullYear(date.getFullYear());
                        date2 = (a.getDay() + 7 - firstDayOfWeek) % 7;
                        a.setTime(a.getTime() - date2 * tu.d);

                        x= (date.getTime()-a.getTime())/tu.d/7;

                        date.setTime(date.getTime() - (x % count) * tu.ww);
                    },
                    MONTH:function(date,count){
                        clearInDay(date);
                        date.setDate(1);
                        var x = date.getMonth();
                        date.setMonth(x - (x % count));
                    },
                    QUARTER:function(date,count){
                        count=self._numb(count,1);
                        return this.MONTH(date, count*3);
                    },
                    YEAR:function(date,count){
                        clearInYear(date);
                        var x = date.getFullYear();
                        date.setFullYear(x - (x % count));
                    },
                    DECADE:function(date,count){
                        clearInYear(date);
                        date.setFullYear(Math.floor(date.getFullYear() / 10) * 10);
                    },
                    CENTURY:function(date,count){
                        clearInYear(date);
                        date.setFullYear(Math.floor(date.getFullYear() / 100) * 100);
                    }
                };
                self._mapKeys(map);

            }
            map[datepart](date2=new Date(date),count, firstDayOfWeek);
            return date2;
        },
        /*get the last datepart begin of certain datepart
        *
        */
        getTimSpanEnd : function(date, datepart, count,firstDayOfWeek) {
            var self=this;

            date = self._date(date);
            datepart = self._validUnit(datepart);
            firstDayOfWeek = self._numb(firstDayOfWeek);

            count=self._numb(count,1);

            var originalTime = date.getTime(),
                date2 = self.getTimSpanStart(date, datepart, count, firstDayOfWeek);
            if (date2.getTime() < originalTime)
                date2=self.add(date2, datepart, count);
            return date2;
        },
        /*fake a date for a certain timezone (based on the current timezone of "Date object")
        * You have to offset back it, if you expect a total real date:
        *   var localDate = new Date, timezone9Date=linb.Date.offsetTimeZone(localDate, 9);
        *   localDate.toString() == linb.Date.offsetTimeZone(timezone9Date, -9);
        */
        offsetTimeZone:function(date, timeZone, back){
            var self=this;
            date=self._date(date);
            return new Date(date.getTime() + (back?-1:1)*(timeZone - self._timeZone)*self.$TIMEUNIT.h);
        },

        /*get week
        *
        */
        getWeek:function(date, firstDayOfWeek){
            var self=this, date2, y;
            date=self._date(date);
            firstDayOfWeek = self._numb(firstDayOfWeek),
            y=date.getFullYear();

            date = self.add(self.getTimSpanStart(date, 'ww', 1, firstDayOfWeek),'d',6);

            if(date.getFullYear()!=y)return 1;

            date2 = self.getTimSpanStart(date, 'y', 1);
            date2 = self.add(self.getTimSpanStart(date2, 'ww', 1, firstDayOfWeek),'d',6);

            return self.diff(date2, date, 'ww')+1;
        },
        parse:function(str){
            str+="";
            var self=this,utc,
                me=arguments.callee,
                dp=me.dp||(me.dp={
                  FullYear: 2,
                  Month: 4,
                  Date: 6,
                  Hours: 8,
                  Minutes: 10,
                  Seconds: 12,
                  Milliseconds: 14
                }),
                match = str.match(me.iso||(me.iso=/^((-\d+|\d{4,})(-(\d{2})(-(\d{2}))?)?)?T((\d{2})(:(\d{2})(:(\d{2})(\.(\d{1,3})(\d)?\d*)?)?)?)?(([+-])(\d{2})(:(\d{2}))?|Z)?$/)),
                date = new Date(0)
                ;
            if(match){
                //month
                if(match[4])match[4]--;
                //ms to 3 digits
                if (match[15]>=5)match[14]++;
                utc = match[16]||match[18]?"UTC":"";
                for (var i in dp) {
                    var v = match[dp[i]];
                    if(!v)continue;
                    date["set" + utc + i](v);
                    if (date["get" + utc + i]() != match[dp[i]])
                        return null;
                }
                if(match[18]){
                    var h = Number(match[17] + match[18]),
                        m = Number(match[17] + (match[20] || 0));
                    date.setUTCMinutes(date.getUTCMinutes() + (h * 60) + m);
                }
                return date;
            }else{
                var r=Date.parse(str);
                return r?date.setTime(r) && date:null;
            }
        },
        getText:function(date, datepart, firstDayOfWeek){
            var self=this;
            date = self._date(date);
            firstDayOfWeek = self._numb(firstDayOfWeek);
            datepart=datepart||'';
            return self.$TEXTFORMAT[datepart](date, firstDayOfWeek);
        }
    }
});/* css
*  dependency: base _ ; Class ; linb ;
*/
Class("linb.CSS", null,{
    Static:{
        _r:linb.browser.ie?'rules':'cssRules',
        _baseid:'linb:css:base',
        _firstid:'linb:css:first',
        _lastid:'linb:css:last',
        _reg1:/\.(\w+)\[CLASS~="\1"\]/g,
        _reg2:/\[ID"([^"]+)"\]/g,
        _reg3:/\*([.#])/g,
        _reg4:/\s+/g,
        _reg5:/\*\|/g,
        _reg6:/(\s*,\s*)/g,
        _rep:function(str){
            var ns=this;
            return str.replace(ns._reg1,'.$1')
                     .replace(ns._reg2,'#$1')
                     .replace(ns._reg3,'$1')
                     .replace(ns._reg4,' ')
                     .replace(ns._reg5,'')
                     .replace(ns._reg6,',').toLowerCase();
        },
        _createCss:function(id, last){
            var ns=this,
                head=this._getHead(),
                fid=ns._firstid,
                lid=ns._lastid,
                fc,
                c;
            fc=document.createElement('style');
            fc.type="text/css";
            fc.id=id;
            if(!last){
                c= document.getElementById(fid) || head.firstChild;
                while((c=c.nextSibling) && !/^(script|link|style)$/i.test(''+c.tagName));
                if(c)
                    head.insertBefore(fc, c);
                else{
                    if(c= document.getElementById(lid))
                        head.insertBefore(fc, c);
                    else
                        head.appendChild(fc);
                }
            }else
                head.appendChild(fc);
            return fc;
        },
        _getCss:function(id, last){
            return document.getElementById(id) || this._createCss(id, last);
        },
        _getBase:function(){
            return this._getCss(this._baseid);
        },
        _getFirst:function(){
            return this._getCss(this._firstid);
        },
        _getLast:function(){
            return this._getCss(this._lastid, true);
        },
        _getHead:function(){
            return this._head || (this._head=document.getElementsByTagName("head")[0]||document.documentElement);
        },
        _check:function(){
            if(!linb.browser.ie)return;
            var count=0;
            for(var head = this._getHead(),i=0,t=head.childNodes,l;l=t[i++];)
                if(l.type=="text/css" )
                    count++
            return count>20;
        },
        get:function(property, value){
            for(var head = this._getHead(),i=0,t=head.childNodes,l;l=t[i++];)
                if(l.type=="text/css" && property in l && l[property]==value)
                    return l;
        },
        //if backOf==true, add to head last node
        //else add to the before position of the base styleSheet
        addStyleSheet:function(txt, id, backOf ){
            var e, ns=this, head = ns._getHead(),add=function(txt,id,backOf){
                var e = document.createElement('style');
                e.type="text/css";
                if(id)e.id=id;
                //for ie
                if(linb.browser.ie)
                    e.styleSheet.cssText = txt||'';
                else
                    try{e.appendChild(document.createTextNode(txt||''))}catch(p){e.styleSheet.cssText = txt||''}
                head.insertBefore(e, backOf  ?ns._getLast():ns._getBase());
                e.disabled=true;
                e.disabled=false;
                return e;
            },merge=function(txt,backOf){
                var e=backOf ?ns._getLast():ns._getBase();
                e.styleSheet.cssText +=txt;
                return e;
            };
            if(id && (id=id.replace(/[^\w\-\_\.\:]/g,'_')) && (e=ns.get('id',id)))
                return e;

            if(ns._check()){
                return merge(txt, backOf);
            }else
                return add(txt,id,backOf);
        },
        //if front==true, add to the before position of the base styleSheet
        //else add to the last postion
        includeLink:function(href, id, front, attr){
            var e, ns=this, head = ns._getHead();
            if(href && (e=ns.get('href',href))){}else{
                e = document.createElement('link');
                e.type = 'text/css';
                e.rel = 'stylesheet';
                e.href = href;
                if(id)
                    e.id=id;
                e.media = 'all';
                _.each(attr,function(o,i){
                    e.setAttribute(i,o);
                });
            }
            head.insertBefore(e, front?ns._getBase():ns._getLast());
            e.disabled=true;
            e.disabled=false;
            return e;
        },
        remove:function(property,value){
            var head = this._getHead();
            if(value=this.get(property,value)){
                value.disabled=true;
                head.removeChild(value);
            }
        },
        replaceLink:function(href, property, oValue, nValue){
            var ns=this,
                head=ns._getHead(),
                attr={},e,v;
            attr[property]=nValue;
            e=ns.includeLink(href,null,false,attr);
            if(v=ns.get(property,oValue))
                head.replaceChild(e,v);
            e.disabled=true;
            e.disabled=false;
        },
        _build:function(selector, value, flag){
            var t='';
            _.each(value,function(o,i){
                t += i.replace(/([A-Z])/g,"-$1").toLowerCase() + ":" + o +";";
            });
            return flag?t:selector+"{" + t + "}";
        },
        //selector: single css exp without ','; not allow '.a, .b{}'
        //  for *** IE *** allow single css exp only
        setStyleRules:function(selector, value, force){
            var ns=this,
                add=true,
                ds=document.styleSheets,
                target, target2, selectorText, bak, h, e, t, _t;
            selector = _.str.trim(selector.replace(/\s+/g,' '));
            if(!(value&&force)){
                bak=selector.toLowerCase();
                _.arr.each(_.toArr(ds),function(o){
                    try{o[ns._r]}catch(e){return}
                    _.arr.each(_.toArr(o[ns._r]),function(v,i){
                        if(!v.selectorText)return;
                        if(v.disabled)return;
                        selectorText = ns._rep(v.selectorText);
                        /*Notice: in IE, no ',' in any selectorTExt*/
                        _t=selectorText.split(',');
                        //null=>remove
                        if(!value){
                            add=false;
                            if(_.arr.indexOf(_t,bak)!=-1 && _t.length>1){
                                _t=_.arr.removeFrom(_t,_.arr.indexOf(_t,bak)).join(',');
                                t=v.cssText.slice(v.cssText.indexOf("{")+1,v.cssText.lastIndexOf("}"));
                                if(o.insertRule)
                                    o.insertRule(_t+"{" + t + "}", o[ns._r].length);
                                else if(o.addRule )
                                    o.addRule(_t, t);
                                if(o.deleteRule)
                                    o.deleteRule(i);
                                else
                                    o.removeRule(i);
                                o.disabled=true;
                                o.disabled=false;
                            }else if(selectorText == bak){
                                if(o.deleteRule)
                                    o.deleteRule(i);
                                else
                                    o.removeRule(i);
                                o.disabled=true;
                                o.disabled=false;
                            }
                        //modify the last one
                        }else{
                            //for single css exp, (all single css exp in IE)
                            if(selectorText==bak){target=v;return false}
                            //for multi css exps, not in IE
                            if(_.arr.indexOf(_t,bak)!=-1){target2=v;return false}
                        }
                    },null,true);
                    if(target){
                        add=false;
                        try{
                            _.each(value,function(o,i){
                                i=i.replace(/(-[a-z])/gi, function(m,a){return a.charAt(1).toUpperCase()});
                                target.style[i]= typeof o=='function'?o(target.style[i]):o;
                            })
                        }catch(e){}
                        o.disabled=true;
                        o.disabled=false;
                        return false;
                    //not in IE
                    }else if(target2){
                        add=false;
                        o.insertRule(ns._build(selector,value), o[ns._r].length);
                        o.disabled=true;
                        o.disabled=false;
                        return false;
                    }
                },null,true);
            }
            //need to add
            if(force || add)
                ns._addRules(selector,value);
            return ns;
        },
        $getCSSValue:function(selector, cssKey){
            var ns=this,
                k=ns._r,
                ds=document.styleSheets,
                l=ds.length,m, o,v,i,j,
                selectorText;
            selector=_.str.trim(selector.replace(/\s+/g,' '));
            for(i=l-1; i>=0; i--){
                m=(o=ds[i][k]).length;
                for(j=m-1; j>=0; j--){
                    if((v=o[j]).selectorText && !v.disabled){
                        selectorText = ns._rep(v.selectorText);
                        if(_.arr.indexOf(selectorText.split(','),selector)!=-1)
                            return v.style[cssKey];
                    }
                }
            }
        },
        _addRules:function(selector,value){
            var ns=this,
                target=ns._getLast(),
                changed=target.sheet || target.styleSheet;
            if(changed.insertRule)
                changed.insertRule(ns._build(selector,value), changed[ns._r].length);
            else if(changed.addRule )
                changed.addRule(selector, ns._build(selector,value,true));
            target.disabled=true;
            target.disabled=false;
            return ns;
        }
    },
    Initialize:function(){
        var b=linb.browser;
        this.addStyleSheet(""+
            "html{color:#000;background:#FFF;}"+
            "body{cursor:default;font:13px/1.231 arial,helvetica,clean,sans-serif;}"+
            (linb.browser.ie?"body{font-size:small;font:x-small;}":"")+
            "body *{line-height:1.22em;}"+
            "body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,textarea,p,blockquote,th,td{margin:0;padding:0;}"+
            "table{border-collapse:collapse;border-spacing:0;empty-cells:show;font-size:inherit;font:100%;}"+
            "fieldset,img{border:0;}"+
            "address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}"+
            "ol,ul,li{list-style:none;}"+
            "caption,th{text-align:left;}"+
            "h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}"+
            "q:before,q:after{content:'';}"+
            "abbr,acronym {border:0;font-variant:normal;}"+
            "sup {vertical-align:text-top;}"+
            "sub {vertical-align:text-bottom;}"+
            "input,textarea,select{font-family:inherit;font-size:inherit;font-weight:inherit;}"+
            (b.ie?"input,textarea,select{font-size:100%;}":"")+
            "legend{color:#000;}"+
            "del,ins{text-decoration:none;}"+
            "pre,code,kbd,samp,tt{font-family:monospace;"+(b.ie?"font-size:108%;":"")+"line-height:100%;}"+
            "select,input,button,textarea{font:99% arial,helvetica,clean,sans-serif;border-width:1px;}"+

            "a{color:#0000ee;text-decoration:none;"+(b.gek?"-moz-user-select:none;":"")+"}"+
            "a:hover{color:red}"+
            (b.gek?"a:focus{-moz-outline-offset:-1px !important}":"")+
            "div{font-size:12px;}"+
            "span{"+
            (b.gek?"display:-moz-inline-block;display:-moz-inline-box;display:inline-block;":
                b.ie6?"display:inline-box;display:inline;":"display:inline-block;")+
            (b.ie?"zoom:1;":"")+
            "}"+
            "h1{font-size:138.5%;}"+
            "h2{font-size:123.1%;}"+
            "h3{font-size:108%;}"+
            "h1,h2,h3{margin:1em 0;}"+
            "h1,h2,h3,h4,h5,h6,strong {font-weight:bold;}"+
            "em{font-style:italic;}"
        , 'linb.CSS');
    }   
});
Class('linb.DomProfile', 'linb.absProfile', {
    Constructor:function(domId){
        arguments.callee.upper.call(this);
        linb.$cache.profileMap[this.domId=domId]=this;
    },
    Instance:{
        __gc:function(){
            delete linb.$cache.profileMap[this.domId];
        },
        _getEV:function(funs, id, name){
            var t=linb.$cache.profileMap[id];
            if(t&&(t=t.events)&&(t=t[name]))
                for(var i=0,l=t.length;i<l;i++)
                    if(typeof t[t[i]]=='function')
                        funs[funs.length]=t[t[i]];
        }
    },
    Static:{
        get:function(id){
            return linb.$cache.profileMap[id];
        },
        $abstract:true
    }
});

//linb.absBox
Class('linb.absBox',null, {
    Constructor:function(){
        this._nodes=[];
    },
    Before:function(key){
        var t=linb.absBox;
        if(t)(t=t.$type)[key.replace('linb.','')]=t[key]=key;
    },
    Instance:{
        __gc:function(){
            this._nodes=0;
        },
        _get:function(index){
            var t=this._nodes;
            return  _.isNumb(index)?t[index]:t;
        },
        _empty:function(){
            this._nodes.length=0;
            return this;
        },
        get:function(index){
            return this._get(index);
        },
        _each:function(fun){
            var self=this,n;
            for(var i=0,j=self._nodes,l=j.length;i<l;i++)
                if(n=j[i])
                    if(false===fun.call(self,n,i))
                        break;
            n=null;
            return self;
        },
        each:function(fun){
            return this._each(fun);
        },
        isEmpty:function(){
            return !this._nodes.length;
        },
        merge:function(obj){
            if(this==linb.win||this==linb.doc||this==linb('body'))return this;
            var self=this, c=self.constructor, obj=obj._nodes, i=0, t, n=self._nodes;
            if(obj.length){
                for(;t=obj[i++];)n[n.length]=t;
                self._nodes=c._unique(n);
            }
            return self;
        },
        reBoxing:function(key,ensureValue){
            var self=this, t=linb.absBox.$type[key||'Dom'];
            if(t==self.KEY)return self;
            if(t=linb.SC(t))return t.pack(self._nodes, ensureValue);
        }
    },
    Static:{
        $abstract:true,
        $type:{},
        pack:function(arr, ensureValue){
            var o = new this(false);

            o._nodes =  !arr
                            ? []
                            : ensureValue===false
                            ? arr.constructor==Array
                                ? arr
                                : [arr]
                            : typeof this._ensureValues=='function'
                                ? this._ensureValues(arr)
                                : arr.constructor==Array
                                    ? arr
                                    : [arr];
            return o;
        },
        _unique:function(arr){
            var h={},a=[],i=0,t,k;
            for(;t=arr[i++];){
                k=typeof t=='string'? t : t.$linbid;
                if(!h[k]){
                    h[k]=1;
                    a[a.length]=t;
                }
            }
            return a;
        },
        plugIn:function(name, fun){
            this.prototype[name]=fun;
            return this;
        }
    }
});

/*linb.Dom
*/
Class('linb.Dom','linb.absBox',{
    Instance:{
        get:function(index){
            var purge=linb.$cache.domPurgeData,t=this._nodes,s;
            if(_.isNumb(index))
                return (s=t[index]) && (s=purge[s]) && s.element;
            else{
                var a=[],l=t.length;
                for(var i=0;i<l;i++)
                    a[a.length] = (s=purge[t[i]]) && s.element;
                return a;
            }
        },
        each:function(fun){
            var ns=this,purge=linb.$cache.domPurgeData,n;
            for(var i=0,j=ns._nodes,l=j.length;i<l;i++)
                if((n=purge[j[i]]) && (n=n.element))
                    if(false===fun.call(ns,n,i))
                        break;
            n=null;
            return ns;
        },

        serialize:function(){
            var a=[];
            this.each(function(o){
                a[a.length]=o.id;
            });
            return "linb(['"+a.join("','")+"'])";
        },
        //Need to consider the cache in linb.$cache.profileMap
        id:function(value, ignoreCache){
            var t,i,cache=linb.$cache.profileMap;
            if(typeof value == 'string')
                return this.each(function(o){
                    if((i=o.id)!==value){
                        if(!ignoreCache&&(t=cache[i])){
                            cache[value] = t;
                            delete cache[i];
                        }
                        o.id=value;
                    }
                });
            else
                return this.get(0).id;
        },

        /*dom collection
        fun: fun to run
        args: arguments for fun
        */
        $sum:function(fun, args){
            var arr=[],r,i;
            this.each(function(o){
                r=fun.apply(o, args||[]);
                if(r){
                    if(_.isArr(r))
                        for(i=0;o=r[i];i++)
                            arr[arr.length]=o;
                    else
                        arr[arr.length]=r;
                }
            });
            return linb(arr);
        },
        /*get all dir children
        */
        children:function(){
            return this.$sum(function(){
                return _.toArr(this.childNodes)
            });
        },
        /* clone
         deep for clone all children
        */
        clone:function(deep){
            return this.$sum(function(){
                var n = this.cloneNode(deep?true:false),
                    children=n.getElementsByTagName('*'),
                    ie=linb.browser.ie,
                    i=0,o;
                if(ie) n.removeAttribute('$linbid');
                else delete n.$linbid;
                for(;o=children[i];i++){
                    if(ie) o.removeAttribute('$linbid');
                    else delete o.$linbid;
                }
                return n;
            },arguments);
        },
        /* iterator
        // type: left : x-axis,  top :y-axis, xy: x-axis and y-axis
        // dir : true => left to right; top to buttom, false => right to left ; bottom to top
        // inn: does start consider children
         fun : number or function => number is iterator index; function is "return true ->stop"
        */
        $iterator:function(type, dir, inn, fun, top){
            return this.$sum(function(type, dir, inn, fun, top){
                var self=arguments.callee;
                if(typeof fun != 'function'){
                    var count=fun||0;
                    fun = function(n,index){return index==count;}
                }
                var index=0,m,n=this,flag=0,t;
                while(n){
                    if(n.nodeType==1)
                        if(fun(n, index++)===true)break;

                    //x-axis true: right ;false: left
                    if(type=='x')
                        n= dir?n.nextSibling:n.previousSibling;
                    //y-axis true: down ;false: up
                    else if(type=='y')
                        n= dir ? self.call(dir===1?n.lastChild:n.firstChild, 'x',(dir!==1), true, 0, top) : n.parentNode;
                    else{
                        inn=_.isBool(inn)?inn:true;
                        m=null;
                        n= dir ?
                                 (t = inn && n.firstChild ) ? t
                                              : (t = n.nextSibling ) ? t
                                                              :(m=n.parentNode)
                               : (t = inn && n.lastChild) ? t
                                              : (t = n.previousSibling ) ? t
                                                              :(m=n.parentNode);
                        if(m){
                            while(!( m = dir ? n.nextSibling: n.previousSibling)){
                                n=n.parentNode;
                                //to the top node
                                if(!n)
                                    if(flag)
                                        return null;
                                    else{
                                        flag=true;
                                        m = dir ? document.body.firstChild : document.body.lastChild;
                                        break;
                                    }
                            }
                            n=m;
                        }
                        inn=true;
                    }
                }
                return n;
            },arguments);
        },
        /*
        query('div');
        query('div','id');
        query('div','id','a');
        query('div','id',/^a/);
        query('div',function(){return true});
        */
        query:function(tagName, property, expr){
            tagName = tagName||'*';
            var f='getElementsByTagName',
                me=arguments.callee, f1=me.f1||(me.f1=function(tag, attr, expr){
                var all = this[f](tag), arr=[];
                if(expr.test(this[attr]))
                    arr[arr.length]=this;
                for(var o,i=0; o=all[i]; i++)
                    if(expr.test(o[attr]))
                        arr[arr.length]=o;
                return arr;
            }),f2=me.f2||(me.f2=function(tag, attr, expr){
                var all = this[f](tag), arr=[];
                if(this[attr]==expr)
                    arr[arr.length]=this;
                for(var o,i=0; o=all[i]; i++)
                    if(o[attr]==expr)
                        arr[arr.length]=o;
                return arr;
            }),f3=me.f3||(me.f3=function(tag, attr, expr){
                var all = this[f](tag), arr=[];
                if(this[attr])
                    arr[arr.length]=this;
                for(var o,i=0; o=all[i]; i++)
                    if(o[attr])
                        arr[arr.length]=o;
                return arr;
            }),f4=me.f4||(me.f4=function(tag){
                return _.toArr(this[f](tag));
            }),f5=me.f5||(me.f5=function(tag, attr){
                var all = this[f](tag), arr=[];
                if(attr(this))
                    arr[arr.length]=this;
                for(var o,i=0; o=all[i]; i++)
                    if(attr(o))
                        arr[arr.length]=o;
                return arr;
            });
            return this.$sum(property?typeof property=='function'?f5:expr?expr.constructor == RegExp?f1:f2:f3:f4, [tagName, property, expr]);
        },

        /*
        dom add implementation
        for addPrev prepend addNext append
        */
        $add:function(fun,target,reversed){
            if(_.isHash(target) || _.isStr(target))
                target=linb.create(target);
            if(reversed){
                reversed=linb(target);
                target=this;
            }else{
                target=linb(target);
                reversed=this;
            }
            if(target._nodes.length){
                var one=reversed.get(0),
                    ns=target.get(),
                    dom=linb.Dom,
                    cache=linb.$cache.profileMap,
                    fragment,uiObj,p,i,o,j,v,uiObj,arr=[];
                target.each(function(o){
                    uiObj=(p=o.id)&&(p=cache[p])&&p.LayoutTrigger&&dom.getStyle(one,'display')!='none'&&p.LayoutTrigger;
                    if(uiObj)arr.push([uiObj,p]);
                });
                if(ns.length==1)
                    fragment=ns[0];
                else{
                    fragment=document.createDocumentFragment();
                    for(i=0;o=ns[i];i++)
                        fragment.appendChild(o);
                }
                fun.call(one,fragment);
                for(i=0;o=arr[i];i++){
                    for(j=0;v=o[0][j];j++)
                        v.call(o[1]);
                    if(o[1].onLayout)
                        o[1].boxing().onLayout(o[1]);
                }
                arr.length=0;

                one=o=fragment=null;
            }

            return this;
        },
        prepend:function(target,reversed){
            return this.$add(function(node){
                if(this.firstChild) this.insertBefore(node, this.firstChild);
                else this.appendChild(node);
            },target,reversed);
        },
        append:function(target,reversed){
            return this.$add(function(node){
                this.appendChild(node);
            },target,reversed);
        },
        addPrev:function(target,reversed){
            return this.$add(function(node){
                this.parentNode.insertBefore(node,this);
            },target,reversed);
        },
        addNext:function(target,reversed){
            return this.$add(function(node){
                if(this.nextSibling) this.parentNode.insertBefore(node,this.nextSibling);
                else this.parentNode.appendChild(node);
            },target,reversed);
        },

        //flag: false => no remove this from momery(IE)
        replace:function(target, triggerGC){
            target=linb(target);
            var v,i,c=this.get(0),ns=target.get(),l=ns.length;
            if(l>0 && (v=ns[l-1])){
                c.parentNode.replaceChild(v,c);
                for(i=0;i<l-1;i++)
                    v.parentNode.insertBefore(ns[i],v);
                //for memory __gc
                if(triggerGC)
                    this.remove();
            }
            c=v=null;
            return target;
        },
        swap:function(target){
            var self=this,t = linb.Dom.getEmptyDiv().html('*',false);

            target=linb(target);

            self.replace(t,false);
            target.replace(self,false);
            t.replace(target,false);

            t.get(0).innerHTML='';
            document.body.insertBefore(t.get(0), document.body.firstChild);
            return self;
        },
        //flag : false => remove from dom tree, not free memory
        remove:function(triggerGC){
            var c=linb.$getGhostDiv();
            if(triggerGC===false)
                this.each(function(o,i){
                    if(o.parentNode)o.parentNode.removeChild(o);
                });
            else{
                this.each(function(o){
                    c.appendChild(o);
                });
                linb.$purgeChildren(c);
                c.innerHTML='';
                c=null;
            }
            return this;
        },
        //set innerHTML empty
        //flag = false: no gc
        empty:function(triggerGC){
            return this.each(function(o){
                linb([o]).html('',triggerGC);
            });
        },

        //flag = false: no gc
        html:function(content,triggerGC){
            var s='',t,o=this.get(0);triggerGC=triggerGC!==false;
            if(content!==undefined){
                if(o.nodeType==3)
                    o.nodeValue=content;
                else{
                     if(!o.firstChild && content=="")return this;
                     // innerHTML='' in IE, will clear it's childNodes innerHTML
                     if(!triggerGC && linb.browser.ie)while(t=o.firstChild)o.removeChild(t);
                     //clear first
                     if(triggerGC)
                        linb.$purgeChildren(o);
                     o.innerHTML=content;
                    //if(triggerGC)
                    //    linb.UI.$addEventsHanlder(o);

                }
                o=null;
                return this;
            }else{
                r = (o.nodeType==3)?o.nodeValue:o.innerHTML;
                o=null;
                return r;
            }
        },
        outerHTML:function(content, triggerGC){
            var self=this, t,s='', o=self.get(0),id=o.id;
            if(content!==undefined){
                var n=self.replace(_.str.toDom(content),false);
                self._nodes[0]=n._nodes[0];

                //avoid inner nodes memory leak
                linb([o]).remove(triggerGC);
                return self;
            }else{
                if(linb.browser.gek){
                    var m = linb.$getGhostDiv();
                    m.appendChild(self.get(0).cloneNode(true));
                    s=m.innerHTML;
                    m.innerHTML="";
                    m=null;
                }else{
                    s= o.outerHTML;
                }
                o=null;
                return s;
            }
        },
        text:function(content){
            if(content!==undefined){
                var self=this, arr=[];
                self.each(function(o){
                    var t=o.firstChild;
                     if(t&&t.nodeType!=1)
                        t.nodeValue = content;
                     else
                        arr[arr.length]=o;
                });
                if(arr.length){
                    linb(arr).empty().each(function(o){
                        o.appendChild(document.createTextNode(content));
                    })
                }
                return self;
            }else{
               return (function(o){
                  var i,a=o.childNodes,l=a.length,content='',me=arguments.callee;
                  for(i=0;i<l;i++)
                    if(a[i].nodeType!= 8)
                      content += (a[i].nodeType!=1) ? a[i].nodeValue : me(a[i]);
                  return content;
                })(this.get(0));
            }
        },
        /*
        .attr(name)=>get attr
        .attr(name,value)=>set attr
        .attr(name,null)=>remove attr
        */
        attr:function(name, value){
            //set one time only
            var self=this,
                me = arguments.callee,
                map1 = me.map1 || (me.map1 = {
                    'class':'className',
                    readonly: "readOnly",
                    tabindex: "tabIndex",
                    'for':'htmlFor',
                    maxlength: "maxLength",
                    cellspacing: "cellSpacing",
                    rowspan: "rowSpan",
                    value:'value'
                }),
                map2 = me.map2||(me.map2={
                    href:1,src:1,style:1
                });

            if(typeof name=='object'){
                for(var i in name)
                    me.call(self,i,name[i]);
                return self;
            }

            var iestyle = linb.browser.ie && name=='style',
                normal=!map2[name=map1[name]||name];
            if(value!==undefined){
                return self.each(function(o){
                    //remove attr
                    if(value===null){
                        if(iestyle)o.style.cssText='';
                        else if(normal){
                            try{
                                o[name]=null;
                                if(o.nodeType==1)o.removeAttribute(name)
                            }catch(e){}
                        }
                    //set attr
                    }else{
                        if(iestyle)o.style.cssText=''+value;
                        else if(normal){
                             o[name]=value;
                             if(o.nodeType==1 && name!="value" && typeof value=='string')o.setAttribute(name, value);
                        }else
                            o.setAttribute(name, value);
                    }
                 });
            //get attr
            }else{
                var r,o=self.get(0);
                if(iestyle) return o.style.cssText;
                if(name=="selected"&&linb.browser.kde) o.parentNode.selectedIndex;
                r=((name in o) && normal)?o[name]:o.getAttribute(name, linb.browser.ie && !normal ? 2 : undefined );
                o=null;
                return r;
            }
        },
        /*
        name format: 'xxxYxx', not 'xxx-yyy'
        left/top/width/height like, must specify 'px'
        Does't fire onResize onMove event
        */
        css:function(name, value){
            return (typeof name=='object' || value!==undefined)
                ?
                this.each(function(o){
                    linb.Dom.setStyle(o,name,value)
                })
                :
                linb.Dom.getStyle(this.get(0), name)
        },
        /*
        *IE/opera \r\n will take 2 chars
        *in IE: '/r/n'.lenght is 2, but range.moveEnd/moveStart will take '/r/n' as 1.
        */
        caret:function(begin,end){
            var input =this.get(0), tn=input.tagName, type=typeof begin,ie=linb.browser.ie, pos;
            if(!/^(input|textarea)$/i.test(tn))return this;
            input.focus();
            //set caret
            if(type=='number'){
                if(ie){
                    var r = input.createTextRange();
                    r.collapse(true);
                    r.moveEnd('character', end);
                    r.moveStart('character', begin);
                    r.select();
                }else
                    input.setSelectionRange(begin, end);
                return this;
            //replace text
            }else if(type=='string'){
                    var r=this.caret(),l=0,m=0,ret,
                        v=input.value,
                        reg1=/\r/g;
                    //for IE, minus \r
                    if(ie){
                        l=v.substr(0,r[0]).match(reg1);
                        l=(l && l.length) || 0;
                        m=begin.match(reg1);
                        m=(m && m.length) || 0;
                    }
                    //opera will add \r to \n, automatically
                    if(linb.browser.opr){
                        l=begin.match(/\n/g);
                        l=(l && l.length) || 0;
                        m=begin.match(/\r\n/g);
                        m=(m && m.length) || 0;
                        m=l-m;l=0;
                    }
                    input.value=v.substr(0,r[0])+begin+v.substr(r[1],v.length);
                    ret= r[0] - l + m + begin.length;
                    this.caret(ret,ret);
                    return ret;
            //get caret
            }else{
                if(ie){
                    var r=document.selection.createRange(),
                        txt=r.text,
                        l=txt.length,
                        e,m;
                    if(tn.toLowerCase()=='input'){
                        r.moveStart('character', -input.value.length);
                        e=r.text.length;
                        return [e-l,e];
                    }else{
                    	var rb=r.duplicate();
                    	rb.moveToElementText(input);
                    	rb.setEndPoint('EndToEnd',r);
                    	e=rb.text.length;
                    	return [e-l, e];
                    }
                //firefox opera safari
                }else
                    return [input.selectionStart, input.selectionEnd];
            }
        },
        //left,top format: "23px"
        show:function(left,top){
            var style,t,auto='auto',v=linb.Dom.HIDE_VALUE,vv;
            return this.each(function(o){
                if(o.nodeType != 1)return;
                style=o.style;
                vv=linb.getNodeData(o);
                if( t = (top || (style.top==v && (vv._top || auto))))style.top = t;
                if( t = (left || (style.left==v && (vv._left || auto))))style.left = t;
                if(t=vv._position)if(style.position!=t)style.position=t;
                vv._linbhide=0;

                if(style.visibility!='visible')style.visibility='visible';
                //ie6 bug
              /*  if(linb.browser.ie6){
                    t=style.wordWrap=='normal';
                    _.asyRun(function(){
                        style.wordWrap=t?'break-word':'normal'
                    })
                }*/
            });
        },
        hide:function(){
            var style,t,vv;
            return this.each(function(o){
                if(o.nodeType != 1)return;
                style=o.style;t=linb([o]);
                vv=linb.getNodeData(o);
                if(vv._linbhide!==1){
                    vv._position = style.position;
                    vv._top = style.top;
                    vv._left = style.left;
                    vv._linbhide=1;
                }
                if(style.position!='absolute')style.position = 'absolute';
                style.top = style.left = linb.Dom.HIDE_VALUE;
            });
        },
        cssRegion:function(region,triggerEvent) {
            var self=this;
            if(typeof region=='object'){
                var i,t,m,  node=self.get(0), dom=linb.Dom, f=dom._setPxStyle,m={};
                for(var j=0,c=dom._boxArr;i=c[j++];)
                    m[i] = ((i in region) && region[i]!==null)?f(node,i,region[i]):false;
                if(triggerEvent){
                    var f=dom.$hasEventHandler;
                    if(f(node,'onsize') && (m.width||m.height))self.onSize(true, {width:m.width,height:m.height});
                    if(f(node,'onmove') && (m.left||m.top))self.onMove(true, {left:m.left,top:m.top});
                }
                return self;
            }else{
                var offset=region,parent=triggerEvent,
                    pos = offset?self.offset(null,parent):self.cssPos(),
                    size = self.cssSize();
                return {
                    left:pos.left,
                    top:pos.top,
                    width:size.width,
                    height:size.height
                };
            }
        },
        //for quick size
        cssSize:function(size,triggerEvent) {
            var self=this, node=self.get(0),r,dom=linb.Dom,f=dom._setPxStyle,b1,b2;
           if(size){
                var t;
                b1 = size.width!==null?f(node,'width',size.width):false;
                b2 = size.height!==null?f(node,'height',size.height):false;
                if(triggerEvent && (b1||b2) && dom.$hasEventHandler(node,'onsize'))self.onSize(true, {width:b1,height:b2});
                r=self;
            }else
                r={ width :self._W(node,1)||0,  height :self._H(node,1)};
            return r;
        },
        //for quick move
        cssPos:function(pos, triggerEvent){
            var node=this.get(0),dom=linb.Dom,f=dom._setPxStyle,b1,b2,r;
            if(pos){
                var t;
                b1 = pos.left!=null?f(node,'left',pos.left):false;
                b2 = pos.top!==null?f(node,'top',pos.top):false;
                if(triggerEvent && (b1||b2) && dom.$hasEventHandler(node,'onmove'))this.onMove(true, {left:b1,top:b2});
                r=this;
            }else{
                f=dom.getStyle;
                r={left :parseInt(f(node, 'left'))||0,  top :parseInt(f(node, 'top'))||0};
            }
            node=null;
            return r;
        },
/*
+--------------------------+
|margin                    |
| #----------------------+ |
| |border                | |
| | +------------------+ | |
| | |padding           | | |
| | | +--------------+ | | |
| | | |   content    | | | |

# is the offset position in jsLinb
*/
        offset:function (pos,boundary){
            var r,t,
            browser = linb.browser,
            ns=this,
            node = ns.get(0),
            keepNode=node,
            parent =node.parentNode,
            op=node.offsetParent,
            doc=node.ownerDocument,
            dd=doc.documentElement,
            db=doc.body,
            _d=/^inline|table.*$/i,
            getStyle=linb.Dom.getStyle,
            fixed = getStyle(node, "position") == "fixed",

            me=arguments.callee,
            add= me.add || (me.add=function(pos, l, t){
                pos.left += parseInt(l,10)||0;
                pos.top += parseInt(t,10)||0;
            }),
            border=me.border || ( me.border = function(node, pos){
                add(pos, getStyle(node,'borderLeftWidth'), getStyle(node,'borderTopWidth'));
            }),
            TTAG=me.TTAG||(me.TTAG={TABLE:1,TD:1,TH:1}),
            HTAG = me.HTAG ||(me.HTAG={BODY:1,HTML:1}),
            posDiff=me.posDiff ||(me.posDiff=function(o,target){
                var cssPos = o.cssPos(),absPos = o.offset(null,target);
                return {left :absPos.left-cssPos.left, top :absPos.top-cssPos.top};
            });

            boundary=boundary?linb(boundary).get(0):doc;

            if(pos){
                //all null, return dir
                if(pos.left===null&&pos.top===null)return ns;
                var d = posDiff(ns,boundary);
                ns.cssPos({left :pos.left===null?null:(pos.left - d.left),  top :pos.top===null?null:(pos.top - d.top)});
                r=ns;
            }else{
                //for IE, firefox3(except document.body)
                if(!(linb.browser.gek && node===document.body) && node.getBoundingClientRect){
                    t = node.getBoundingClientRect();
                    pos = {left :t.left, top :t.top};
                    if(boundary.nodeType==1 && boundary!==document.body)
                        add(pos, -(t=boundary.getBoundingClientRect()).left+boundary.scrollLeft, -t.top+boundary.scrollTop);
                    else
                        add(pos, Math.max(dd.scrollLeft, db.scrollLeft)-dd.clientLeft, Math.max(dd.scrollTop,  db.scrollTop)-dd.clientTop);
                }else{
                    pos = {left :0, top :0};
                    add(pos, node.offsetLeft, node.offsetTop );
                    //get offset, stop by boundary or boundary.offsetParent
                    while(op && op!=boundary && op!=boundary.offsetParent){
                        add(pos, op.offsetLeft, op.offsetTop);
                        if(browser.kde || (browser.gek && !TTAG[op.tagName]))
                            border(op, pos);
                        if ( !fixed && getStyle(op,"position")== "fixed")
                            fixed = true;
                        if(op.tagName!='BODY')
                            keepNode=op.tagName=='BODY'?keepNode:op;
                        op = op.offsetParent;
                    }

                    //get scroll offset, stop by boundary
                    while (parent && parent.tagName && parent!=boundary && !HTAG[parent.tagName]){
                        if(!_d.test(getStyle(parent, "display")) )
                            add(pos, -parent.scrollLeft, -parent.scrollTop );
                        if(browser.gek && getStyle(parent,"overflow")!= "visible" )
                            border(parent,pos);
                        parent = parent.parentNode;
                    }
                    if((browser.gek && getStyle(keepNode,"position")!="absolute"))
                        add(pos, -db.offsetLeft, -db.offsetTop);
                    if(fixed)
                        add(pos, Math.max(dd.scrollLeft, db.scrollLeft), Math.max(dd.scrollTop,  db.scrollTop));
                }
                r=pos;
            }
            return r;
        },

//class and src
        hasClass:function(name){
            var arr = this.get(0).className.split(/\s+/);
            return _.arr.indexOf(arr,name)!=-1;
        },
        addClass:function(name){
            var arr, t, me=arguments.callee,reg=(me.reg||(me.reg=/\s+/));
            return this.each(function(o){
                arr = (t=o.className).split(reg);
                if(_.arr.indexOf(arr,name)==-1)
                    o.className = t + " " +name;
            });
        },
        removeClass:function(name){
            var arr, i,l,a, t, bs=typeof name=='string', me=arguments.callee,reg=(me.reg||(me.reg=/\s+/));
            return this.each(function(o){
                arr = o.className.split(reg);
                l=arr.length;
                a=[];
                for(i=0;t=arr[i];i++)
                    if(bs?(t!=name):(!name.test(String(t))))
                        a[a.length]=t;
                if(l!=a.length)o.className=a.join(' ');
            });
        },
        replaceClass:function(regexp,replace){
            var n,r;
            return this.each(function(o){
                r = (n=o.className).replace(regexp, replace);
                if(n!=r)o.className=r;
            });
        },
        tagClass:function(tag, isAdd){
            var self=this,
                me=arguments.callee,
                r1=me["_r1_"+tag]||(me["_r1_"+tag]=new RegExp("([-\\w]+" + tag + "[-\\w]*)")),
                r2=me["_r2"]||(me["_r2"]=/([-\w]+)/g);
            self.removeClass(r1);
            return (false===isAdd)? self : self.replaceClass(r2, '$1 $1' + tag);
        },
//events:
        /*
        $addEvent('onClick',fun,'idforthisclick';)
        $addEvent([['onClick',fun,'idforthisclick'],[...]...])

        do:
            add onclick to dom
            append fun to linb.$cache.profileMap.id.events.onClick array
            append 'onclick' to linb.$cache.profileMap.id.add array
        */

        $addEventHandler:function(name){
            var event=linb.Event,
                type,
                handler=event.$eventhandler;
            return this.each(function(o){
                if(o.nodeType==3)return;
                //set to purge map
                linb.setNodeData(o, ['eHandlers', 'on'+event._eventMap[name]], handler);

                //set to dom node
                if(type=event._eventHandler[name]){
                    o[type]=handler;
                    linb.setNodeData(o, ['eHandlers', type], handler);
                }
            });
        },
        /*
        'mousedown' -> 'dragbegin'
        'mouseover' -> 'dragenter'
        'mouseout' -> 'dragleave'
        'mouseup' -> 'drop'
        */
        $removeEventHandler:function(name){
            var event=linb.Event,
                type;
            return this.each(function(o){
                //remove from dom node
                if(type=event._eventHandler[name])
                    o[type]=null;

                //remove from purge map
                if(o=linb.getNodeData(o,'eHandlers'))
                    delete o['on'+event._eventMap[name]];
            });
        },
        $addEvent:function(name, fun, label, index){
            var self=this,
                event=linb.Event,
                arv=_.arr.removeValue,
                ari=_.arr.insertAny,
                id,c,t,m;

            if(!index && index!==0)index=-1;

            if(typeof label=='string')
                label="$"+label;
            else label=undefined;

            self.$addEventHandler(name).each(function(o){
                if(o.nodeType==3)return;

                if(!(id=event.getId(o)))
                    id=o.id=linb.Dom._pickDomId();

                if(!(c=linb.$cache.profileMap[id]))
                    c=new linb.DomProfile(id);

                t = c.events || (c.events = {});
                m = t[name] || (t[name]=[]);

                //if no label input, clear all, and add a single
                if(label===undefined){
                    m.length=0;
                    m=t[name]=[];
                    index=-1;
                    label='_';
                }
                m[label]=fun;
                arv(m,label);
                if(index==-1)m[m.length]=label;
                else
                    ari(m,label, index);

                if(c.clearCache)c.clearCache();
            });

            return self;
        },
        /*
        $removeEvent('onClick','idforthisclick')
        $removeEvent('onClick')
            will remove all onClick in linb.$cache.profileMap.id.events.
        $removeEvent('onClick',null,true)
            will remove all onClick/beforeClick/afterClick in linb.$cache.profileMap.id.events.
        */
        $removeEvent:function(name, label, bAll){
            var self=this,c,t,k,id,i,type,
                event=linb.Event,
                dom=linb.$cache.profileMap,
                type=event._eventMap[name];

            self.each(function(o){
                if(!(id=event.getId(o)))return;
                if(!(c=dom[id]))return;
                if(!(t=c.events))return;
                if(bAll)
                    _.arr.each(event._getEventName(type),function(o){
                        delete t[o];
                    });
                else{
                    if(typeof label == 'string'){
                        label='$'+label;
                        if(k=t[name]){
                            if(_.arr.indexOf(k,label)!=-1)
                                _.arr.removeValue(k,label);
                            delete k[label];
                        }
                    }else
                        delete t[name];
                }
                if(c.clearCache)c.clearCache();
            });

            return self;
        },
        $getEvent:function(name, label){
            var id;
            if(!(id=linb.Event.getId(this.get(0))))return;

            if(label)
                return _.get(linb.$cache.profileMap,[id,'events',name,'$' + label]);
            else{
                var r=[],arr = _.get(linb.$cache.profileMap,[id,'events',name]);
                _.arr.each(arr,function(o,i){
                    r[r.length]={o:arr[o]};
                });
                return r;
            }
        },
        $clearEvent:function(){
            return this.each(function(o){
                if(!(o=linb.Event.getId(o)))return;
                if(!(o=linb.$cache.profileMap[o]))return;
                _.breakO(o.events,2);
                delete o.events;

                _.arr.each(linb.Event._events,function(s){
                   o["on"+s]=null;
                });
            });
        },
        $fireEvent:function(name, args){
            var type=linb.Event._eventMap[name],
            t,s='on'+type,
            handler,
            hash,
            me=arguments.callee,
            f=linb.Event.$eventhandler,
            f1=me.f1||(me.f1=function(){this.returnValue=false}),
            f2=me.f2||(me.f2=function(){this.cancelBubble=true});
            return this.each(function(o){
                if(!(handler=linb.getNodeData(o,['eHandlers', s])))return;

                hash=_.copy(args);
                _.merge(hash,{
                    type: type,
                    target: o,
                    button : 1,
                    $e:true,
                    $name:name,
                    preventDefault:f1,
                    stopPropagation:f2
                },'all');

                if('blur'==type || 'focus'==type)
                    //try{
                        o[type].call(o,hash);
                    //}catch(e){}
                else
                    handler.call(o,hash);
            });
        },

//functions
        $canFocus:function(){
            var me=arguments.callee, getStyle=linb.Dom.getStyle, map = me.map || (me.map={a:1,input:1,select:1,textarea:1,button:1,object:1}),t,node;
            return !!(
                (node = this.get(0)) &&
                node.focus &&
                //IE bug: It can't be focused with 'default tabIndex 0'; but if you set it to 0, it can be focused.
                //So, for cross browser, don't set tabIndex to 0
                (((t=map[node.tagName.toLowerCase()]) && !(parseInt(node.tabIndex)<=-1)) || (!t && parseInt(node.tabIndex)>=(linb.browser.ie?1:0))) &&
                getStyle(node,'display')!='none' &&
                getStyle(node,'visibility')!='hidden' &&
                node.offsetWidth>0 &&
                node.offsetHeight>0
            );
        },
        focus:function(force){
            var ns=this;
            if(force || ns.$canFocus())
                try{ns.get(0).focus()}catch(e){}
            return ns;
        },
        setSelectable:function(value){
            var me=arguments.callee, _f = me._f || (me._f=function(){return false});
             return this.each(function(o){
                if(linb.browser.gek)
                    o.style.MozUserSelect=value?"all":"none"
                else{
                    o.unselectable=value?"off":"on";
                    o.onselectstart=value?null:_f;
                }
            })
        },
        setInlineBlock:function(){
            var ns=this;
            if(linb.browser.gek)
                ns.css('display','-moz-inline-block').css('display','-moz-inline-box').css('display','inline-block');
            else if(linb.browser.ie6)
                ns.css('display','inline-block').css({display:'inline',zoom:'1'});
            else
                ns.css('display','inline-block');
            return ns;
        },
        topZindex:function(flag){
            //set the minimum to 1000
            var i=1000, j=0, k, node = this.get(0), p = node.offsetParent, t, o;
            if(node.nodeType !=1 || !p)return 1;

            t=p.childNodes;
            for(k=0;o=t[k];k++){
                if(o==node || o.nodeType !=1 || !o.$linbid || o.style.display=='none' || o.style.visibility=='hidden' ||  linb.getNodeData(o,'zIndexIgnore') )continue;
                j = parseInt(o.style && o.style.zIndex) || 0 ;
                i=i>j?i:j;
            }
            i++;
            if(i>=linb.Dom.TOP_ZINDEX)
                linb.Dom.TOP_ZINDEX =i+1000;

            if(flag)
                 node.style.zIndex = i;
            else{
                j = parseInt(node.style.zIndex) || 0;
                return i>j?i:j;
            }
            return this;
        },
        /*
        dir:true for next, false for prev
        inn:true for include the inner node
        set:true for give focus
        */
        nextFocus:function(downwards, includeChild, setFocus){
            downwards=_.isBool(downwards)?downwards:true;
            var self=this.get(0),node = this.$iterator('',downwards,includeChild,function(node){return node!==self && linb([node]).$canFocus()});
            if(!node.isEmpty() && setFocus!==false)node.focus();
            self=null;
            return node;
        },

        /*
        args:{
            with:[0,100],
            height:[0,100],
            left:[0,100]
            top:[0,100]
            opacity:[0,1],
            backgroundColor:['#ffffff','#000000']
            scrollTop:[0,100]
            scrollLeft:[0,100]
            fontSize:[12,18]
        }
        */
        animate: function(args, onStart, onEnd, time, step, type, threadid, unit){
            var me=arguments.callee,
            hash = me.lib ||  (me.lib = {
                linear:function(x,s){return x/s},
                expoIn:function(x,s){return (x/s==0)?0:Math.pow(2,10*(x/s-1))},
                expoOut:function(x,s){return (x/s==1)?1:-Math.pow(2,-10*x/s)+1},
                expoInOut:function(x,s){
                    if(x==0)return 0;
			        else if(x==s)return 1;
			        else if((x/=s/2) < 1) return 1/2 * Math.pow(2, 10 * (x - 1));
			        return 1/2 * (-Math.pow(2, -10 * --x) + 2);
			    },
                sineIn:function(x,s){return -1*Math.cos(x/s*(Math.PI/2))+1},
                sineOut:function(x,s){return Math.sin(x/s*(Math.PI/2))},
                sineInOut:function(x,s){return -1/2*(Math.cos(Math.PI*x/s)-1)},
                backIn:function(x,s){
        			var n=1.70158;
        			return (x/=s)*x*((n+1)*x - n);
        		},
        		backOut:function(x,s){
        			var n=1.70158;
        			return ((x=x/s-1)*x*((n+1)*x + n) + 1);
        		},
        		backInOut:function(x,s){
        			var n=1.70158;
        			if ((x/=s/2) < 1) return 1/2*(x*x*(((n*=(1.525))+1)*x - n));
        			return 1/2*((x-=2)*x*(((n*=(1.525))+1)*x + n) + 2);
        		},
        		bounceOut:function(x,s){
        			if((x/=s) < (1/2.75))return 7.5625*x*x;
        			else if(x < (2/2.75))return 7.5625*(x-=(1.5/2.75))*x + .75;
        			else if(x < (2.5/2.75))return 7.5625*(x-=(2.25/2.75))*x + .9375;
        			else return 7.5625*(x-=(2.625/2.75))*x + .984375;
			    }
            }),
            color = me.color || (me.color = function(type, args, step, j){
                var f,fun,value = 0 + (100-0)*hash[type](j,step), from = args[0], to = args[1];

                if(typeof from !='string' || typeof to != 'string')return '#fff';
                if(value<0)
                    return from;
                else if(value>100)
                    return to;

                f=function(str){
                    return (str.charAt(0)!='#')?('#'+str):str;
                };
                from=f(from);to=f(to);

                f=function(str, i, j){
                    return parseInt(str.slice(i,j),16)||0;
                };
                fun=function(o){
                    return {red:f(o,1,3),green:f(o,3,5),blue:f(o,5,7)}
                };
                from = fun(from);to = fun(to);

                f=function(from, to, value,c){
                    var r= from[c]+Math.round((value/100)*(to[c]-from[c]));
                    return (r < 16 ? '0' : '') + r.toString(16)
                };
                return '#' + f(from,to, value, 'red') + f(from,to, value, 'green') + f(from,to, value, 'blue');
            });

            time = time||100;
            step = step||5;
            type = hash[type]!==undefined?type:'expoIn';

            var self=this, count=0,
                funs=[function(threadid){
                    //try{
                       // if(++count > step)throw new Error;
                        if(++count > step){
                            linb.Thread(threadid).abort();
                            return false;
                        }
                        _.each(args,function(o,i){
                            if(typeof o == 'function') o(hash[type](count,step));
                            else{
                                var value = String( _.str.endWith(i.toLowerCase(),'color') ? color(type, o, step, count) : (o[0] + (o[1]-o[0])*hash[type](count,step)));
                                (self[i]) ? (self[i](value+(unit||''))) :(self.css(i, value+(unit||'')));
                            }
                        });
                    //}catch(e){
                    //    linb.Thread(threadid).abort();
                    //    color=hash=null;
                   // }
                }];
            return linb.Thread(threadid||_.id(), funs, Math.max(time/step-9,0), null, onStart, onEnd ,true);
        },
        /*
        pos: {left:,top:} or dom element
        parent:parent node
        type:1,2,3,4
        */
        popToTop : function(pos, type, parent){
            var region, target=this,  t;

            parent=linb(parent);
            if(parent.isEmpty())parent=linb('body');

            //prepare
            target.css({position:'absolute',left:linb.Dom.HIDE_VALUE, top:linb.Dom.HIDE_VALUE,display:'block', zIndex:linb.Dom.TOP_ZINDEX});

            if(pos['linb.Dom'] || pos.nodeType==1 || typeof pos=='string'){
                type = (type || 1).toString();
                var node=linb(pos),
                    //base region
                    abspos = node.offset(null, parent);
                region = {
                    left:abspos.left,
                    top:abspos.top,
                    width:node.offsetWidth(),
                    height:node.offsetHeight()
                };
             }else{
                type = type?'3':'0';
                t=type=='0'?0:8;
                region = pos.region || {
                    left:pos.left-t,
                    top:pos.top-t,
                    width:t*2,
                    height:t*2
                };
            }
            pos={left :0, top :0};

            //window edge
            var t=linb.win, box = {};
            box.left=t.scrollLeft();
            box.top=t.scrollTop();
            box.width =t.width()+box.left;
            box.height =t.height()+box.top;
/*
type:1
    +------------------+    +------------------+
    |        3         |    |        4         |
    +--------------+---+    +---+--------------+
    |              |            |              |
    |              |            |              |
    +--------------+---+    +---+--------------+
    |        1         |    |        2         |
    +------------------+    +------------------+
type:2
                         +---+              +---+
                         |   |              |   |
+---+--------------+---+ |   +--------------+   |
|   |              |   | | 3 |              | 4 |
| 2 |              | 1 | |   |              |   |
|   +--------------+   | +---+--------------+---+
|   |              |   |
+---+              +---+
type:3
                         +---+              +---+
                         | 3 |              | 4 |
    +--------------+     +---+--------------+---+
    |              |         |              |
    |              |         |              |
+---+--------------+---+     +--------------+
| 2 |              | 1 |
+---+              +---+
type:4
                     +------------------+
                     | 3                |
+--------------+---+ |   +--------------+ +----+--------------+ +--------------+----+
|              |   | |   |              | |    |              | |              |    |
|              |   | |   |              | |    |              | |              |    |
+--------------+   | +---+--------------+ |    +--------------+ +--------------+    |
|                1 |                      |  2                | |               4   |
+------------------+                      +-------------------- +-------------------+
*/

            //target size
            var w = target.offsetWidth(), h = target.offsetHeight(),
                hi,wi;
            switch(type){
                case '1':
                    hi=false;wi=true;
                break;
                case '2':
                    hi=true;wi=false;
                break;
                case '3':
                    hi=false;wi=false;
                break;
                case '4':
                    hi=wi=true;
                break;
            }

            if(hi){
                if(region.top + h < box.height)
                    pos.top=region.top;
                else
                    pos.top=region.top+region.height-h;
            }else{
                if(region.top + region.height + h < box.height)
                    pos.top=region.top + region.height;
                else
                    pos.top=region.top - h;
            }
            if(wi){
                if(region.left + w < box.width)
                    pos.left=region.left;
                else
                    pos.left=region.left+region.width-w;
            }else{
                if(region.left + region.width + w < box.width)
                    pos.left=region.left + region.width;
                else
                    pos.left=region.left - w;
            }

            //over right
            if(pos.left + w>  box.width)pos.left = box.width - w;
            //over left
            if(pos.left < box.left)pos.left = box.left;
            //over bottom
            if(pos.top + h>  box.height)pos.top = box.height - h;
            //over top
            if(pos.top < box.top)pos.top = box.top;
            //show
            target.cssPos(pos).css({visibility:'visible',display:'block'});

            //ensure show target on the top of the other elements with the same zindex
            parent.get(0).appendChild(target.get(0))

            return this;
        },
        //for remove obj when blur
        setBlurTrigger : function(id, trigger, group){
            var ns=this,
                doc=document,
                sid='$blur_triggers$',
                fun=linb.Dom._blurTrigger||(linb.Dom._blurTrigger=function(p,e){
                    var me=arguments.callee,
                        p=linb.Event.getPos(e),
                        arr=me.arr,
                        a=_.copy(arr),
                        b, pos, w, h, v;
                    //filter first
                    _.arr.each(a,function(i){
                        b=true;
                        if(!(v=arr[i].target))b=false;
                        else
                            v.each(function(o){
                                if(!linb.Dom.byId(o.id))
                                    return b=false;
                            });
                        if(!b){
                            _.arr.removeValue(arr,i);
                            delete arr[i];
                        };
                    });
                    a=_.copy(arr);
                    _.arr.each(a,function(i){
                        v=arr[i];
                        b=true;
                        v.target.each(function(o){
                            if(o.parentNode && (w=o.offsetWidth) && (h=o.offsetHeight)){
                                pos=linb([o]).offset();
                                if(p.left>=pos.left && p.top>=pos.top && p.left<=(pos.left+w) && p.top<=(pos.top+h))
                                    return b=false;
                            }
                        });
                        if(b){
                            _.tryF(v.trigger,[],v.target);
                            _.arr.removeValue(arr,i);
                            delete arr[i];
                        }else
                            //if the top layer popwnd cant be triggerred, prevent the other layer popwnd trigger
                            return false;
                    },null,true);
                    a.length=0;
                }),
                arr=fun.arr||(fun.arr=[]),
                target;
            if(group){
                //keep the original refrence
                if(group['linb.Dom'])
                    target=group;
                else if(_.isArr(group)){
                    target=linb();
                    target._nodes=group;
                }
            }else
                target=ns;
            
            if(!doc.onmousedown)doc.onmousedown=linb.Event.$eventhandler;
            target.each(function(o){if(!o.id)o.id=linb.Dom._pickDomId()});
            //remove this trigger
            if(!trigger){
                _.arr.removeValue(arr,id);
                delete arr[id];
            //double link
            }else
                if(arr[id]){
                    _.arr.removeValue(arr,id);
                    delete arr[id];
                }
                arr[id]={
                    trigger:trigger,
                    target:target
                };
                arr.push(id);
            return this;
        },
        //for firefox disappeared cursor bug in input/textarea
        $firfox2:function(){
            if(!linb.browser.gek2)return this;
            var ns=this;
            ns.css('overflow','hidden');
            _.asyRun(function(){ns.css('overflow','auto')});
            return ns;
        },
        //IE not trigger dimension change, when change height only in overflow=visible.
        ieRemedy:function(){
            if(linb.browser.ie){
                var dom=linb.Dom;
                if(!dom.$_ie)dom.$_ie=linb();
                dom.$_ie.merge(this);
                _.asyRun(function(){
                    if(!dom.$_ie.isEmpty())
                        dom.$_ie.css('wordWrap','break-word')
                });
                _.asyRun(function(){
                    if(!dom.$_ie.isEmpty()){
                        dom.$_ie.css('wordWrap','');
                        dom.$_ie._nodes.length=0;
                    }
                });
            }
            return this;
        },
        //for ie6
        fixPng:function(type){
            if(linb.browser.ie6)
                return this.each(function(n){
                    if(n.tagName=='IMG'){
                        n.style.height = n.height;
                        n.style.width = n.width;
                        n.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, src=" + n.src + ", sizingMethod="+type+")";
                        n.src = linb.ini.file_bg;
                    }
                });
        }
        /*,
        gekRemedy:function(){
            if(linb.browser.gek)
                return this.each(function(o,i){
                    if(i=o.style){
                        var b=i.zIndex||0;
                        i.zIndex=++b;
                        i.zIndex=b;
                    }
                });
        }*/
    },
    Static:{
        HIDE_VALUE : '-10000px',
        TOP_ZINDEX:10000,

        _boxArr:_.toArr('width,height,left,top,right,bottom'),
        _cursor:{},

        _pickDomId:function(){
            var id;
            do{id='linb_'+_.id()}while(document.getElementById(id))
            return id;
        },
        _map:{
            'html':1,
            'head':1,
            'body':1
        },
        _getTag:function(n){ return n ? n.$linbid ? n.$linbid : n.nodeType==1 ? linb.$registerNode(n).$linbid : 0 : 0},
        _ensureValues:function(obj){
            var t,i,map=this._map,a=[],
            //can't be obj, or opera will crash
            arr =  obj===window
                    ? ['!window']
                    : obj===document
                    ? ['!document']
                    : obj.constructor == Array
                    ? obj
                    : obj['linb.Dom']
                    ? obj._nodes
                    : obj._toDomElems
                    ? obj._toDomElems()
                    : typeof obj == 'function'
                    ? obj()
                    :[obj];
            for(i=0;i<arr.length;i++)
                if( t = !(t=arr[i])
                            ? 0
                            : t===window
                            ? '!window'
                            : t===document
                            ? '!document'
                            : typeof (t=arr[i])=='string'
                            ? t.charAt(0)=='!'
                                ?  t
                                : this._getTag( map[t] ? document.getElementsByTagName(t)[0] : document.getElementById(t))
                            : (t['linb.UIProfile']||t['linb.Template'])
                            ? t.renderId ? t.renderId : (t.boxing().render() && t.renderId)
                            : this._getTag(t)
                  )
                    a[a.length]=t;
            return a.length<=1?a:this._unique(a);
        },
        getStyle:function(node, name){
            if(!node || node.nodeType!=1)return '';

            var value,b;
            if(name=='opacity' && linb.browser.ie)
                b = name = 'filter';

            value= node.style[name];
            if(!value){
                var me = arguments.callee,t,
                map = me.map || (me.map = {'float':1,'cssFloat':1,'styleFloat':1}),
                c1 = me._c1 || (me._c1={}),
                c2 = me._c2 || (me._c2={}),
                name = c1[name] || (c1[name] = name.replace(/\-(\w)/g, function(a,b){return b.toUpperCase()})),
                name2 = c2[name] || (c2[name] = name.replace(/([A-Z])/g, "-$1" ).toLowerCase())
                ;
                if(map[name])
                    name = linb.browser.ie?"styleFloat":"cssFloat";
                //document.defaultView first, for opera 9.0
                value = ((t=document.defaultView) && t.getComputedStyle)?(t=t.getComputedStyle(node,null))?t.getPropertyValue(name2):'':(node.currentStyle&&(node.currentStyle[name]||node.currentStyle[name2]));
/*
                if(linb.browser.opr){
                    var map2 = me.map2 || (me.map2={left:1,top:1,right:1,bottom:1});
                    if(map2[name] && (linb.Dom.getStyle(node,'position')=='static'))
                        value = 'auto';
                }
*/
            }
            return b?value?(parseFloat(value.match(/alpha\(opacity=(.*)\)/)[1] )||0)/100:1:(value||'');
        },
        setStyle:function(node, name , value){
            if(node.nodeType != 1)return;
            if(typeof name == 'string'){
                var me=this.getStyle,
                c1 = me._c1 || (me._c1={}),
                r1 = me._r1 || (me._r1=/alpha\([^\)]*\)/ig);
                name = c1[name] || (c1[name] = name.replace(/\-(\w)/g, function(a,b){return b.toUpperCase()}));
                if(name=='opacity'){
                    value=parseFloat(value)||0;
                    value= value >0.9999 ? '' : linb.browser.ie ? "alpha(opacity="+ 100*value +")" : value;
                    if(linb.browser.ie){
                        node.zoom=1;
                        name='filter';
                        value = node.style.filter.replace(r1, "") + value;
                    }
                }
                node.style[name]=value;
            }else
                for(var i in name)
                    arguments.callee.call(this,node, i, name[i]);
        },
        _setPxStyle:function(node, key, value){
            if(node.nodeType != 1)return false;
            var style=node.style;
            if(value || value===0){
                value = ((''+parseFloat(value))==(''+value)) ? (parseInt(value)||0) + "px" : value +'';
                if((key=='width'||key=='height') && value.charAt(0)=='-')value='0';
                if(style[key]!=value){
                    style[key]=value;
                    return true;
                }
            }return false;
        },
        _emptyDivId:"linb.empty::",
        getEmptyDiv:function(sequence){
            var i=1,id,rt,style,o,t,count=0,doc=document,body=doc.body,ini=function(o){
                o.id=id;
                linb([o]).attr('style','position:absolute;visibility:hidden;overflow:visible;left:'+linb.Dom.HIDE_VALUE+';top:'+linb.Dom.HIDE_VALUE+';');
            };
            sequence=sequence || 1;
            while(1){
                id = this._emptyDivId + i;
                //don't remove this {
                if(o=linb.Dom.byId(id)){
                    //Using firstChild, for performance
                    if(!o.firstChild && ++count == sequence)
                        return linb([o]);
                }else{
                    o=doc.createElement('div');
                    ini(o,id);
                    if(body.firstChild)
                        body.insertBefore(o, body.firstChild);
                    else
                        body.appendChild(o);
                    rt=linb([o]);
                    body=o=null;
                    return rt;
                }
                i++;
            }
            body=o=null;
        },
        setCover:function(visible,label){
            // get or create first
            var me=arguments.callee,
                id="linb.temp:cover:",
                id2="linb.temp:message:",
                content = typeof visible=='string'?visible:'',
                o1,o2;

            if((o1=linb(id)).isEmpty()){
                linb('body').prepend(o1=linb.create('<div id="'+ id +'" style="position:absolute;display:none;left:0;top:0;background-image:url('+linb.ini.file_bg+')"><div id="'+id2+'" style="position:absolute;font-size:12px"></div></div>'));
                linb.setNodeData(o1.get(0),'zIndexIgnore',1)
            }
            o2=linb(id2);

            //clear
            if(!visible){
                if(typeof me._label =='string' && me._label!==label)
                    return;
                if(me._showed){
                    o2.empty(false);
                    o1.css({zIndex:0,cursor:'',display:'none'});
                    me._showed=false;
                }
                delete me._label;
            }else{
                if(typeof label=='string')me._label=label;
                var t = linb.win;
                if(!me._showed){
                    o1.css({zIndex:linb.Dom.TOP_ZINDEX*2,display:'',width:t.scrollWidth()+'px',height:t.scrollHeight()+'px',cursor:'wait'});
                    me._showed=true;
                }
                //show content
                if(content){
                    o2.css({left :t.scrollLeft()+t.width()/2+'px', top: t.scrollTop()+t.height()/2+'px'});
                    o2.html(content +'',false);
                }
            }
        },

        byId:function(id){
            return  document.getElementById(id||"");
        },
        $hasEventHandler:function(node, name){
            return linb.getNodeData(node,['eHandlers', name]);
        },
        /*
        action: uri
        data:hash{key:value}
        method:'post'(default) or 'get'
        target: uri target: _blank etc.
        */
        submit:function(action, data, method, target, enctype){
            data=_.isHash(data)?data:{};method=method||'get';action=action||'';target=target||'_blank';
            var _t=[];
            _.each(data,function(o,i){
                _t.push('<textarea name="'+i+'">'+(typeof o=='object'?_.serialize(o):o)+'</textarea>');
            });
            if(!_.isEmpty(data))_t.push('<input type="hidden" name="rnd" value="'+_()+'">');
            var d=_.str.toDom('<form target="'+target+'" action="'+action+'" method="'+method  + (enctype?'" enctype="' +enctype:'') +  '">'+_t.join('')+'</form>');
            linb.Dom.getEmptyDiv().append(d);
            d.get(0).submit();
            d.remove();
        },
        busy:function(label){
            linb.Dom.setCover(true,label);
        },
        free:function(label){
           linb.Dom.setCover(false,label);
        },
        animate:function(css, args, onStart, onEnd, time, step, type, threadid, unit){
            var node = document.createElement('div');
            _.merge(css,{position:'absolute', left:this.HIDE_VALUE, zIndex:this.TOP_ZINDEX+10});
            linb.Dom.setStyle(node, css);
            document.body.appendChild(node);
            return linb([node]).animate(args, onStart, function(){
                _.tryF(onEnd);
                if(node.parentNode)
                    node.parentNode.removeChild(node);
                node=null;
            }, time, step, type, threadid, unit);
        },
        //plugin event function to linb.Dom
        $enableEvents:function(name){
            if(!_.isArr(name))name=[name];
            var self=this,f;
            _.arr.each(name,function(o){
                f=function(fun, label, flag){
                    if(typeof fun  == 'function')
                        return this.$addEvent(o, fun, label, flag);
                    else if(fun===null)
                        return this.$removeEvent(o, label, flag);
                    var args = arguments[1] || {};
                    args.$all = (arguments[0]===true);
                    return this.$fireEvent(o, args)
                };
                f.$event$=1;
                self.plugIn(o, f)
            });
        }
    },
    After:function(d){
        var self=this;
       //getter
        _.each({ parent:['y',false], prev:['x',false], next:['x',true], first:['y',true], last:['y',1]},function(o,i){
            self.plugIn(i, function(index){
                return this.$iterator(o[0], o[1], true, index || 1)
            });
        });

        //readonly profile
        _.arr.each(_.toArr('offsetLeft,offsetTop,scrollWidth,scrollHeight'),function(o){
            self.plugIn(o,function(){
                var t=this.get(0),w=window,d=document;
                if(t==w||t==d){
                    if("scrollWidth"==o||"scrollHeight"==o){
                        var a=d.documentElement,b=d.body;
                        return Math.max(a[o], b[o]);
                    }else
                        t = linb.browser.contentBox ? d.documentElement : d.body;
                }
                return t[o];
            })
        });

        var p='padding',m='margin',b='border',c='inner',o='offset',r='outer',w='width',h='height',W='Width',H='Height',T='Top',L='Left',t='top',l='left',R='Right',B='Bottom';
        //dimesion
        _.arr.each([['_'+p+'H',p+T,p+B],
            ['_'+p+'W',p+L,p+R],
            ['_'+b+'H',b+T+W,b+B+W],
            ['_'+b+'W',b+L+W,b+R+W],
            ['_'+m+'W',m+L,m+R],
            ['_'+m+'H',m+T,m+B]
        ],function(o){
            //use get Style dir
            var node,fun=linb.Dom.getStyle;
            self.plugIn(o[0],function(){
                node = this.get(0);
                return (parseInt(fun(node, o[1])) + parseInt(fun(node, o[2]))) || 0;
            })
        });
        /*
        get W/H for

        1:width
        2:innerWidth
        3:offsetWidth
        4:outerWidth

        content-box
        +--------------------------+
        |margin                    |
        | +----------------------+ |
        | |border                | |
        | | +------------------+ | |
        | | |padding           | | |
        | | | +--------------+ | | |
        | | | |   content    | | | |
        |-|-|-|--------------|-|-|-|
        | | | |<-css width ->| | | |
        | | |<-  innerWidth  ->| | |
        | |<--  offsetWidth   -->| |
        |<--    outerWidth      -->|

        border-box
        +--------------------------+
        |margin                    |
        | +----------------------+ |
        | |border                | |
        | | +------------------+ | |
        | | |padding           | | |
        | | | +--------------+ | | |
        | | | |   content    | | | |
        |-|-|-|--------------|-|-|-|
        | | |<-   css width  ->| | |
        | | |<-  innerWidth  ->| | |
        | |<--  offsetWidth   -->| |
        |<--    outerWidth      -->|
        */

        _.arr.each([['_W',w, '_'+p+'W', '_'+b+'W', '_'+m+'W', c+W, o+W],
        ['_H',h, '_'+p+'H', '_'+b+'H', '_'+m+'H', c+H, o+H]],function(o){
            self.plugIn(o[0],function(node,index,value){
                var n,r,t,style=node.style,me=arguments.callee,contentBox=linb.browser.contentBox,
                r1=me.r1 || (me.r1=/%$/),
                getStyle=linb.Dom.getStyle,
                f=linb.Dom._setPxStyle,type=typeof value,t1;
                if(type=='undefined' || type=='boolean'){
                    if(value===true){
                        n=(getStyle(node,'display')=='none');
                        if(n){
                            var temp = linb.Dom.getEmptyDiv().html('*',false);
                            linb([node]).swap(temp);
                            var b,p,d;
                            b = style.visibility,p = style.position,d = style.display; p=p||'';b=b||'';d=d||'';
                            style.visibility = 'hidden'; style.position ='absolute';style.display = 'block';
                        }
                    }
                    t=linb([node]);
                    switch(index){
                        case 1:
                            r=getStyle(node,o[1]);
                            if(isNaN(parseInt(r)) || r1.test(r))
                                r = me(node,2) - (contentBox?t[o[2]]():0);
                            r=parseInt(r)||0;
                            break;
                        case 2:
                            r=node[o[6]]-t[o[3]]();
                            break;
                        case 3:
                            //for in firefox, offsetHeight/Width's bad performance
                            //if(node._bp)
                            //    r=node['_'+o[6]];
                            //else{
                            //    t1=_();
                                r=node[o[6]];
                            //    if(_()-t1>60){
                            //        node['_'+o[6]]=r;
                            //        node._bp=1;
                            //    }
                            //}
                            if(!r)
                                //get from css setting before css applied
                                r=me(node,1)+(contentBox?t[o[2]]():0)+t[o[3]]();
                            break;
                        case 4:
                            r=me(node,3);
                            r+=t[o[4]]();
                            break;
                    }
                    if(n){
                        style.display = d; style.position = p;style.visibility = b;
                        t.swap(temp);
                        temp.empty(false);
                    }
                    return parseInt(r)||0;
                }else{
                    switch(index){
                        case 1:
                            if(f(node, o[1], value))
                                if(linb.Dom.$hasEventHandler(node,'onsize')){
                                    var args={};args[o[1]]=1;
                                    linb([node]).onSize(true, args);
                                }
                            break;
                        case 2:
                            me(node, 1, value - (contentBox?linb([node])[o[2]]():0));
                            break;
                        case 3:
                            //back value for offsetHeight/offsetWidth slowly
                            me(node, 1, value - (t=linb([node]))[o[3]]() - (contentBox?t[o[2]]():0));
                            break;
                        case 4:
                            me(node, 1, value - (t=linb([node]))[o[4]]() - t[o[3]]() - (contentBox?t[o[2]]():0));
                            break;
                    }
                    //if(node._bp)
                    //    node['_'+o[6]]=null;
                }
            })
        });
        _.arr.each([[c+W,'_W',2],[o+W,'_W',3],[r+W,'_W',4],
         [c+H,'_H',2],[o+H,'_H',3],[r+H,'_H',4]],function(o){
            self.plugIn(o[0],function(value){
                var type=typeof value;
                if(type=='undefined' || type=='boolean')
                    return this[o[1]](this.get(0), o[2]);
                else
                    return this.each(function(v){
                        this[o[1]](v, o[2],value);
                    });
            })
        });
        _.arr.each([[l+'By',l],[t+'By',t],[w+'By',w],[h+'By',h]],function(o){
            self.plugIn(o[0],function(offset,triggerEvent){
                if(offset===0)return this;
                var m,args,k=o[1],fun=linb.Dom.getStyle;
                return this.each(function(node){
                    m=fun(node,k);
                    m=(parseInt(m)||0)+offset;
                    if(k=='width'||k=='height')m=m>0?m:0;
                    node.style[k]=m+'px';
                    if(triggerEvent){
                        args={};args[k]=1;
                        var f=linb.Dom.$hasEventHandler;
                        if((k=='left' || k=='top')&& f(node,'onmove'))
                            linb([node]).onMove(true, args);
                        if((k=='width' || k=='height')&& f(node,'onsize')){
                            linb([node]).onSize(true, args);
                        }
                    }
                },this)
            });
        });
        _.arr.each(['scrollLeft','scrollTop'],function(o){
            self.plugIn(o,function(value){
                if(value !==undefined)
                    return this.each(function(v){
                        v[o]=value;
                    });
                else{
                    var v=this.get(0);
                    if(v===window || v===document){
                        var a=document.documentElement,b=document.body;
                        if("scrollTop"==o)return window.pageYOffset || Math.max(a[o], b[o]);
                        if("scrollLeft"==o)return window.pageXOffset || Math.max(a[o], b[o]);
                    }
                    return v[o];
                }
            })
        });
        _.arr.each('width,height,left,top'.split(','),function(o){
            self.plugIn(o,function(value){
                var self=this, node=self.get(0),b=linb.browser,type=typeof value,doc=document,t;
                if(!node || node.nodeType==3)return;
                if(type=='undefined'||type=='boolean'){
                    if((o=='width' && (t='Width'))||(o=='height' && (t='Height'))){
                        if(doc===node)return Math.max( doc.body['scroll'+t], doc.body['offset'+t], doc.documentElement['scroll'+t], doc.documentElement['offset'+t]);
                        if(window===node)return b.opr?(doc.body['client'+t]||window['inner'+t]):b.kde?window['inner'+t]:(linb.browser.contentBox && doc.documentElement['client'+t]) ||doc.body['client'+t];
                    }
                    //give shortcut
                    if(o=='width')value=parseInt(node.style.width)||self._W(node,1,value);
                    else if(o=='height')value=parseInt(node.style.height)||self._H(node,1,value);
                    else
                        value = linb.Dom.getStyle(node, o);
                    return value=='auto'?value:(parseInt(value)||0);
                }else{
                    var f=linb.Dom._setPxStyle,t,a;
                    return self.each(function(v){
                        if(v.nodeType!=1)return;
                            if(v.style[o]!==value){
                                if(o=='width')self._W(v,1,value);
                                else if(o=='height')self._H(v,1,value);
                                else{
                                    if(f(v, o, value))
                                        if((o=='top' || o=='left') && linb.Dom.$hasEventHandler(node,'onmove')){
                                            a={};a[o]=1;
                                            linb([v]).onMove(true, a);
                                        }
                                }
                            }
                    });
                }
            });
        });

        //linb.Dom event
        _.arr.each(linb.Event._events,function(o){
            _.arr.each(linb.Event._getEventName(o),function(o){
                self.$enableEvents(o);
            })
        });
    },
    Initialize:function(){
        _.set(linb.$cache.domPurgeData,'!window',{$linbid:'!window',element:window});
        _.set(linb.$cache.domPurgeData,'!document',{$linbid:'!document',element:document});

        linb.win=linb(['!window'],false);
        linb.doc=linb(['!document'],false);

        linb.$inlineBlock=linb.browser.gek?['-moz-inline-block', '-moz-inline-box','inline-block'] : linb.browser.ie6? ['inline-block', 'inline'] : 'inline-block',
        //hot keys
        linb.doc.onKeydown(function(p,e){
            var event=linb.Event,set,
                ks=event.$keyboard=event.getKey(e);
            if(ks){
                if(ks[0].length==1)ks[0]=ks[0].toLowerCase();
                set = linb.$cache.hookKey[ks.join(":")];
                //if hot function return false, stop bubble
                if(set)
//                    try{
                        if(_.tryF(set[0],set[1],set[2])===false){
                            event.stopBubble(e);
                            return false;
                        }
//                    }catch(e){}
            }
            return true;
        },"document")
        .onKeyup(function(p,e){
            delete linb.Event.$keyboard;
        },"document");

        //hook link(<a ...>xxx</a>) click action
        //if(linb.browser.ie || linb.browser.kde)
            linb.doc.onClick(function(p,e,src){
                if(!linb.History)return;

                var s = location.href.split('#')[0],
                    t=linb.Event,
                    o = t.getSrc(e),b,i=0,
                    b
                ;
                do{
                    if(o.tagName == 'A'){
                        b=true;
                        break;
                    }
                    if(++i>8)break;
                }while(o=o.parentNode)
                if(b){
                    if(o.href.indexOf('javascript:')==0)return false;
                    if(!t.getKey(e)[2] && t.getBtn(e)=='left' && (o.href.indexOf(s+'#')==0||o.href.indexOf('#')==0)){
                        linb.History.setFI(o.href.replace(s,''));
                        return false;
                    }
                }
            },'hookA',0);

        //free memory
        linb.win.afterUnload(function(){
            //unlink link 'App'
            linb.SC.__gc();
            linb.Thread.__gc();
            linb([window, document]).$clearEvent();
            linb('body').empty();
            _.breakO(linb.$cache,2);
            _.breakO([linb,Class,_],3);
            window.Class=window.Namespace=window.linb=window._=undefined;
        },"window",-1);

    }
});Class('linb.Template','linb.absProfile',{
    Constructor:function(template,properties,events,domId){
        arguments.callee.upper.apply(this,arguments);
        
        var self=this;
        self.$domId = self.KEY + ':' + (self.serialId=self._pickSerialId()) + ':';
        self.domId = typeof domId == 'string'?domId:self.$domId;
        self._links={};
        self.template={'root':[['<div></div>'],[]]};
        self.properties={};
        self.events={};
        self.$template={};
        self.link(self.constructor._cache,'self').link(linb._pool,'linb');
        self.box=self.constructor;
        self.boxing=function(){return this};

        if(template)self.setTemplate(typeof template=='string'?{'root':template}:template);
        if(events)self.setEvents(events);
        if(properties)self.setProperties(properties);
        return self;
    },
    Instance : {
        renderId:null,
        __gc:function(){
            var self=this,
                t=linb.$cache.reclaimId;
            if(!self.$noReclaim) 
                (t[self.KEY] || (t[self.KEY]=[])).push(self.serialId);
            else 
                delete self.$noReclaim

            delete linb.$cache.profileMap[self.domId];
            delete linb.$cache.profileMap[self.$domId];
            self.unLinkAll();
            _.breakO([self.properties, self.event, self], 2);
        },
        _reg0:/^\w[\w_-]*$/,
        show:function(parent){
            if(!parent)parent=linb('body');
            parent=linb(parent);
            parent.append(this);
            return this;
        },
        getRootNode:function(){
            return linb.getNodeData(this.renderId, 'element');
        },
        /*
         *getRoot is the only function that depends on linb.Dom Class
        */
        getRoot:function(){
            return linb([this.renderId],false);
        },
        setDomId:function(id){
            var t=this, c=linb.$cache.profileMap, reg=t._reg0;
            //ensure the value
            if(typeof id== 'string' && reg.test(id) && !document.getElementById(id)){
                //delete the original one
                if(t.domId!=t.$domId)delete c[t.domId];
                //set profile's domId
                t.domId=id;
                //change the domNode id value
                if(t.renderId)
                    t.getRootNode().id=id;
                //if doesn't create yet, don't set it to linb.$cache:
                if(c[t.$domId])c[id]=t;
            }
            return t;
        },
        destroy:function(){
            if(this.renderId){
                var rn=this.getRootNode();
                linb.$purgeChildren(rn);
                if(rn.parentNode)
                    rn.parentNode.removeChild(rn);
                rn=null;
            }else this.__gc();          
        },
        setEvents:function(key,value){
            var self=this;
            if(typeof key == 'object')
                self.events=key;
            else
                self.events[key]=value;
            return self;
        },
        setTemplate:function(key,value){
            var self=this, t=self.template,$t=self.$template,h;
            if(typeof key == 'object'){
                self.template=key;
                h={};
                for(var i in key)
                    h[i||'root']=self._buildTemplate(key[i]);
                self.$template=h;
            }else if(typeof value == 'string')
                $t[key]=self._buildTemplate(t[key]=value);
            else
                $t['root']=self._buildTemplate(t['root']=key);
            return self;
        },
        setProperties:function(key,value){
            var self=this;
            if(typeof key == 'object')
                self.properties=key;
            else
                self.properties[key]=value;
            return self;
        },
        getItem:function(src){
            var obj=linb.getNodeData(src);
            if(!obj)return;

            var id=obj.tpl_evid, tpl_evkey=obj.tpl_evkey;
            if(!id || !tpl_evkey)return;

            var me=arguments.callee,
                f = me.f || (me.f = function(data, tpl_evkey, id){
                    var i,o,j,v;
                    for(j in data){
                        o=data[j];
                        if(_.isArr(o) && (tpl_evkey==j||tpl_evkey.indexOf((data.tpl_evkey||j)+'.')===0))
                            for(i=0;v=o[i];i++){
                                if(v.tpl_evkey==tpl_evkey&&v.id==id)return v;
                                else if(v=f(v,tpl_evkey,id)) return v;
                            }
                    }
                });
            return f(this.properties, tpl_evkey, id);
        } ,
        _pickSerialId:function(){
            //get id from cache or id
            var arr = linb.$cache.reclaimId[this.KEY];
            if(arr && arr[0])return arr.shift();
            return this.constructor._ctrlId.next();
        },
        render:function(){
            var self=this;
            if(!self.renderId){
                var div=linb.$getGhostDiv();
                linb.$cache.profileMap[self.domId]=linb.$cache.profileMap[self.$domId]=this;
                div.innerHTML = self.toHtml();
                //add event handler
                var ch=self.events,
                    eh=linb.Event._eventHandler,
                    children=div.getElementsByTagName('*'),
                    domId=self.$domId,
                    f=function(){return linb.Event(arguments[0],this,0,domId)},
                    i,l,j,k,o,key,id,t,v;
                if(l=children.length){
                    for(i=0;i<l;i++){
                        if((o=children[i]).nodeType!=1)continue;
                        key=o.getAttribute('tpl_evkey');
                        id=o.getAttribute('tpl_evid');
                        if(key!==null && id!==null){
                            v=linb.$registerNode(o);
                            v.tpl_evkey=key;
                            v.tpl_evid=id;
                            if(t = ch[key] ){
                                v=v.eHandlers||(v.eHandlers={});
                                for(j in t){
                                    //attach event handler to domPurgeData
                                    v[j]=f;
                                    //attach event handler to dom node
                                    if(k=eh[j])
                                        v[k]=o[k]=f;
                                }
                            }
                            o.removeAttribute('tpl_evkey');
                            o.removeAttribute('tpl_evid');
                        }
                    }
                    if(!div.firstChild.$linbid)
                        linb.$registerNode(div.firstChild);
                    //the first
                    self.renderId=div.firstChild.$linbid;
                }
                o=div=null;
            }
            return self;
        },
        refresh:function(){
            var ns=this;
            if(ns.renderId){
                var proxy = document.createElement('span'), 
                    rn = ns.getRootNode(),
                    cache=linb.$cache.profileMap;
                
                //avoid of being destroyed                
                delete cache[ns.domId];
                delete cache[ns.$domId];
                
                if(rn.parentNode)
                    rn.parentNode.replaceChild(proxy,rn);
                ns.destroy();
                
                delete ns.renderId;

                ns.render();

                if(proxy.parentNode)
                    proxy.parentNode.replaceChild(ns.getRootNode(), proxy);

                proxy=rn=null;
            }
            return ns;
        },
        renderOnto:function(node){
            var self=this,id,domNode,style='style',t;
            if(typeof node=='string')node=document.getElementById(node);
            id=node.id||self.domId;
            
            //ensure renderId
            if(!self.renderId)
                self.render();
            
            domNode=self.getRootNode();
            node.parentNode.replaceChild(domNode,node);

            if(domNode.tabIndex!=node.tabIndex)
                domNode.tabIndex!=node.tabIndex;
            if(node.className)
                domNode.className += node.className;
            if(linb.browser.ie && (t=node.style.cssText))
                domNode.style.cssText += t+'';
            else if(t=node.getAttribute(style))
                domNode.setAttribute(style, (domNode.getAttribute(style)||'') + t);

            this.setDomId(id);
        },
        toHtml:function(properties){
            //must copy it for giving a default tpl_evkey
            var p=_.copy(properties||this.properties||{});
            p.tpl_evkey="root";
            return this._doTemplate(p);
        },
        _reg1:/([^{}]*)\{([\w]+)\}([^{}]*)/g,
        _reg2:/\[event\]/g,
        _buildTemplate:function(str){
            if(typeof str=='string'){
                var obj=[[],[]],
                    a0=obj[0],
                    a1=obj[1];
                str=str.replace(this._reg2,' tpl_evid="{id}" tpl_evkey="{tpl_evkey}" ');
                str.replace(this._reg1,function(a,b,c,d){
                    if(b)a0[a0.length]=b;
                    a1[a0.length]=a0[a0.length]=c;
                    if(d)a0[a0.length]=d;
                    return '';
                });
                return obj;
            }else
                return str;
        },
        _getEV:function(funs, id, name, linbId){
            var obj=linb.getNodeData(linbId);
            if(!obj)return;

            var evs = this.events,
                tpl_evkey = obj.tpl_evkey,
                evg = (tpl_evkey&&evs&&evs[tpl_evkey])||evs,
                ev = evg&&evg[name];
            if(ev)funs.push(ev);
        },
        _reg3:/(^\s*<\w+)(\s|>)(.*)/,
        _doTemplate:function(properties, tag, result){
            if(!properties)return '';

            var self=this, me=arguments.callee,s,t,n,isA = properties.constructor == Array,
            template = self.$template,
            temp = template[tag||'root'],
            r = !result;

            result= result || [];
            if(isA){
                if(typeof temp != 'function')temp = me;
                for(var i=0;t=properties[i++];){
                    t.tpl_evkey=tag;
                    temp.call(self, t, tag, result);
                }
            }else{
                if(typeof temp == 'function')
                    temp.call(self, properties, tag, result);
                else{
                    tag = tag?tag+'.':'';
                    var a0=temp[0], a1=temp[1];
                    for(var i=0,l=a0.length;i<l;i++){
                        if(n=a1[i]){
                            if(n in properties){
                                t=typeof properties[n]=='function'?properties[n].call(self, n, properties):properties[n];
                                //if sub template exists
                                if(template[s=tag+n])
                                    me.call(self, t, s, result);
                                else
                                    result[result.length]=t;
                            }
                        }else
                            result[result.length]=a0[i];
                    }
                }
            }
            if(r){
                return result.join('')
                    .replace(self._reg3, '$1 id="'+self.$domId+'" $2$3');
            }
        },
        serialize:function(){
            var self=this,
                s=_.serialize,
                t=linb.absObj.$specialChars,
                properties = _.isEmpty(self.properties)?null:_.clone(self.properties,function(o,i){return !t[(i+'').charAt(0)]});            
            return 'new linb.Template(' + 
            s(self.template||null) + "," + 
            s(properties) + "," + 
            s(_.isEmpty(self.events)?null:self.events) + "," + 
            s(self.$domId!=self.domId?self.domId:null) + 
            ')';
        }
    },
    Static : {
        getFromDom:function(id){
            if((id=typeof id=='string'?id:(id && id.id)) &&(id=linb.$cache.profileMap[id]) && id['linb.Template'])
                return id.boxing();
        },
        _cache:[],
        _ctrlId : new _.id()
    }
});Class('linb.Template','linb.absProfile',{
    Constructor:function(template,properties,events,domId){
        arguments.callee.upper.apply(this,arguments);
        
        var self=this;
        self.$domId = self.KEY + ':' + (self.serialId=self._pickSerialId()) + ':';
        self.domId = typeof domId == 'string'?domId:self.$domId;
        self._links={};
        self.template={'root':[['<div></div>'],[]]};
        self.properties={};
        self.events={};
        self.$template={};
        self.link(self.constructor._cache,'self').link(linb._pool,'linb');
        self.box=self.constructor;
        self.boxing=function(){return this};

        if(template)self.setTemplate(typeof template=='string'?{'root':template}:template);
        if(events)self.setEvents(events);
        if(properties)self.setProperties(properties);
        return self;
    },
    Instance : {
        renderId:null,
        __gc:function(){
            var self=this,
                t=linb.$cache.reclaimId;
            if(!self.$noReclaim) 
                (t[self.KEY] || (t[self.KEY]=[])).push(self.serialId);
            else 
                delete self.$noReclaim

            delete linb.$cache.profileMap[self.domId];
            delete linb.$cache.profileMap[self.$domId];
            self.unLinkAll();
            _.breakO([self.properties, self.event, self], 2);
        },
        _reg0:/^\w[\w_-]*$/,
        show:function(parent){
            if(!parent)parent=linb('body');
            parent=linb(parent);
            parent.append(this);
            return this;
        },
        getRootNode:function(){
            return linb.getNodeData(this.renderId, 'element');
        },
        /*
         *getRoot is the only function that depends on linb.Dom Class
        */
        getRoot:function(){
            return linb([this.renderId],false);
        },
        setDomId:function(id){
            var t=this, c=linb.$cache.profileMap, reg=t._reg0;
            //ensure the value
            if(typeof id== 'string' && reg.test(id) && !document.getElementById(id)){
                //delete the original one
                if(t.domId!=t.$domId)delete c[t.domId];
                //set profile's domId
                t.domId=id;
                //change the domNode id value
                if(t.renderId)
                    t.getRootNode().id=id;
                //if doesn't create yet, don't set it to linb.$cache:
                if(c[t.$domId])c[id]=t;
            }
            return t;
        },
        destroy:function(){
            if(this.renderId){
                var rn=this.getRootNode();
                linb.$purgeChildren(rn);
                if(rn.parentNode)
                    rn.parentNode.removeChild(rn);
                rn=null;
            }else this.__gc();          
        },
        setEvents:function(key,value){
            var self=this;
            if(typeof key == 'object')
                self.events=key;
            else
                self.events[key]=value;
            return self;
        },
        setTemplate:function(key,value){
            var self=this, t=self.template,$t=self.$template,h;
            if(typeof key == 'object'){
                self.template=key;
                h={};
                for(var i in key)
                    h[i||'root']=self._buildTemplate(key[i]);
                self.$template=h;
            }else if(typeof value == 'string')
                $t[key]=self._buildTemplate(t[key]=value);
            else
                $t['root']=self._buildTemplate(t['root']=key);
            return self;
        },
        setProperties:function(key,value){
            var self=this;
            if(typeof key == 'object')
                self.properties=key;
            else
                self.properties[key]=value;
            return self;
        },
        getItem:function(src){
            var obj=linb.getNodeData(src);
            if(!obj)return;

            var id=obj.tpl_evid, tpl_evkey=obj.tpl_evkey;
            if(!id || !tpl_evkey)return;

            var me=arguments.callee,
                f = me.f || (me.f = function(data, tpl_evkey, id){
                    var i,o,j,v;
                    for(j in data){
                        o=data[j];
                        if(_.isArr(o) && (tpl_evkey==j||tpl_evkey.indexOf((data.tpl_evkey||j)+'.')===0))
                            for(i=0;v=o[i];i++){
                                if(v.tpl_evkey==tpl_evkey&&v.id==id)return v;
                                else if(v=f(v,tpl_evkey,id)) return v;
                            }
                    }
                });
            return f(this.properties, tpl_evkey, id);
        } ,
        _pickSerialId:function(){
            //get id from cache or id
            var arr = linb.$cache.reclaimId[this.KEY];
            if(arr && arr[0])return arr.shift();
            return this.constructor._ctrlId.next();
        },
        render:function(){
            var self=this;
            if(!self.renderId){
                var div=linb.$getGhostDiv();
                linb.$cache.profileMap[self.domId]=linb.$cache.profileMap[self.$domId]=this;
                div.innerHTML = self.toHtml();
                //add event handler
                var ch=self.events,
                    eh=linb.Event._eventHandler,
                    children=div.getElementsByTagName('*'),
                    domId=self.$domId,
                    f=function(){return linb.Event(arguments[0],this,0,domId)},
                    i,l,j,k,o,key,id,t,v;
                if(l=children.length){
                    for(i=0;i<l;i++){
                        if((o=children[i]).nodeType!=1)continue;
                        key=o.getAttribute('tpl_evkey');
                        id=o.getAttribute('tpl_evid');
                        if(key!==null && id!==null){
                            v=linb.$registerNode(o);
                            v.tpl_evkey=key;
                            v.tpl_evid=id;
                            if(t = ch[key] ){
                                v=v.eHandlers||(v.eHandlers={});
                                for(j in t){
                                    //attach event handler to domPurgeData
                                    v[j]=f;
                                    //attach event handler to dom node
                                    if(k=eh[j])
                                        v[k]=o[k]=f;
                                }
                            }
                            o.removeAttribute('tpl_evkey');
                            o.removeAttribute('tpl_evid');
                        }
                    }
                    if(!div.firstChild.$linbid)
                        linb.$registerNode(div.firstChild);
                    //the first
                    self.renderId=div.firstChild.$linbid;
                }
                o=div=null;
            }
            return self;
        },
        refresh:function(){
            var ns=this;
            if(ns.renderId){
                var proxy = document.createElement('span'), 
                    rn = ns.getRootNode(),
                    cache=linb.$cache.profileMap;
                
                //avoid of being destroyed                
                delete cache[ns.domId];
                delete cache[ns.$domId];
                
                if(rn.parentNode)
                    rn.parentNode.replaceChild(proxy,rn);
                ns.destroy();
                
                delete ns.renderId;

                ns.render();

                if(proxy.parentNode)
                    proxy.parentNode.replaceChild(ns.getRootNode(), proxy);

                proxy=rn=null;
            }
            return ns;
        },
        renderOnto:function(node){
            var self=this,id,domNode,style='style',t;
            if(typeof node=='string')node=document.getElementById(node);
            id=node.id||self.domId;
            
            //ensure renderId
            if(!self.renderId)
                self.render();
            
            domNode=self.getRootNode();
            node.parentNode.replaceChild(domNode,node);

            if(domNode.tabIndex!=node.tabIndex)
                domNode.tabIndex!=node.tabIndex;
            if(node.className)
                domNode.className += node.className;
            if(linb.browser.ie && (t=node.style.cssText))
                domNode.style.cssText += t+'';
            else if(t=node.getAttribute(style))
                domNode.setAttribute(style, (domNode.getAttribute(style)||'') + t);

            this.setDomId(id);
        },
        toHtml:function(properties){
            //must copy it for giving a default tpl_evkey
            var p=_.copy(properties||this.properties||{});
            p.tpl_evkey="root";
            return this._doTemplate(p);
        },
        _reg1:/([^{}]*)\{([\w]+)\}([^{}]*)/g,
        _reg2:/\[event\]/g,
        _buildTemplate:function(str){
            if(typeof str=='string'){
                var obj=[[],[]],
                    a0=obj[0],
                    a1=obj[1];
                str=str.replace(this._reg2,' tpl_evid="{id}" tpl_evkey="{tpl_evkey}" ');
                str.replace(this._reg1,function(a,b,c,d){
                    if(b)a0[a0.length]=b;
                    a1[a0.length]=a0[a0.length]=c;
                    if(d)a0[a0.length]=d;
                    return '';
                });
                return obj;
            }else
                return str;
        },
        _getEV:function(funs, id, name, linbId){
            var obj=linb.getNodeData(linbId);
            if(!obj)return;

            var evs = this.events,
                tpl_evkey = obj.tpl_evkey,
                evg = (tpl_evkey&&evs&&evs[tpl_evkey])||evs,
                ev = evg&&evg[name];
            if(ev)funs.push(ev);
        },
        _reg3:/(^\s*<\w+)(\s|>)(.*)/,
        _doTemplate:function(properties, tag, result){
            if(!properties)return '';

            var self=this, me=arguments.callee,s,t,n,isA = properties.constructor == Array,
            template = self.$template,
            temp = template[tag||'root'],
            r = !result;

            result= result || [];
            if(isA){
                if(typeof temp != 'function')temp = me;
                for(var i=0;t=properties[i++];){
                    t.tpl_evkey=tag;
                    temp.call(self, t, tag, result);
                }
            }else{
                if(typeof temp == 'function')
                    temp.call(self, properties, tag, result);
                else{
                    tag = tag?tag+'.':'';
                    var a0=temp[0], a1=temp[1];
                    for(var i=0,l=a0.length;i<l;i++){
                        if(n=a1[i]){
                            if(n in properties){
                                t=typeof properties[n]=='function'?properties[n].call(self, n, properties):properties[n];
                                //if sub template exists
                                if(template[s=tag+n])
                                    me.call(self, t, s, result);
                                else
                                    result[result.length]=t;
                            }
                        }else
                            result[result.length]=a0[i];
                    }
                }
            }
            if(r){
                return result.join('')
                    .replace(self._reg3, '$1 id="'+self.$domId+'" $2$3');
            }
        },
        serialize:function(){
            var self=this,
                s=_.serialize,
                t=linb.absObj.$specialChars,
                properties = _.isEmpty(self.properties)?null:_.clone(self.properties,function(o,i){return !t[(i+'').charAt(0)]});            
            return 'new linb.Template(' + 
            s(self.template||null) + "," + 
            s(properties) + "," + 
            s(_.isEmpty(self.events)?null:self.events) + "," + 
            s(self.$domId!=self.domId?self.domId:null) + 
            ')';
        }
    },
    Static : {
        getFromDom:function(id){
            if((id=typeof id=='string'?id:(id && id.id)) &&(id=linb.$cache.profileMap[id]) && id['linb.Template'])
                return id.boxing();
        },
        _cache:[],
        _ctrlId : new _.id()
    }
});/*
beforeCreated
onCreated
onLoadBaseClass
onIniResource
    iniResource (asy)
beforeIniComponents
    iniComponents (asy)
afterIniComponents
    iniExComs (asy)
onLoadReqiredClass
onReady
onRender
*/

Class('linb.Com',null,{
    Constructor:function(properties, events, host){
        var self=this;
        self._nodes=[];
        self.host=host||self;

        self.properties = properties || {};
        //copy those from class setting
        self.events = _.copy(self.events) || {};
        if(events)
            _.merge(self.events, events, 'all');
    },
    Instance:{
        setHost:function(value, alias){
            this.host=value;
            return value[alias]=this;
        },
        getHost:function(){
            return this.host;
        },
        setProperties:function(key,value){
            var self=this;
            if(!key)
                self.properties={};
            else if(typeof key=='string')
                self.properties[key]=value;
            else
                _.merge(self.properties, key, 'all');
            return self;
        },
        getProperties:function(key){
            return key?this.properties[key]:this.properties;
        },
        setEvents:function(key,value){
            var self=this;
            if(!key)
                self.events={};
            else if(typeof key=='string')
                self.events[key]=value;
            else
                _.merge(self.events, key, 'all');
            return self;
        },
        getEvents:function(key){
            return key?this.events[key]:this.events;
        },

        _fireEvent:function(name, args){
            var t, self=this;
            if(t=self.events[name]){
                if(typeof t=='string')t=self.host[t];
                args=args||[];
                args.splice(0,0,self,self.threadid);
                self.$lastEvent=name;
                if(typeof t=='function')
                    return t.apply(self.host, args);
            }
        },
        _innerCall:function(name){
            var self=this;
            return _.tryF(self[name],[self, self.threadid],self);
        },
        show:function(onEnd,parent,subId,threadid){
            var self=this,f=function(){
                self.render();
                if(self.customAppend)
                    self.customAppend.call(self, parent,subId,threadid);
                else
                    (parent||linb('body')).append(self.getUIComponents(),subId);
                _.tryF(onEnd,[self, threadid],self.host);
            };
            self.threadid=threadid;
            
            if(self.created)
                f();
            else
                self.create(f,threadid);
        },
        render:function(triggerLayOut){
            var self=this;
            self.getUIComponents().render(triggerLayOut);
            self._fireEvent('onRender');
            self.renderId='ok';
        },
        create:function(onEnd, threadid){
            //get paras
            var self=this,
                t,funs=[]
                ;
            self.threadid=threadid;

            if(false===self._fireEvent('beforeCreated'))return;
            //if no threadid or threadid doesnt exist, reset threadid to self
            funs.push(function(threadid){
                self.threadid=threadid;
                self._fireEvent('onCreated');
            });
            //base classes
            if((t=self.base) && t.length)
                funs.push(function(threadid){
                    linb.SC.groupCall(self.base,function(key){
                        self._fireEvent('onLoadBaseClass', [key]);
                    },null,threadid);
                });
            //load resource here
            if(self.iniResource)
                funs.push(function(){
                    self._fireEvent('onIniResource');
                    self._innerCall('iniResource');
                });
            //load required class
            if((t=self.required) && t.length)
                funs.push(function(threadid){
                    linb.SC.groupCall(self.required,function(key){
                        self._fireEvent('onLoadReqiredClass', [key]);
                    },null,threadid);
                });
            //inner components
            if(self.iniComponents)
                funs.push(function(){
                    if(false===self._fireEvent('beforeIniComponents'))return;
                    Array.prototype.push.apply(self._nodes, self._innerCall('iniComponents')||[]);
                    self._fireEvent('afterIniComponents');
                });
            //Outer components
            if(self.iniExComs)
                funs.push(function(){
                    self._innerCall('iniExComs');
                });
            //core
            funs.push(function(threadid){
                self.loaded=true;
                //lazy load
                if(self.background)
                    linb.SC.runInBG(self.background);
                self._fireEvent('onReady');
            });
            funs.push(function(threadid){
                _.tryF(onEnd,[self, threadid],self.host);
            });
            //use asyUI to insert tasks
            linb.Thread.observableRun(funs, function(){
                self.created=true;
            },threadid);
        },

        iniComponents:function(){},

/*
        +-----------+
        |  +-------+|
        |  |  +---+||
        |a |ab|abc|||
        |  |  +---+||
        |  +-------+|
        +-----------+
        1.thread start
        2.build a UI
            build ab UI
                build abc UI
        3.fill a data
            fill ab data
                fill abc data
        4.thread end

        requestData:function(group, onEnd, threadid){
            var thread=linb.Thread;
            thread.observableRun(function(t){
                linb.absIO.groupCall(group, null, null, onEnd,thread||t);
            },null,threadid);
        },
        composeUI:function(onEnd, threadid, flag){_.tryF(onEnd)},
        fillUI:function(onEnd, threadid, flag){_.tryF(onEnd)},
*/



        getUIComponents:function(){
            var nodes = _.copy(this._nodes),t,k='linb.UI';
            _.filter(nodes,function(o){
                return !!(o.box[k] && !o.box.$noDomRoot);
            });
            return linb.UI.pack(nodes, false);
        },
        getComponents:function(){
            return linb.absObj.pack(_.copy(this._nodes),false);
        },
        setComponents:function(obj){
            var self=this,t;
            _.arr.each(self._nodes,function(o){
                if((t=self[o.alias]) &&t.get(0)==o)
                    delete self[o.alias];
            });
            _.arr.each(self._nodes=obj.get(),function(o){
                self[o.alias]=o.boxing();
            });
            return self;
        },
        destroy:function(threadid){
            var self=this;
            self.threadid=threadid;
            self._fireEvent('onDestroy');
            _.arr.each(self._nodes, function(o){
                if(o.box)
                    o.boxing().destroy();
            });
            self._nodes.length=0;
            _.breakO(self);
        }
    },
    Static:{
        load:function(cls, onEnd, lang, showUI){
            var fun=function(){
                //get app class
                linb.SC(cls,function(path){
                    //if successes
                    if(path){
                        var a=this,f=function(){
                            var o=new a();
                            if(showUI!==false)o.show(onEnd);
                            else _.tryF(onEnd,[o],o);
                        };
                        //get locale info
                        if(lang) linb.setLang(lang, f);
                        else f();
                    }else
                        throw new Error(cls+' doesnt exists!');
                },true);
            };
            if(linb.isDomReady)
                fun();
            else
                linb.main(fun);
        },
        $EventHandlers:{
            beforeCreated:function(com, threadid){},
            onLoadBaseClass:function(com, threadid, key){},
            onIniResource:function(com, threadid){},
            beforeIniComponents:function(com, threadid){},
            afterIniComponents:function(com, threadid){},
            onLoadRequiredClass:function(com, threadid, key){},
            onReady:function(com, threadid){},
            onRender:function(com, threadid){}
        }
    }
});
Class("linb.Cookies", null,{
    Static:{
        set:function(name,value,days,path,domain,isSecure){
	        if(name){
    	        document.cookie = escape(name) + "=" + escape(value) +
    		        (days?";expires="+(new Date((new Date()).getTime()+(24*60*60*1000*days))).toGMTString():"")+
    		        (path?";path="+path:"")+
    		        (domain?";domain="+domain:"")+ 
    		        (isSecure?";secure":"");
    		}
    		return this;
        },
        get:function(name){
        	var i,a,ca = document.cookie.split( "; " );
        	for(i=0;i<ca.length;i++){
        		a=ca[i].split("=");
        		if(a[0]==escape(name))
        		    return a[1]?unescape(a[1]):'';
        	}
        	return null;
        },
        remove:function(name){
        	return this.set(name,"",-1).set(name,"/",-1);
        }
    }
});Class('linb.XML',null,{
    Static:{
        //return xml text (for post data)
        json2xml:function(jsonObj){
           var arr=[],
           _f=function(key,value,arr){
                if(typeof value=="object"){
                    if(_.isArr(value)){
                        if(value.length){
                            for(var i=0,l=value.length; i<l; i++)
                                arr.push(_f(key,value[i],arr));
                        }else
                            arr.push("<"+key+">"+"__[]__"+"</"+key+">");
                    }else{
                        var b;
                        arr.push("<"+key);
                        for(var i in value) {
                            if(i.charAt(0)=="@")
                                arr.push(" "+i.substr(1)+'="'+value[i]+'"');
                            else
                                b=1;
                        }
                        arr.push(b?">":"/>");
                        if(b){
                            for(var i in value) {
                                if(i=="#text")
                                    arr.push(value[i]);
                                else if(i=="#cdata")
                                    arr.push("<![CDATA["+value[i]+"]]>");
                                else if (i.charAt(0)!="@")
                                    arr.push(_f(i,value[i],arr));
                            }
                            arr.push("</"+key+">");
                        }
                    }
                }else
                    arr.push("<"+key+">"+value+"</"+key+">");
           };
           for(var i in jsonObj)
              _f(i,jsonObj[i],arr);
           return '<?xml version="1.0" encoding="UTF-8" ?>'+arr.join('');
        },
        //return json object (for request data)
        xml2json:function(xmlObj){
            if(xmlObj.nodeType==9)
                xmlObj=xmlObj.documentElement;
            var o={},
            M={
                '\b': '\\b',
                '\t': '\\t',
                '\n': '\\n',
                '\f': '\\f',
                '\r': '\\r',
                '"' : '\\"',
                '\\': '\\\\'
            },
            R=/^-?(\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/,
            _map={
                "__[]__":[],
                "null":null,
                'false':false,
                'true':true
             },
            _es=function(str){
                return str.replace(/[\s\S]/g,function(a,b){return (b=M[a])?b:a});
            },
            _clear = function(xml) {
                var n,k;
                xml.normalize();
                for(n=xml.firstChild;n;){
                    k=n;
                    if(n.nodeType==1)_clear(n);
                    n=n.nextSibling;
                    if(k.nodeType==3 && !k.nodeValue.match(/\S/))
                        xml.removeChild(k);
                }
                return xml;
            },
            _xml=function(n){
                if ("innerHTML" in n){
                    n=n.innerHTML;
                    n=n in _map?_map[n]:R.test(n)?parseFloat(n):n;
                }else{
                    var arr=[],t,
                    _in=function(n) {
                        if(n.nodeType==1) {
                            arr.push("<"+n.nodeName);
                            var m=n.attributes;
                            for(var i=0,l=m.length;i<l;i++)
                                arr.push(" "+m[i].nodeName+'="'+(m[i].nodeValue||"")+'"');
                            if (n.firstChild) {
                                arr.push(">");
                                for(m=n.firstChild;m;m=m.nextSibling)
                                    arr.push(_in(m));
                                arr.push("</"+n.nodeName+">");
                            }else arr.push("/>");
                        }else if(n.nodeType==3){
                            n=n.nodeValue;
                            arr.push(n in _map?_map[n]:R.test(n)?parseFloat(n):n);
                        }else if(n.nodeType==4)
                            arr.push("<![CDATA[" + n.nodeValue + "]]>");
                    };
                    for(var m=n.firstChild;m;m=m.nextSibling)
                        _in(m);
                    n=(arr.length==1?arr[0]:arr.join(''))
                }
                return typeof n=='string'?_es(n):n;
            },
            _f=function(xml){
                var o=null,t,tt;
                if(xml.nodeType==1 && ((t=xml.attributes).length||xml.firstChild)){
                    o={};
                    if(t.length){
                        for(var i=0,l=t.length;i<l;i++)
                            o["@"+t[i].nodeName]=(t[i].nodeValue||"")+"";
                    }
                    if(xml.firstChild){
                        var text=0, cdata=0, children=0, n;
                        for(n=xml.firstChild;n;n=n.nextSibling){
                            tt=n.nodeType;
                            if(tt==1)
                                children++;
                            else if(tt==3)
                                text++;
                            else if(tt==4)
                                cdata++;
                        }
                        if(children){
                            if(text<2 && cdata<2) {
                                for(n=xml.firstChild;n;n=n.nextSibling){
                                    if (n.nodeType==3)
                                        o["#text"]=_es(n.nodeValue);
                                    else if(n.nodeType==4)
                                        o["#cdata"]=_es(n.nodeValue);
                                    else if(o[tt=n.nodeName]){
                                        if(o[tt] instanceof Array)
                                            o[tt][o[tt].length]=_f(n);
                                        else
                                            o[tt]=[o[tt],_f(n)];
                                    }else
                                        o[tt]=_f(n);
                                }
                            }else {
                                if(!t.length)
                                    o=_xml(xml);
                                else
                                    o["#text"]= _xml(xml);
                            }
                        }else if(text){
                            if(!t.length) {
                                o=_xml(xml);
                            }else
                                o["#text"]=_xml(xml);
                        }else if(cdata) {
                            if(cdata>1)
                                o=_xml(xml);
                            else
                                for(n=xml.firstChild;n;n=n.nextSibling)
                                    o["#cdata"] = _es(n.nodeValue);
                        }
                    }
                }
                return o;
            };
            o[xmlObj.nodeName]=_f(_clear(xmlObj));
            return o;
        },
        parseXML:function(xmlText){

            var dom=null;
            if(typeof DOMParser=='undefined'){
                try{
                    dom=new ActiveXObject('Microsoft.XMLDOM');
                    dom.async=false;
                    dom.loadXML(xmlText);
                }catch(e){dom=null}
            }else{
                try{
                    var p=new DOMParser();
                    dom=p.parseFromString(xmlText, "text/xml");
                }catch(e){dom=null}finally{p=null}
            }
            return dom;
        }
    }
});/*
profile input:
===========================
    [dragType]: String , "move","copy","deep_copy","shape","icon","blank" and "none", default is "shape"
        "blank": moves a empty proxy when mouse moves
        "move": moves target object directly when mouse moves
        "copy": moves a copy of target object when mouse moves
        "deep_copy": moves a deep copy of target object when mouse moves
        "shape": moves a shape of target object when mouse moves
        "icon": moves a icon that represents target object when mouse moves
        "none": moves mouse only
-------------------------
    [dragDefer] :  Number, when [linb.DragDrop.startDrag] is called, the real drag action will be triggered after [document.onmousemove] runs [dragDefer] times, default is 0;
-------------------------
    [magneticDistance]: Number,
    [xMagneticLines]: Array of Number,
    [yMagneticLines]: Array of Number,
        Magnetic setting:
        yMagneticLines 1                      2                     3
              |                      |                     |       xMagneticLines
          ----+----------------------+---------------------+-------1
              |                      |                     |
              |                      |                     |
              |                      |                     |
              |                      |                     |
          ----+----------------------+---------------------+-------2
              |                      |                     |
              |                      |                     |
              |                      |                     |
          ----+----------------------+---------------------+-------3
              |                      |                     |

        magneticDistance
         +-------------
         |*************
         |*************
         |**
         |**
         |**
-------------------------
    [widthIncrement]: Number,
    [heightIncrement]: Number,
        Increment setting:
                   widthIncrement
               <-------------------->
              |                      |                     |
          ----+----------------------+---------------------+-------
              |                      |                     |
heightIncrement|                      |                     |
              |                      |                     |
              |                      |                     |
          ----+----------------------+---------------------+-------
              |                      |                     |
              |                      |                     |
              |                      |                     |
              |                      |                     |
          ----+----------------------+---------------------+-------
              |                      |                     |
              |                      |                     |
-------------------------
    [horizontalOnly]: Number,
    [verticalOnly]: Number,
    horizontalOnly
    ------------------------------------------
                ****************
                ****************
                ****************
                ****************
                ****************
                ****************
    ------------------------------------------
    verticalOnly
               |                |
               |                |
               |****************|
               |****************|
               |****************|
               |****************|
               |****************|
               |****************|
               |                |
               |                |
-------------------------
    [maxBottomOffset]: Number,
    [maxLeftOffset]: Number,
    [maxRightOffset]: Number,
    [maxTopOffset]: Number,
        you can set the limited offset region
        +----------------------------------------------+
        |              |                               |
        |              |maxTopOffset                   |
        |<------------>****************<-------------->|
        |maxLeftOffset**************** maxRightOffset  |
        |              ****************                |
        |              ****************                |
        |              ****************                |
        |              ****************                |
        |              |maxBottomOffset                |
        |              |                               |
        +----------------------------------------------+
-------------------------
    [targetReposition]: <bool>,

    //ini pos and size
    [targetLeft]: Number
    [targetTop]: Number
    [targetWidth]: Number
    [targetHeight]: Number
    [targetCSS]: <object>
        You can set position and size when drag start:
                      targetLeft
                      |
                      |
        targetTop  ---**************** |
                      **************** |
                      **************** |
                      **************** |targetHeight
                      **************** |
                      **************** |
                     |<--targetWidth ->+
-------------------------
    //properties
    [dragCursor]: <string>
-------------------------
    //for drag data
    [dragKey]
    [dragData]

profile output: readonly
===========================
linb.DragDrop.getProfile():
    x  :current X value of mouse;
    y  :current Y value of mouse;
    ox: mouse original X when drag start;
    oy: mouse original Y when drag start;
    curPos:{left:xx,top:xx}: current css pos of the dragging node;
    offset : {x:,y}: offset from now to origin
    restrictedLeft : Number
    restrictedRight : Number
    restrictedTop : Number
    restrictedBottom : Number
    isWorking: Bool.
    proxyNode: linb.Dom object,
    dropElement: String, DOM element id.
*/
Class('linb.DragDrop',null,{
    Static:{
        _eh:"_dd",
        _id:"linb.dd:proxy:",
        _idi:"linb.dd:td:",
        _type:{blank:1,move:1,shape:1,deep_copy:1,copy:1,icon:1,none:1},
        _Icons:{none:'0 0', move:'0 -16px', link:'0 -32px',add:'0 -48px'},
        _profile:{},

        //get left for cssPos
        _left:function(value){
            with(this._profile){
                if(magneticDistance>0 && xMagneticLines.length){
                    var l=xMagneticLines.length;
                    while(l--)
                        if(Math.abs(value - xMagneticLines[l])<=magneticDistance)
                            return xMagneticLines[l];
                }
                if(widthIncrement>1)
                   return Math.floor(value/widthIncrement)*widthIncrement;
                return value;
            }
        },
        //get top for cssPos
        _top:function(value){
            with(this._profile){
                if(magneticDistance>0 && yMagneticLines.length){
                    var l=yMagneticLines.length;
                    while(l--)
                        if(Math.abs(value - yMagneticLines[l])<=magneticDistance)
                            return yMagneticLines[l];
                }
                if(heightIncrement>1)
                    return Math.floor(value/heightIncrement)*heightIncrement;
                return value;
            }
        },

        _ini:function(o){
            var d=this,p=d._profile,_t=linb.win;

            d._box = { width :_t.width()+_t.scrollLeft(),  height :_t.height()+_t.scrollTop()};

            p.ox = p.x;
            p.oy = p.y;

            if(d._proxy = o){
                d._proxystyle=o.get(0).style;

                //ini cssPos here
                d._profile.curPos = d._cssPos= d._proxy.cssPos();

                d._cssPos_x = p.x - d._cssPos.left;
                d._cssPos_y = p.y - d._cssPos.top;

                p.restrictedLeft = p.x - (p.maxLeftOffset||0);
                p.restrictedRight =  p.x + (p.maxRightOffset||0);
                p.restrictedTop = p.y - (p.maxTopOffset||0);
                p.restrictedBottom = p.y + (p.maxBottomOffset||0);

                //here
                d._proxyLeft = d._pre.left = d._cssPos.left;
                d._proxyTop = d._pre.top = d._cssPos.top;

                if("move" !== p.dragType)
                    d._proxy.css('zIndex',linb.Dom.TOP_ZINDEX*10);
            }

        },
        _reset:function(){
            var d=this,NULL=null,FALSE=false;
            //reset
            _.tryF(d.$reset);
            d.setDropFace();
            d._resetProxy();

            d.$proxySize=50;
            //event
            d.$mousemove=d.$mouseup=d.$onselectstart=d.$ondragstart='*';

            //reset private vars
            d._cursor='';
            d._pre={};
            d._proxyLeft=d._proxyTop=d._cssPos_x=d._cssPos_y=0;
            d._stop=FALSE;
            if(d._onDrag && d._onDrag.tasks){
                d._onDrag.tasks.length=0;
                delete d._onDrag.tasks;
            }
            if(d._onDragover && d._onDragover.tasks){
                d._onDragover.tasks.length=0;
                delete d._onDragover.tasks;
            }
            d._cssPos=d._box=d._dropElement=d._source=d._proxy=d._proxystyle=d._onDrag=d._onDragover=NULL;

            //reset profile
            d._profile={
                dragType:'shape',
                dragCursor:'move',
                targetReposition:true,

                dragIcon:linb.ini.path+'ondrag.gif',
                magneticDistance:0,
                xMagneticLines:[],
                yMagneticLines:[],
                widthIncrement:0,
                heightIncrement:0,
                dragDefer:0,

                horizontalOnly:FALSE,
                verticalOnly:FALSE,
                maxBottomOffset:NULL,
                maxLeftOffset:NULL,
                maxRightOffset:NULL,
                maxTopOffset:NULL,

                targetNode:NULL,
                targetCSS:NULL,
                dragKey:NULL,
                dragData:NULL,
                targetLeft:NULL,
                targetTop:NULL,
                targetWidth:NULL,
                targetHeight:NULL,
                targetOffsetParent:NULL,

                shadowFrom:NULL,

                //Cant input the following items:
                proxyNode:NULL,
                x:0,
                y:0,
                ox:0,
                oy:0,
                curPos:{},
                offset:{},
                isWorking:FALSE,
                restrictedLeft:NULL,
                restrictedRight:NULL,
                restrictedTop:NULL,
                restrictedBottom:NULL,
                dropElement:NULL
            };
            return d;
        },
        abort:function(){
            this._stop=true;
        },
        _end:function(){
            var d=this,doc=document;

            if(d._proxy) d._unpack();

            //must here
            //if bak, restore
            if(d.$onselectstart!='*')doc.body.onselectstart=d.$onselectstart;
            if(d.$ondragstart!='*')doc.ondragstart=d.$ondragstart;
            //if bak, restore
            if(d.$mousemove!='*')doc.onmousemove=d.$mousemove;
            if(d.$mouseup!='*')doc.onmouseup=d.$mouseup;

            return  d;
        },
        startDrag:function(e, targetNode, profile, dragKey, dragData){
            var d=this,t;
            if(d._profile.isWorking)return false;
            //clear
            d._end()._reset();
            d._profile.isWorking=true;

            profile=_.isHash(profile)?profile:{};
            e = e || window.event;
            // not left button
            if(linb.Event.getBtn(e) !== 'left')
               return true;

            d._source = profile.targetNode = linb(targetNode);
            d._cursor = d._source.css('cursor');

            if((t=profile.targetNode.get(0)) && !t.id){
                t.id=linb.Dom._pickDomId();
                t=null;
            }

            //must set here
            d._defer = profile.dragDefer = _.isNumb(profile.dragDefer) ? profile.dragDefer : 0;
            if(true===profile.dragCursor)profile.dragCursor=d._cursor;
            if(typeof profile.dragIcon == 'string') profile.dragType="icon";

            var doc=document, _pos = linb.Event.getPos(e);
            profile.x = _pos.left;
            profile.y = _pos.top;

            profile.dragKey= dragKey || profile.dragKey || null;
            profile.dragData= dragData  || profile.dragData|| null;

            var fromN=linb.Event.getSrc(e);

            d._start=function(e){
//ie6: mousemove - mousedown =>78 ms
//delay is related to window size, weird
            //                  try{
                var p=d._profile;
                //set profile
                _.merge(p, profile, "with");

                //call event, you can call abort(set _stoop)
                d._source.beforeDragbegin();

                if(d._stop){d._end()._reset();return false}

                //set linb.Event._preDropable at the begining of drag, for a dd from a child in a dropable node
                if(linb.Event && (t=d._source.get(0))){
                    linb.Event._preDropable= t.id;
                    t=null;
                }

                //set default icon
                if(p.dragType=='icon')p.targetReposition=false;

                //ini
                d._ini(p.dragType=='none'?null:d._pack(_pos, p.targetNode));
                // on scrollbar
                if(profile.x >= d._box.width  || profile.y >= d._box.height ){d._end()._reset();return true}

                d._source.onDragbegin();

                //set back first
                if(p.dragDefer<1){
                    d.$mousemove = doc.onmousemove;
                    d.$mouseup = doc.onmouseup;
                }
                //avoid setcapture
                if(linb.browser.ie)
                    setTimeout(function(){fromN.releaseCapture()});

                //back up
                doc.onmousemove = d.$onDrag;
                doc.onmouseup = d.$onDrop;
                //for events
                d._source.afterDragbegin();
                //for delay, call ondrag now
                if(p.dragDefer>0)d.$onDrag.call(d, e);
            //                  }catch(e){d._end()._reset();}
            };
            if(linb.browser.ie){
                d.$ondragstart=doc.ondragstart;
                d.$onselectstart=doc.body.onselectstart;
                doc.ondragstart = doc.body.onselectstart = null;
                if(doc.selection)_.tryF(doc.selection.empty);
            }

            //avoid select
            linb.Event.stopBubble(e);

            //fire document onmousedown event
            if(profile.targetNode.get(0)!==doc)
                linb(doc).onMousedown(true, linb.Event.getEventPara(e, _pos));

            if(profile.dragDefer<1){
                _.tryF(d._start,[e],d);
                return false;
            }else{
                //for mouseup before drag
                d.$mouseup = doc.onmouseup;
                doc.onmouseup = function(e){
                    linb.DragDrop._end()._reset();
                    return _.tryF(document.onmouseup,[e],null,true);
                };
                //for mousemove before drag
                d.$mousemove = doc.onmousemove;
                var pbak={};
                doc.onmousemove = function(e){
                    var p=linb.Event.getPos(e);
                    if(p.left===pbak.left&&p.top===pbak.top)return;
                    pbak=p;
                    if(--d._defer<=0)linb.DragDrop._start(e);
                    return false;
                };
            }
//ie6: mousemove - mousedown =>78 ms
        },
        $onDrag:function(e){
            var d=linb.DragDrop,p=d._profile;

           //try{
                e = e || window.event;
                //set _stop or (in IE, show alert)
                if(!p.isWorking || d._stop){
                //if(!p.isWorking || d._stop || (linb.browser.ie && (!e.button) )){
                    d.$onDrop(e);
                    return true;
                }

                var _pos=linb.Event.getPos(e);
                p.x=_pos.left;
                p.y=_pos.top;

                if(!p.isWorking)return false;

                if(d._proxy){
                    if(!p.verticalOnly){
                        d._proxyLeft=Math.floor(d._left(
                            ((p.maxLeftOffset!==null && p.x<=p.restrictedLeft)?p.restrictedLeft:
                             (p.maxRightOffset!==null && p.x>=p.restrictedRight)?p.restrictedRight : p.x)
                            - d._cssPos_x)
                        );
                        if(d._proxyLeft-d._pre.left)
                            d._proxystyle.left=d._proxyLeft+'px';
                        d._pre.left=d._proxyLeft;
                        p.curPos.left = d._proxyLeft + d.$proxySize;
                    }
                    if(!p.horizontalOnly){
                        d._proxyTop=Math.floor(d._top(
                            ((p.maxTopOffset!==null && p.y<=p.restrictedTop) ? p.restrictedTop :
                             (p.maxBottomOffset!==null && p.y>=p.restrictedBottom) ? p.restrictedBottom : p.y)
                            - d._cssPos_y)
                        );
                        if(d._proxyTop-d._pre.top)
                            d._proxystyle.top=d._proxyTop+'px';
                        d._pre.top=d._proxyTop;
                        p.curPos.top = d._proxyTop + d.$proxySize;
                    }
                }else{
                    p.curPos.left = p.x;
                    p.curPos.top = p.y;
                    //style='none', no dd.current dd._pre provided
                    //fireEvent
                    //d._source.onDrag(true); //shortcut for mousemove
                }
                if(d._onDrag!=1){
                    if(d._onDrag)d._onDrag(e,d._source._get(0));
                    else{
                        //ensure to run once only
                        d._onDrag=1;
                        //if any ondrag event exists, this function will set _onDrag
                        d._source.onDrag(true,linb.Event.getEventPara(e, _pos));
                    }
                }
            //}catch(e){linb.DragDrop._end()._reset();}finally{
               return false;
            //}
        },
        $onDrop:function(e){
            var d=linb.DragDrop,p=d._profile,evt=linb.Event;
//                try{
                e = e || window.event;

                // opera 9 down with
                // if(!isWorking){evt.stopBubble(e);return false;}
                d._end();
                if(p.isWorking){

                    //here, release drop face first
                    //users maybe use html() function in onDrop function
                    d.setDropFace();

                    var r = d._source.onDragstop(true,evt.getEventPara(e));
                    if(d._dropElement)
                        linb.use(d._dropElement).onDrop(true,evt.getEventPara(e));
                }
//                }catch(a){}finally{
                d._reset();
                evt.stopBubble(e);
                _.tryF(document.onmouseup,[e]);
                return !!r;
//                }
        },
        setDropElement:function(id){
            this._profile.dropElement=this._dropElement=id;
            return this;
        },
        getProfile:function(){
            var d=this,p=d._profile;
            p.offset=d._proxy
            ?
            { x : d._proxyLeft-p.ox+d._cssPos_x,  y : d._proxyTop-p.oy+d._cssPos_y}
            :
            { x : p.x-p.ox,  y : p.y-p.oy}
            ;
            return p;
        },
        setDropFace:function(target, dragIcon){
            var d=this,
                s1='<div style="position:absolute;z-index:'+linb.Dom.TOP_ZINDEX+';font-size:0;line-height:0;border-',
                s2=":dashed 1px #ff6600;",
                region=d._Region,rh=d._rh,
                bg='backgroundColor';
            if(region && region.parent())
                region.remove(false);
            if(d._R){
                d._R.css(bg, d._RB);
                delete d._R;
                delete d._RB;
            }

            if(target){
                //never create, or be destroyed region 
                if(!region || !region.get(0)){
                    region=d._Region=linb.create(s1+'top'+s2+'left:0;top:0;width:100%;height:0;"></div>'+s1+'right'+s2+'right:0;top:0;height:100%;width:0;"></div>'+s1+'bottom'+s2+'bottom:0;left:0;width:100%;height:0;"></div>'+s1+'left:solid 2px #ff6600;width:0;left:0;top:0;height:100%;"></div>');
                    rh=d._rh=linb([region.get(1),region.get(3)]);
                }target=linb(target);
                if(linb.browser.ie6)rh.height('100%');
                if(target.css('display')=='block'){
                    target.append(region);
                    if(linb.browser.ie6 && !rh.get(0).offsetHeight)
                        rh.height(target.get(0).offsetHeight);
                }else{
                    d._RB = target.get(0).style[bg];
                    d._R=target;
                    target.css(bg, '#FA8072');
                }
                d.setDragIcon(dragIcon||'move');
            }else
                d.setDragIcon('none');
            return d;
        },
        setDragIcon:function(key){
            //avoid other dropable targetNode's setDropFace disturbing.
            _.resetRun('setDropFace', null);
            var d=this,p=d._profile,i=p.proxyNode,ic=d._Icons;
            if(i && p.dragType=='icon')
                i.first(4).css(typeof key=='object'?key:{backgroundPosition: (ic[key]||key)});
            return d;
        },
        _setProxy:function(child, pos){
            var t,temp,d=this,p=d._profile,dom=linb.Dom;
            if(!dom.byId(d._id))
                linb('body').prepend(
                    //&nbsp; for IE6
                    linb.create('<div id="' + d._id + '" style="left:0;top:0;border:0;font-size:0;line-height:0;padding:'+d.$proxySize+'px; position: absolute;"><div style="font-size:0;line-height:0;" id="' +d._idi+ '">'+(linb.browser.ie6?'&nbsp;':'')+'</div></div>')
                );
            t=linb(d._id);
            if(p.dragKey){
                d.$proxySize=0;
                t.css('padding',0);
            }else{
                pos.left -=  d.$proxySize;
                pos.top -= d.$proxySize;
                if(!p.targetOffsetParent)
                    dom.setCover(true);
            }
            if(temp=p.targetOffsetParent)
                linb(temp).append(t);

            if(child){
                linb(d._idi).empty(false).append(child);
                p.proxyNode = child;
            }else
                p.proxyNode = linb(d._idi);
            t.css({display:'',zIndex:dom.TOP_ZINDEX*10,cursor:p.dragCursor}).offset(pos, temp);

            return t;
        },
        _resetProxy:function(){
            var d=this, p=d._profile,
                dom=linb.Dom,
                id1=d._id,
                id2=d._idi;
            if(dom.byId(id1)){
                var t,k,o=linb(id2),t=linb(id1);
                //&nbsp; for IE6
                if(linb.browser.ie6)
                    o.html('&nbsp;',false);
                else o.empty(false);
                o.attr('style','font-size:0;line-height:0;');

                linb('body').prepend(
                    t
                    .css({
                        zIndex:0,
                        cursor:'',
                        display:'none',
                        padding:d.$proxySize+'px'
                    })
                );
                p.proxyNode=d._proxystyle=null;
                dom.setCover(false);
            }
        },
        _pack:function(mousePos,targetNode){
            var target, pos={}, size={}, d=this, p=d._profile, t;
            // get abs pos (border corner)
            if(p.targetLeft===null || null===p.targetTop)
                t=targetNode.offset(null, p.targetOffsetParent);
            pos.left = null!==p.targetLeft?p.targetLeft: t.left;
            pos.top = null!==p.targetTop?p.targetTop: t.top;

            switch(p.dragType){
                case 'deep_copy':
                case 'copy':
                   var t;
                    size.width =  _.isNumb(p.targetWidth)? p.targetWidth:(targetNode.cssSize().width||0);
                    size.height = _.isNumb(p.targetHeight)?p.targetHeight:(targetNode.cssSize().height||0);
                    var n=targetNode.clone(p.dragType=='deep_copy')
                        .css({position:'relative',cursor:p.dragCursor,margin:0,'cssFloat':'none'})
                        .cssSize(size)
                        .id('',true)
                        .css('opacity',0.8);

                    n.query('*').id('',true);
                    if(p.targetCSS)
                        n.css(p.targetCSS);
                    n.cssPos({margin:'0',left:'0',top:'0'}).query().id('',true);
                    target = d._setProxy(n,pos);
                    break;
                case 'shape':
                    // get size
                    size.width = null!==p.targetWidth?p.targetWidth:targetNode.offsetWidth();
                    size.height = null!==p.targetHeight?p.targetHeight:targetNode.offsetHeight();
                    size.width-=2;size.height-=2;
                    target = d._setProxy(
                        linb.create('div').css({border:'dashed 1px',fontSize:'0',lineHeight:'0'}).cssSize(size)
                        ,pos);
                    break;
                case 'blank':
                    target = d._setProxy(null,pos);
                    break;
                case 'icon':
                    pos.left=_.isNumb(p.targetLeft)?p.targetLeft:(mousePos.left - linb.win.scrollLeft() + 16);
                    pos.top=_.isNumb(p.targetTop)?p.targetTop:(mousePos.top - linb.win.scrollTop() + 16);
                    t='<table border="0"><tr><td valign="top"><span style="background:url('+p.dragIcon+') no-repeat left top;width:'+(_.isNumb(p.targetWidth)?p.targetWidth:16)+'px;height:'+(_.isNumb(p.targetHeight)?p.targetHeight:16)+'px;" ></span></td><td id="linb:dd:shadow" '+(p.shadowFrom?'style="border:solid 1px #e5e5e5;background:#fff;font-size:12px;line-height:14px;"':'')+'>'+(p.shadowFrom?

                    linb(p.shadowFrom).clone(true)
                    .css({left:'auto',top:'auto', position:'relative'})
                    .outerHTML().replace(/\s*id\=[^\s\>]*/g,''):'')

                    +'</td></tr></table>';
                    target = d._setProxy(linb.create(t).css('opacity',0.8), pos);
                    break;
                case 'move':
                    d.$proxySize=0;
                    target=targetNode;
                    if(target.css('position') != 'absolute')
                        target.css('position','absolute').offset(pos);
                    target.css('cursor',p.dragCursor);
            }

            return target;
        },
        _unpack:function(){
            var d=this, p=d._profile, t,f;
            if(p.targetReposition && ("move" != p.dragType)){
                if((t=linb(d._source)))
                    if(!t.isEmpty()){
                        if(t.css('position')!= 'absolute')
                            t.css('position','absolute').cssPos(t.offset(null,t.get(0).offsetParent ));

                        //for ie bug
                        if(linb.browser.ie)
                            t.cssRegion({right:'auto',bottom:'auto'});
                        t.offset(p.curPos, p.targetOffsetParent||document.body);
                    }
            }
            if("move" == p.dragType)
                d._source.css('cursor',d._cursor);
        },
        _unRegister:function(node, key){
            var eh=this._eh;
            linb([node])
                .$removeEvent('beforeMouseover', eh)
                .$removeEvent('beforeMouseout', eh)
                .$removeEvent('beforeMousemove', eh);

            linb.setNodeData(node.$linbid, ['_dropKeys',key]);
        },
        _register:function(node, key){
            var eh=this._eh;
            linb(node)
                .beforeMouseover(function(p,e,i){
                    var t=linb.DragDrop, p=t._profile;
                    if(p.dragKey && linb.getNodeData(i,['_dropKeys', p.dragKey])){
                        t.setDropElement(i);
                        t._onDragover=null;
                        linb.use(i).onDragenter(true);
                        if(t._dropElement)
                            _.resetRun('setDropFace', t.setDropFace, 0, [i], t);
                    }
                }, eh)
                .beforeMouseout(function(p,e,i){
                    var t=linb.DragDrop,p=t._profile;
                     if(p.dragKey && linb.getNodeData(i,['_dropKeys', p.dragKey])){
                        linb.use(i).onDragleave(true);
                        t.setDropElement(t._onDragover=null);
                        _.resetRun('setDropFace', t.setDropFace, 0, [null], t);
                    }
                }, eh)
                .beforeMousemove(function(a,e,i){
                    var t=linb.DragDrop, h=t._onDragover, p=t._profile;
                    //no dragover event
                    if(h==1)return;
                    if(t._dropElement==i && p.dragKey && linb.getNodeData(i,['_dropKeys', p.dragKey])){
                        if(h)h(e,i);
                        else{
                            //ensure to run once only
                            t._onDragover=1;
                            //if any dragover event exists, this function will set _onDragover
                            linb.use(i).onDragover(true,linb.Event.getEventPara(e));
                        }
                    }
                }, eh);
            linb.setNodeData(node.$linbid, ['_dropKeys', key], true);
        }
    },
    After:function(){
        this._reset();
        //add dom dd functions
        _.each({
            startDrag:function(e, profile, dragKey, dragData){
                linb.DragDrop.startDrag(e, this.get(0), profile, dragKey||'', dragData||null);
                return this;
            },
            dragable:function(flag, profile, dragKey, dragData){
                var self=this, dd=linb.DragDrop;
                if(flag===undefined)
                    flag=true;
                else if(typeof flag=='object'){
                    profile=flag;
                    flag=true;
                }
                if(!!flag)
                    self.$addEvent('onMousedown',function(p,e,src){
                        if(linb.getId(linb.Event.getSrc(e))!=src)return true;
                        linb.use(src).startDrag(e, profile, dragKey, dragData)
                    }, dd._eh, -1);
                else
                    self.$removeEvent('onMousedown', dd._eh);

                return self;
            },
            dropable:function(flag, key){
                if(flag===undefined)flag=true;
                key = key || 'default';
                var d=linb.DragDrop;
                return this.each(function(o){
                    if(!!flag)
                        d._register(o, key);
                    else
                        d._unRegister(o, key);
                });
            }
        },function(o,i){
            linb.Dom.plugIn(i,o);
        });
    }
});//singleton

Class("linb.Tips", null,{
    Constructor:function(){return null},
    Initialize:function(){
        var dd=linb.DragDrop,
            tips=this;
        if(dd)
            dd.$reset=function(){
                tips._pos={left:dd._profile.x,top:dd._profile.y}
            };

        //for: span(display:-moz-inline-box) cant wrap in firefox
        linb.CSS.addStyleSheet(
            ".linb-tips{font-size:0;line-height:0;position:absolute;overflow:visible;} "+
            ".linb-tips-i{font-size:12px;overflow:hidden;}"+
            ".linb-tips-i span{display:inline;}"
        , this.KEY);

        linb.doc
        .afterMousedown(function(){
            tips._cancel();
        },'$Tips',-1)
        .afterMousemove(function(obj, e){
            if(dd.isWorking)return;
            var event=linb.Event,
                p,n;

            //if ready to show in settimeout(resetRun)
            if((p=_.resetRun.$cache) && p['$Tips3'])
                tips._pos=event.getPos(e);

            //it's first show
            if(tips._from){
                _.resetRun('$Tips3', null);
                tips._showF();
            //after show, before hide
            }else if(tips._showed && tips.MOVABLE){
                p=event.getPos(e);
                n=tips._Node.style;
                n.left = (parseInt(n.left)||0) + (p.left-tips._pos.left) +'px';
                n.top = (parseInt(n.top)||0) + (p.top-tips._pos.top) +'px';
                tips._pos=p;
                n=null;
            }
        },'$Tips',-1)
        .afterMouseover(function(obj, e){
            var event=linb.Event,
                rt=event.$FALSE,
                node=event.getSrc(e),
                id,
                _from,
                tempid,evid,
                index=0,
                pass
            ;
            if(!node)
                return rt;
            try{
                //for inner renderer
                while((!node.id || node.id==linb.$langId) && node.parentNode!==document && index++<10)
                    node=node.parentNode;
                if(!(id=node.id)){
                    node=null;
                    return rt;
                }
            }catch(e){}

            //check id
            if((_from=event._getProfile(id)) && _from.box && _from.KEY=='linb.UIProfile'){
                //if onShowTips exists, use custom tips id region, or use item region
                tempid=_from.onShowTips?id:id.replace(tips._reg,':');
                if(tips._markId && tempid==tips._markId)
                    return rt;

                //set mark id
                tips._markId = tempid;
                tips._pos=event.getPos(e);
                
                if(tips._showed){
                    tips._from=_from;
                    tips._enode=id;
                    tips._showF();
                }else
                    _.resetRun('$Tips', function(){
                        tips._from=_from;
                        tips._enode=id;
                        _.resetRun('$Tips3', function(){
                            if(tips._from)
                                tips._showF();
                        },100);
                    }, tips.DELAYTIME);
            }else
                tips._cancel();

            node=null;
            return rt;
        },'$Tips',-1)
        .afterMouseout(function(obj, e){
            if(tips._markId){
                var event=linb.Event,
                    id,
                    tempid,
                    evid,
                    _from=tips._from,
                    clear,
                    index=0,
                    node = e.toElement||e.relatedTarget;

                if(!node)
                    clear=1;
                else{
                    //for firefox wearing anynomous div in input/textarea
                    try{
                        //for inner renderer
                        while((!node.id || node.id==linb.$langId) && node.parentNode!==document && index++<10)
                            node=node.parentNode;
                        if(!(id=node.id)){
                            node=null;
                            clear=1;
                        }
                    }catch(e){clear=1}
                }
                if(clear)
                    tips._cancel();
                else
                    tempid=(_from && _from.onShowTips)?id:id.replace(tips._reg,':');

                node=null;
                return event.$FALSE;
            }
        },'$Tips',-1);

        this._Types = {
            'default' : new function(){
                this._r=/(\$)([\w\.]+)/g;
                this.show=function(item, pos, key){
                    //if trigger onmouseover before onmousemove, pos will be undefined
                    if(!pos)return;

                    var self=this,node,_ruler,s,w,h;
                    if(!(node=self.node) || !node.get(0)){
                        node = self.node = linb.create('<div class="linb-tips"><div class="linb-tips-i"></div></div>');
                        _ruler = self._ruler = linb.create('<div class="linb-tips" style="position:absolute;visibility:hidden;left:-10000px;"><div class="linb-tips-i" style="position:relative;"></div></div>');
                        self.n = node.first();
                        self._n = _ruler.first();
                        if(typeof node.addShadow == 'function'){
                            node.addShadow();
                            _ruler.addShadow();
                        }
                        linb('body').append(_ruler);
                    }
                    _ruler = self._ruler;
                    //ensure zindex is the top
                    if(document.body.lastChild!=node.get(0))
                        linb('body').append(node);

                    s = typeof item=='object'? item[key||linb.Tips.TIPSKEY] :item ;
                    if(typeof s=='function')
                        s=s();
                    if(s+=""){
                        var html=/^\s*\</.test(s);
                        //get string
                        s=s.replace(self._r, function(a,b,c){
                            return linb.getRes(c);
                        });
                        linb.Tips._curTips=s;
                        if(!item.transTips || !html)
                            s='<div style="border:solid gray 1px;background-color:#FFF8DC;padding:1px 2px 2px 2px;">'+s+'</div>';
                        //set to this one
                        self._n.get(0).innerHTML=s;

                        //get width
                        w=_ruler.get(0).offsetWidth;
                        if(!html)
                            w=Math.min(tips.MAXWIDTH, w);

                        //set content, AND dimension
                        var style=node.get(0).style, t1=self.n.get(0),styleI=t1.style;
                        //hide first
                        style.visibility='hidden';
                        //set content
                        t1.innerHTML=s;
                        //set dimension
                        if(linb.browser.ie){
                            style.width=styleI.width=w+(w%2)+'px';
                            h=t1.offsetHeight;
                            style.height=h-(h%2)+'px';
                        }else
                            styleI.width=w+'px';

                        //pop(visible too)
                        node.popToTop({left:pos.left,top:pos.top,region:{
                            left:pos.left,
                            top:pos.top-12,
                            width:24,height:32
                        }},1);
                        style=styleI=t1=null;
                    }else
                        node.css('zIndex',0).hide();
                };
                this.hide = function(){
                    this.node.css('zIndex',0).hide();
                };
            }/*,
            'animate' : new function(){
                this.threadid='$tips:1$';
                this.show=function(item, pos){
                    if(!this.node){
                        this.node = linb.create('<div style="position:absolute;border:solid gray 1px;background-color:#FFFACD;font-size:12px;padding:3px;overflow:hidden;"></div>');
                        linb('body').append(this.node);
                    }
                    pos.left+=12;
                    pos.top+=12;
                    var s=item.tips;
                    s = s.charAt(0)=='$'?linb.wrapRes(s.slice(1)):s;
                    this.node.html(s).css('zIndex',linb.Dom.TOP_ZINDEX).cssPos(pos);
                    var w=this.node.width(),h=this.node.height();
                    this.node.cssSize({ width :0, height :0}).css('display','block').animate({width:[0,w],height:[0,h]},0,0,240,8,'expoOut',this.threadid).start();
                };
                this.hide = function(){
                    linb.Thread.abort(this.threadid);
                    this.node.height('auto').width('auto').css('display','none').css('zIndex',0);
                };
            }*/
        };
    },
    Static:{
        _reg:/-[\w]+:/,
        TIPSKEY:'tips',
        MAXWIDTH:300,
        MOVABLE:true,
        DELAYTIME:200,
        AUTOHIDETIME:5000,

        _showF:function(){
            var self=this,
                _from=self._from,
                node=linb.Dom.byId(self._enode),
                pos=self._pos,
                id,
                o,t,b=false;

            self._from=self._enode=null;

            if(!node || !_from || !pos || !(o=_from.box))return;

            //keep older
            self._pos=pos;
            //1.CF.showTips
            b=((t=_from.CF) && (t=t.showTips) && t(_from, node, pos));
            //2._showTips / onShowTips
            //check if showTips works
            if(!b)b=(o._showTips && o._showTips(_from, node, pos));

            //default tips var(profile.tips > profile.properties.tips)
            if(!b && ((t=_from) && t.tips)||(t && (t=t.properties) && (t.tips))){
                self.show(pos, t);
                b=true;
            }

            //no work hide it
            if(!b)self.hide();
            else {
                if(!self.MOVABLE)
                    _.resetRun('$Tips2', self.hide,self.AUTOHIDETIME,null,self);
            }
            node=pos=_from=null;
        },
        getTips:function(){
            return this._curTips;
        },
        show:function(pos, item, key){
            var self=this,t;
            //for mousemove
            self._pos=pos;
            //same item, return
            if(self._item === item)return;

            //hide first
            //if(self._tpl)self._tpl.hide();

            //base check
            if(typeof item =='string' || (item && (item[key||linb.Tips.TIPSKEY]))){
                //get template
                t = self._tpl = self._Types[item.tipsTemplate] || self._Types['default'];
                t.show(item,pos,key);
                self._Node=t.node.get(0);
                self._item=item;
                self._showed = true;
            }else
                self._cancel();
        },
        hide:function(){
            var self=this;
            if(self._showed){
                if(self._tpl)self._tpl.hide();
                self._clear();
            }
        },
        _cancel:function(){
            var self=this;
            if(self._markId){
                if(self._showed)
                    self.hide();
                else{
                    _.resetRun('$Tips', null);
                    _.resetRun('$Tips3', null);
                    self._clear();
                }
            }            
        },
        _clear:function(){
            var self=this;
            self._Node=self._curTips=self._markId = self._from=self._tpl = self._item = self._showed = null;
        }
    }
});Class("linb.History",null,{
    Static:{
        _fid:'linb:history',
        /* set callback function
        callback: function(hashStr<"string after #">)
        */
    	setCallback: function(callback){
    	    var self=this;
    		self._callback = callback;
    		var hash = location.hash;
            if(callback){
        		self._lastFI = hash;
        		if(linb.browser.ie) {
        			if(self._lastFI=='')self._lastFI = '#';
    
                    var n=document.createElement("div");
                    n.style.display = "none";
                    document.body.appendChild(n);
        			n.innerHTML = '<iframe id="'+this._fid+'" style="display: none;"></iframe>';
        			var ihistory = document.getElementById(this._fid), iframe = ihistory.contentWindow.document;
        			iframe.open();
        			iframe.close();
        			iframe.location.hash = hash;
        			n=null;
        		}else if(linb.browser.kde) {
        			// etablish back/forward stacks
        			self.backStack = [];
        			self.backStack.length = history.length;
        			self.forwardStack = [];
        		}
        		self._callback(hash.replace(/^#/, ''));
                clearInterval(self._itimer);
                self._itimer = setInterval(self._timer,100);
            }else
                clearInterval(self._itimer);

    		return self;
    	},
        //cross case=>
	    //  1: goto another url, and back
	    //  2: back to another url, and forward
        //check location.hash change periodically
    	_timer: function(){
    	    var self=linb.History;
    	    if(typeof self._callback!='function'){
    	        clearInterval(self._itimer);
    	        return;
    	    }

    		if(linb.browser.ie) {
    		    var ihistory = document.getElementById(self._fid), iframe = ihistory.contentWindow.document;
    			hash = iframe.location.hash;
    			if(hash != self._lastFI) {
    				self._lastFI = location.hash = hash;
    				self._callback(hash.replace(/^#/, ''));
    			}
    		}else if(linb.browser.kde) {
    			if(!self.dontCheck) {
    			    var backStack=self.backStack,
    			        forwardStack=self.forwardStack,
    				    historyDelta = history.length - backStack.length;
    				//for back button or forward button
    				if(historyDelta) {
                        //back button case
    					if(historyDelta<0)
    						for (var i = 0; i < Math.abs(historyDelta); i++) forwardStack.unshift(backStack.pop());
    					//forward button case
    					else
    						for (var i = 0; i < historyDelta; i++) backStack.push(forwardStack.shift())
    					
    					var cachedHash = backStack[backStack.length-1];
    					if (cachedHash !== undefined) {
    						self._lastFI = location.hash;
    						self._callback(cachedHash);
    					}else{
    					    //cross case=>
    					}
    				}else if(backStack[backStack.length-1]===undefined){
    				    if(self._lastFI != location.hash){
    				        //cross case=>
        				    self._lastFI = location.hash;
        				    self._callback(location.hash);
        				}
    				}
    			}
    		}else{
    			// otherwise, check for location.hash
    			var hash = location.hash;
    			if(hash != self._lastFI) {
    				self._lastFI = hash;
    				self._callback(hash.replace(/^#/, ''));
    			}
    		}
    	},
    	getFI:function(){
    	    return this._lastFI;
    	},
        /*change Fragement Identifier(string after '#')
        */
    	setFI:function(fi,triggerCallback){
    	    var self=this;
    	    if(!self._callback)return;
    	    if(fi)fi=(''+fi).replace(/^#+/,'');
            if(self._lastFI == '#' + fi)return false;

    		if(linb.browser.ie) {
    			var ihistory = document.getElementById(self._fid), iframe = ihistory.contentWindow.document;
                iframe.open();
    			iframe.close();
    			iframe.location.hash = location.hash = self._lastFI = '#' + fi;
    		}else if(linb.browser.kde) {
    			self.dontCheck = true;
        		self.backStack.push(fi);
        		self.forwardStack.length = 0;
    			var t=self;
    			_.asyRun(function(){t.dontCheck=false;t=null;},300);
    			location.hash = self._lastFI = fi;
    		}else
    		    location.hash = self._lastFI = '#' + fi;
            if(triggerCallback!==false)
		        _.tryF(self._callback,[fi]);
    	}
    }
});Class('linb.ComFactory',null,{
    Static:{
        _pro:{},
        _cache:{},
        _domId:'linb:ComFactory:',
        getProfile:function(key){
            return key?this._pro[key]:this._pro;
        },
        setProfile:function(key, value){
            if(typeof key=='string')
                this._pro[key]=value;
            else
                this._pro=key;
            return this;
        },
        destroyAll:function(){
            _.each(this._cache,function(o){
                _.tryF(o.destroy,[],o);
            });
            this._cache={};
        },
        broadcast:function(fun){
            if(typeof fun=='function'){
                var i,c=this._cache;
                for(i in c)
                    fun.call(c[i],i);
            }
        },

        setCom:function(id, obj){
            this._cache[id]=obj;
            if(obj)obj.comRefId=id;
            return this;
        },
        getComFromCache:function(id){
            return this._cache[id]||null;
        },
        //singleton:false->don't get it from cache, and don't cache the result.
        getCom:function(id, onEnd, threadid, singleton){
            singleton=singleton!==false;
            var c=this._cache,p=this._pro,ini=p._iniMethod;
            if(singleton && c[id]){
                _.tryF(onEnd, [threadid,c[id]], c[id]);
                return c[id];
            }else{
                if(!(p=p[id]))return null;
                var self=arguments.callee, me=this, children=p.children;
                //ensure array
                var iniMethod = p.iniMethod || ini || 'create',
                    clsPath = p.cls || p,
                    properties = p.properties,
                    events = p.events,
                    singleton=p.singleton!==false,
                    cls,
                    task=function(cls,properties,threadid){
                        var o = new cls();
                        if(properties)
                            _.merge(o.properties,properties,'all');
                        if(events)
                            _.merge(o.events,event,'all');

                        if(singleton)
                            linb.ComFactory.setCom(id, o);

                        var args = [function(com){
                            var arr = com.getUIComponents().get(),
                                fun=function(arr,firstlayer){
                                    var self1 = arguments.callee;
                                    _.arr.each(arr,function(v,i){
                                        //if tag exists, replace tag with com from linb.ComFactory
                                        if(v.key=='linb.UI.Tag'){
                                            var tag=v, cid=tag.properties.tagKey;

                                            if(cid && children && children[cid])
                                                self.apply(me, [children[cid], function(){
                                                    //set link to parent com(linb.Com)
                                                    com[cid]=this;
                                                    //set com parent
                                                    this.parent=com;

                                                    //replace tag with this
                                                    var ui = this.getUIComponents(), root;
                                                    // no UI in this com
                                                    if(!(root=ui.get(0)))return;

                                                    linb.UI.Tag.replace(tag,root,firstlayer?com:null);
                                                },threadid]);
                                        }
                                        if(v.children){
                                            var a=[];
                                            _.arr.each(v.children,function(o){
                                                a[a.length]=o[0];
                                            });
                                            self1(a);
                                        }
                                    });
                                };
                            //handle tag sub from com
                            fun(arr,1);
                        }];
                        args.push(threadid||null);

                        //insert first
                        if(onEnd)
                            linb.Thread(threadid).insert({
                                task:onEnd,
                                args:[threadid,o],
                                scope:o
                            });
                        //latter
                        _.tryF(o[iniMethod], args, o);
                    };
                linb.Thread.observableRun(function(threadid){
                        var f=function(a,b,threadid){
                            var cls;
                            if(cls=linb.SC.get(clsPath)){
                                linb.Thread(threadid).insert({
                                    task:task,
                                    args:[cls, properties, threadid]
                                });
                            }
                        };
                        linb.SC(clsPath, function(path){
                            if(path)
                                f(0,0,threadid);
                            else
                                throw new Error(clsPath+' doesnt exists!');
                        }, true,threadid);

                    },null,threadid
                );
            }
        },
        newCom:function(cls, onEnd,threadid){
            var o=linb.SC.get(cls);
            o=typeof o == 'function' ?new o():null;
            if(o)
                _.tryF(onEnd,[threadid,o],o);
            else
                linb.Thread.observableRun(function(threadid){
                    linb.SC(cls, function(path,txt){
                        if(path){
                            var o=linb.SC.get(cls);
                            o=typeof o == 'function' ?new o():null;
                            _.tryF(onEnd,[threadid,o],o);
                        }else
                             throw new Error(cls+' doesnt exists!');
                    }, true,threadid);
                },null,threadid);
        },
        storeCom:function(id){
            var m,t,c=this._cache,domId=this._domId;
            if(t=c[id]){
                if(!(m=linb.Dom.byId(domId)))
                    //using display:none here for performance, when appendchild, it'll not trigger layout etc.
                    linb('body').prepend(linb.create('<div id="'+domId+'" style="display:none;"></div>'));
                m=linb(domId);
                t=t.getUIComponents();
                if(!t.isEmpty()){
                    //detach
                    t.get(0).unlinkParent();
                    //move to hide
                    m.append(t);
                }
            }
        },

        //prepare widget (build css string and add css to head, build template)
        prepareWidgets:function(){
            //prepare UI Ctrl
            var self=this,
                fun=function(){
                    var r=false;
                    _.each(linb.UI, function(o){
                        if(o.$linb$ && o['linb.UI'] && o.$Appearances['default']){
                            var path = linb.getPath(o.KEY, '/default/css.css','appearance');
                            if(!linb.UI.$cache_csspath[path]){
                                o=(new o).get(0);
                                o.toString();
                                o.destroy();
                                r=true;
                                return false;
                            }
                        }
                    });
                    if(!r)return false;
                };
            linb.Thread.repeat(fun,100);
            return this;
        },
        prepareComs:function(arr){
            var self=this,funs=[];
            _.arr.each(arr, function(i){
                funs.push(function(){
                    self.getCom(i);
                });
            });
            linb.Thread(null, funs, 500).start();
            return this;
        }
    }
});Class('linb.Debugger', null, {
    Static:{
        $time:_(),
        _id1:'linb:dbg::_frm',
        _id4:'linb:dbg::_head',
        _id2:'linb:dbg::_con',
        _id3:'linb:dbg::_inp',
        err:function(sMsg,sUrl,sLine){
            if(linb.browser.gek && sMsg=='Error loading script')
                return true;
            linb.Debugger.log( '*** An error raised ***', ' >> Location: '+ sUrl + ' ( line ' + sLine + ' )', ' >> Message: '+sMsg);
        },
        trace:function(obj){
            var args=arguments,
                fun=args[1]||arguments.callee.caller,
                arr=args[2]||[];
            if(fun){
                arr.push('function "' + (fun.$name$||'') + '" in Class "' + (fun.$original$||'') +'"');
                if(fun.caller){
                    try{
                        arguments.callee(null,fun.caller,arr,1);
                    }catch(e){}
                }
            }
            if(!args[3]){
                var a=[];
                a.push(' >> Object Info:');
                if(typeof obj == 'object')
                    for(var i in obj)
                        a.push(' -- ' + i + " : " + obj[i]);
                else
                    a.push(obj);
                a.push(' >> Function Trace: ' + arr.join(' <= '));
                linb.Debugger.log.apply(linb.Debugger,a);
            }
        },
        log:function(){
            var t1,t2,time,self=this,arr=arguments,str;
            if(!arr.length)return;

            t1 = document.createElement("div");
            t2 = document.createElement("div");
            t2.className='linb-dbg-con1';
            time=_();
            t2.appendChild(document.createTextNode('Time stamp : '+time +'('+(time-self.$time)+')' ));
            self.$time=time;
            t1.appendChild(t2);
            for(var i=0,l=arr.length;i<l;i++){
                str=arr[i];
                t2 = document.createElement("div");
                t2.className='linb-dbg-con2';
                t2.appendChild(document.createTextNode(" "+_.serialize(_.isArguments(str)?_.toArr(str):str)));
                t1.appendChild(t2);
            }

            if(!linb.Dom.byId(self._id2)){
                var ns=linb.create('<div id='+self._id1+' style="left:5px;top:'+(linb.win.scrollTop()+5)+'px;" class="linb-dbg-frm"><div class="linb-dbg-box"><div id='+self._id4+' class="linb-dbg-header">&nbsp;&nbsp;:&nbsp;)&nbsp;&nbsp;jsLINB Debug Window <span class="linb-dbg-cmds"><a href="javascript:;" onclick="linb(\''+self._id2+'\').empty(false);">Clear</a><a href="javascript:;" onclick="linb(\''+self._id1+'\').remove();"> &Chi; </a></span></div><div id='+self._id2+' class="linb-dbg-content"></div><div class="linb-dbg-tail"><table><tr><td style="font-family:serif;">&nbsp;>>>&nbsp;</td><td style="width:100%"><input id='+self._id3+' /></td></tr></table></div></div></div>');
                linb('body').append(ns);
                self.$con=linb(self._id2);
                linb(self._id4).onMousedown(function(p,e,s){
                    if(linb.Event.getSrc(e)!=linb.use(s).get(0))return;
                    linb.use(s).parent(2).startDrag(e);
                });

                if(linb.browser.ie6)ns.height(ns.offsetHeight());
                if(ns.addShadow)ns.addShadow();
                var bak='',temp;
                linb(self._id3).onKeydown(function(p,e,s){
                    var k=linb.Event.getKey(e)[0];
                    s=linb.use(s).get(0);
                    if(k=='enter'){
                        switch(s.value){
                            case '?':
                            case 'help':
                                self.$con.append(linb.create("<div class='linb-dbg-con3'><p><strong>vailable commands:</strong></p><ul><li> -- <strong>[clr]</strong> or <strong>[clear]</strong> : clears the message</li><li> -- <strong>[?]</strong> or <strong>[help]</strong> : shows this message</li><li> -- <strong>any other</strong>: shows its string representation</li></ul></div>"));
                                break;
                            case 'clr':
                            case 'clear':
                                linb(self._id2).empty();
                                break;
                            default:
                                try{
                                    temp=s.value;
                                    if(/^\s*\x7b/.test(temp))temp='('+temp+')';
                                    self.log(eval(temp));
                                }catch(e){self.$con.append(linb.create("<div  class='linb-dbg-con4'>"+String(e)+"</div>"));return;}
                        }
                        bak=s.value;
                        s.value='';
                    }else if(k=='up'||k=='down'){
                        var a=s.value;
                        s.value=bak||'';
                        bak=a;
                    }
                });
            }
            self.$con.append(t1).scrollTop(self.$con.scrollHeight());
            t1=t2=null;
        }
    },
    Initialize:function(){
        //window.onerror=(linb.browser.gek && window.console)?null:this.err;

        linb.CSS.addStyleSheet(
            '.linb-dbg-frm{position:absolute;width:300px;z-index:2000;}'+
            '.linb-dbg-header{cursor:move;height:18px;padding-top:2px;position:relative;border-bottom:solid 1px #CCC;background-color:#FFAB3F;font-weight:bold;}'+
            '.linb-dbg-cmds{position:absolute;right:2px;top:2px;}'+
            '.linb-dbg-cmds a{margin:2px;}'+
            '.linb-dbg-box{position:relative;overflow:hidden;border:solid 1px #AAA;}'+
            '.linb-dbg-content{position:relative;width:100%;overflow:auto;height:300px;background:#fff;}'+
            '.linb-dbg-con1{background-color:#CCC}'+
            '.linb-dbg-con2{padding-left:6px;border-bottom:dashed 1px #CCC}'+
            '.linb-dbg-con3{padding-left:6px;border-bottom:dashed 1px #CCC;background:#EEE;color:#0000ff;}'+
            '.linb-dbg-con4{padding-left:6px;border-bottom:dashed 1px #CCC;background:#EEE;color:#ff0000;}'+
            '.linb-dbg-tail{overflow:hidden;position:relative;border-top:solid 1px #CCC;height:16px;background:#fff;color:#0000ff;}'+
            '.linb-dbg-tail input{width:100%;border:0;background:transparent;}'
        ,this.KEY);
        //fix ie6:

        //shorcut
        linb.log = function(){
            if(linb.browser.gek && window.console)
                console.log.apply(console,arguments);
            linb.Debugger.log.apply(linb.Debugger,arguments);
        };
        linb.message = function(body, head, width, time){
           width = width || 200;
           if(linb.browser.ie)width=width+(width%2);
           var div, h, me=arguments.callee,
           stack=me.stack||(me.stack=[]),
           t=linb.win, left = t.scrollLeft() + t.width()/2 - width/2, height=t.height(), st=t.scrollTop();
           
           div=stack.pop();
           while(div&&!div.get(0))
                div=stack.pop();

           if(!div){
               div =
               '<div class="uibg-bar uiborder-outset" style="font-size:0;line-height:0;border:solid 1px #cdcdcd;position:absolute;overflow:visible;top:-50px;z-index:'+linb.Dom.TOP_ZINDEX+'">' +
               '<div style="font-size:14px;overflow:hidden;font-weight:bold;padding:2px;"></div>'+
               '<div style="padding:5px;overflow:hidden;"></div>'+
               '</div>';
               div = linb.create(div);
               if(div.addBorder)div.addBorder();
               linb('body').append(div);
            }
            div.css({left:left+'px', width:width+'px', visibility:'visible'})
            .first().html(head||'').css('visibility',head?'visible':'hidden')
            .next().html(body||'');

            if(me.last && div!=me.last){
                var l=me.last.left();
                me.last.animate({left:[l,l+(me.last.width+width)/2+20]},null,null,100,5).start();
            }
            me.last = div;
            me.last.width = width;

            //height() is ok
            h = div.height();

            if(linb.browser.ie6)div.cssSize({ height :h, width :width+2});

            div.animate({top:[st-h-20,st+20]},null,null,100,5,'expoOut').start();
            _.asyRun(function(){
                div.animate({top:[st+20, height+20]},null,function(){stack.push(div); div.hide()},100,10).start();
            }, time||5000);
        };
    }
});//Profile Class
Class('linb.Profile','linb.absProfile',{
    Constructor:function(host,key,alias,box,properties,events,options){
        arguments.callee.upper.apply(this,arguments);
        var self=this;
        _.merge(self,options);

        self.key=key||self.key||'';
        self.alias=alias||self.alias||'',
        self.properties=properties||self.properties||{};
        self.events=events||self.events||{};
        self.host=host||self.host||self;
        self.box=box||self.box||self.constructor;
        if(self.events){
            self.setEvents(self.events);
            delete self.events;
        }
        self._links={};
    },
    Instance:{
        setEvents:function(events){
            var evs=this.box.$EventHandlers;
            return _.merge(this,events,'all',function(o,i){return evs[i]});
        },
        getEvents:function(){
            var self=this, t,hash={};
            _.each(self.box.$EventHandlers,function(o,i){
                if(self[i])hash[i]=self[i];
            });
            return hash;
        },
        _applySetAction:function(fun, value){
            return fun.call(this,value);
        },
        __gc:function(){
            var ns=this;
            ns.unLinkAll();
            _.tryF(ns.clearCache,[],ns);
            var o=_.get(ns,['box','_namePool']);
            if(o)delete o[self.alias];
            _.breakO([ns.properties, ns.events, ns],2);
        },
        boxing:function(){
            //cache boxing
            var self=this, t;
            if(!((t=self.object) && t.get(0)==self && t._nodes.length==1))
                t = self.object = self.box.pack([self],false);
            return t;
        },
        serialize:function(rtnString, keepHost){
            var t,
                self = this,
                o = (t=self.box._beforeSerialized)?t(self):self,
                r={
                    alias:o.alias,
                    key:o.key,
                    host:o.host
                };
            //host
            if(r.host===self){
                delete r.host;
            }else if(o.host && !keepHost ){
                if(rtnString!==false)
                    r.host='@this';
                else
                    delete r.host;
            }

            //properties
            var c={}, p=o.box.$DataStruct, map=linb.absObj.$specialChars;
            _.merge(c,o.properties, function(o,i){return (i in p) &&  p[i]!==o && !map[i.charAt(0)]});
            if(!_.isEmpty(c))r.properties=c;

            //events
            if(!_.isEmpty(t=this.getEvents()))r.events=t;
            var eh = o.box.$EventHandlers;
            _.filter(r.events, function(o,i){
                return o!=eh[i];
            });
            if(_.isEmpty(r.events))delete r.events;
            return rtnString===false?r:_.serialize(r);
        }
    }
});
//absObj Class
Class('linb.absObj',"linb.absBox",{
    //properties, events, host
    Constructor:function(){
        arguments.callee.upper.apply(this,arguments);
        //for pack function
        if(arguments[0]!==false && typeof this._ini=='function')
            return this._ini.apply(this,arguments);
    },
    Before:function(key, parent_key, o){
        linb.absBox.$type[key]=key;
        return true;
    },
    After:function(){
        var self=this, me=arguments.callee,
            temp,t,k,u,m,i,j,l,v,n,b;
        self._nameId=0;
        self._namePool={};
        self._nameTag=(t=self.KEY.split('.'))[t.length-1].toLowerCase();
        self._cache=[];

        if(self===linb.absObj || self===linb.absObj)return;

        m=me.a1 || (me.a1=_.toArr('$Keys,$DataStruct,$EventHandlers,$DataModel'));
        for(j=0;v=m[j++];){
            k={};
            if((t=self.$parent) && (i=t.length))
                while(i--)
                    _.merge(k, t[i][v]);
            self[v]=k;
        }

        self.setDataModel(self.DataModel);
        delete self.DataModel;

        self.setEventHandlers(self.EventHandlers);
        delete self.EventHandlers;

        m=me.a5 || (me.a5=_.toArr('RenderTrigger,LayoutTrigger'));
        for(j=0;v=m[j++];){
            temp=[];
             if((t=self.$parent) && (l=t.length))
                for(i=0;i<l;i++){
                    u=t[i]
                    if(u=u['$'+v])
                        temp.push.apply(temp,u);
                }
            if(self[v])
                temp.push(self[v]);
            self['$'+v] = temp;
            delete self[v];
        }
    },
    //don't add any other function or member to absObj
    Static:{
        $abstract:true,
        $specialChars:{_:1,$:1},
        getAll:function(){
          return this.pack(this._cache);
        },
        pickAlias:function(){
            var t,p=this._namePool,a=this._nameTag;
            while(p[t=(a+(++this._nameId))]){}
            return  t;
        },
        setDataModel:function(hash){
            var self=this,
                sc=linb.absObj.$specialChars,
                ds=self.$DataStruct,
                properties=self.$DataModel,
                ps=self.prototype,
                i,j,t,o,n,m,r;

            //merge default value and properties
            for(i in hash){
                if(!properties[i])properties[i]={};
                o=hash[i];
                if(null===o || undefined===o){
                    r=_.str.initial(i);
                    delete ds[i];
                    delete properties[i]
                    delete ps['get'+r];
                    delete ps['set'+r];
                //Here, if $DataModel inherites from it's parent class, properties[i] will pointer to parent's object.
                }else{
                    t=typeof o;
                    if(t!='object' || o.constructor!=Object)
                        o={ini:o};
                    ds[i] = ('ini' in o)?o.ini:(i in ds)?ds[i]:'';

                    t=properties[i];
                    for(j in t)
                        if(!(j in o))
                            o[j]=t[j];
                    properties[i]=o;
                }
            }

            _.each(hash,function(o,i){
                if(null===o || undefined===o || sc[i.charAt(0)])return;
                r=_.str.initial(i);
                n = 'set'+r;
                //readonly properties
                if(!(o && (o.readonly || o.inner))){
                    //custom set
                    var $set = o.set;
                    m = ps[n];
                    ps[n] = typeof m=='function' ? m : Class._fun(function(value,force){
                        return this.each(function(v){
                            if(!v.properties)return;
                            //if same return
                            if(v.properties[i] === value && !force)return;

                            var ovalue = v.properties[i];
                            if(v.beforePropertyChanged && false===v.boxing().beforePropertyChanged(v,i,value,ovalue))
                                return;

                            if(typeof $set=='function'){
                                $set.call(v,value,ovalue);
                            }else{
                                var m = _.get(v.box.$DataModel, [i, 'action']);
                                v.properties[i] = value;
                                if(typeof m == 'function' && v._applySetAction(m, value, ovalue) === false)
                                    v.properties[i] = ovalue;
                            }

                            if(v.afterPropertyChanged)
                                v.boxing().afterPropertyChanged(v,i,value,ovalue);
                        });
                    },n,self.KEY);
                    delete o.set;
                    if(ps[n]!==m)ps[n].$auto$=1;
                }else
                    delete ps[n];
                n = 'get'+r;
                if(!(o && o.inner)){
                    // get custom getter
                    var $get = o.get;
                    m = ps[n];
                    ps[n] = typeof t=='function' ? Class._fun(t,n,self.KEY) : typeof m=='function' ? m : Class._fun(function(){
                        if(typeof $get=='function')
                            return $get.call(v);
                        else
                            return this.get(0).properties[i];
                    },n,self.KEY);
                    delete o.get;
                    if(ps[n]!==m)ps[n].$auto$=1;
                }else
                    delete ps[n];
            });
            return self;
        },
        setEventHandlers:function(hash){
            var self=this;
            _.each(hash,function(o,i){
                if(null===o){
                    delete self.$EventHandlers[i];
                    delete self.prototype[i];
                }else{
                    self.$EventHandlers[i]=o;
                    var f=function(fun){
                        var l=arguments.length;
                        if(l==1 && (typeof fun == 'function' || typeof fun == 'string'))
                            return this.each(function(v){
                                if(v.renderId)
                                    v.clearCache();
                                v[i] =fun;
                            });
                        else if(l==1 && null===fun)
                            return this.each(function(v){
                                v.clearCache();
                                delete v[i];
                            });
                        else{
                            var args=[], v=this.get(0), t=v[i], k=v.host || v,j;
                            if(v.$inDesign)return;
                            if(arguments[0]!=v)args[0]=v;
                            for(j=0;j<l;j++)args[args.length]=arguments[j];
                            v.$lastEvent=i;
                            if(typeof t=='string')t=k[t];
                            if(typeof t=='function')return _.tryF(t, args, k);
                        }
                    };
                    f.$event$=1;
                    f.$original$=o.$original$||self.KEY;
                    self.plugIn(i,f);
                }
            });
            return self;
        }
    },
    Instance:{
        alias:function(str){
            var self=this,pro=this.get(0),old;
            if(str){
                if(old=pro.alias){
                    if(pro.host){try{delete pro.host[old]}catch(e){pro.host[old]=undefined}}
                    delete self.constructor._namePool[old];
                }
                self.constructor._namePool[pro.alias=str]=1;
                if(pro.host)
                    pro.host[str]=self;
                return self;
            }else
                return pro.alias;
        },
        host:function(value, alias){
            var self=this;
            if(value){
                self.get(0).host=value;
                if(alias){
                    self.alias(alias);
                    value[alias]=self;
                }
                return self;
            }else
                return self.get(0).host;
        }
        /*non-abstract inheritance must have those functions:*/
        //1. destroy:function(){delete this.box._namePool[this.alias];this.get(0).__gc();}
        //2. _ini(properties, events, host, .....){/*set _nodes with profile*/return this;}
        //3. render(){return this}
    }
});
//DataBinder Class
Class("linb.DataBinder","linb.absObj",{
    Instance:{
        _ini:function(properties, events, host){
            var self=this,
                c=self.constructor,
                profile,
                options,
                np=c._namePool,
                alias;
            if(properties && properties['linb.Profile']){
                profile=properties;
                alias = profile.alias || c.pickAlias();
            }else{
                if(properties && properties.key && linb.absBox.$type[properties.key]){
                    options=properties;
                    properties=null;
                    alias = options.alias;
                    alias = (alias&&!np[alias])?alias:c.pickAlias();
                }else
                    alias = c.pickAlias();
                profile=new linb.Profile(host,self.$key,alias,c,properties,events, options);
            }
            np[alias]=1;
            profile._n=profile._n||[];

            //set anti-links
            profile.link(c._cache,'self').link(linb._pool,'linb');
            
            if(!profile.name)profile.boxing().setName(alias);

            self._nodes.push(profile);
            return self;
        },
        destroy:function(){
            this.each(function(profile){
                var box=profile.box,name=profile.properties.name;
                //unlink
                _.arr.each(profile._n, function(v){box._unBind(name,v)});
                //delete from pool
                delete box._pool[name];
                //free profile
                profile.__gc();
            });
        },
        resetValue:function(hash){
            return this.each(function(o,i){
                _.arr.each(o._n,function(profile){
                    var p=profile.properties;
                    profile.boxing().resetValue((hash && p.dataField in hash)?hash[p.dataField]:'');
                });
            })
        },
        getUI:function(){
            return linb.UI.pack(this.get(0)._n,false);
        },
        checkValid:function(){
            return linb.absValue.pack(this.get(0)._n,false).checkValid();
        },
        getValue:function(){
            var o=this.get(0);
            if( this.checkValid() ){
                var hash={};
                _.arr.each(o._n,function(profile){
                    var p=profile.properties, b = profile.boxing(),v;
                    if(profile.renderId)b.updateValue();
                    v = b.getValue();
                    hash[p.dataField]=v;
                });
                return hash;
            }else return null;
        },
        host:function(value, alias){
            var self=this;
            if(value && alias)
                self.setName(alias);
            return arguments.callee.upper.apply(self,arguments);
        }
    },
    Static:{
        _pool:{},
        destroyAll:function(){
            this.pack(this._pool,false).destroy();
            this._pool={};
        },
        getFromName:function(name){
            var o=this._pool[name];
            return o && o.boxing();
        },
        _bind:function(name, pro){
            var o=this._pool[name];
            if(!o){
                o=new linb.DataBinder();
                o.setName(name);
                o=o.get(0);
            }
            if(pro && _.arr.indexOf(o._n,pro)==-1)
                //use link for 'destroy UIProfile' trigger 'auto unbind function '
                pro.link(o._n, 'databinder.'+name);
        },
        _unBind:function(name, pro){
            if(this._pool[name])
                pro.unLink('databinder.'+name);
        },
        DataModel:{
            name:{
                set:function(value,ovalue){
                    var o=this,
                        c=linb.DataBinder,
                        _p=c._pool,
                        to=_p[ovalue],
                        t=_p[value];
                    
                    //if it exitst, overwrite it dir
                    //if(to && t)
                    //    throw new Error(value+' exists!');

                    _p[o.properties.name=value]=o;
                    //modify name
                    if(to && !t){
                        linb.absValue.pack(o._n).setDataBinder(value);
                        _.arr.each(o._n, function(v){c._unBind(ovalue,v)});
                    }
                    //pointer to the old one
                    if(t && !to) o._n=t._n;
                    //delete the old name from pool
                    if(to)delete _p[ovalue];

                }
            }
        }
    }
});
//UIProfile Class
Class('linb.UIProfile','linb.Profile', {
    Instance:{
        //readonly please
        renderId:null,
        _render:function(){
            var ns=this,t,map=linb.$cache.profileMap;

            //first render
            if(!ns.renderId){
                var ele=linb.Dom.byId(ns.$domId);

                //for dynRender
                if(!ele)return;

                if(ns.domId!=ns.$domId)
                    ele.id=ns.domId;

                map[ns.domId] = map[ns.$domId] = ns;

                //e.g. use div.innerHTML = ui.toHtml();
                if(!ele.$linbid)
                    linb.UI.$addEventsHanlder(ele, true);

                ns.renderId=ele.$linbid;

                ele=null;
            }

            //RenderTrigger
            if(t=ns.RenderTrigger){
                for(var i=0,l=t.length;i<l;i++)
                    t[i].call(ns);
                delete ns.RenderTrigger;
                if(ns.onRender)
                    ns.boxing().onRender(ns);
            }

            if(arguments[0]===true && (t=ns.LayoutTrigger)){
                for(var i=0,l=t.length;i<l;i++)
                    t[i].call(ns);
                if(ns.onLayout)
                    ns.boxing().onLayout(ns);
            }
            if(!ns.box._dynamicRender){
                if(ns.children)
                    for(var i=0,v;v=ns.children[i++];)
                        v[0]._render(true);
    
                if(ns.$attached){
                    for(var i=0,v;v=ns.$attached[i++];)
                        v._render(true);
                    delete ns.$attached;
                }
            }
        },
        __gc:function(){
            var ns=this, t;
            _.tryF(ns.$ondestory,[],ns);
            if(ns.onDestroy)ns.boxing().onDestroy();
            if(ns.destroyTrigger)ns.destroyTrigger();

            //gc already
            if(!ns.serialId)return;
            if(t=ns._$composed)
                _.each(t,function(v){
                    v.__gc();
                });

            //clear cache things
            ns.clearCache();

            //for dock case
            if(t=ns.$dockParent)
                if(t=ns.constructor.getFromDom(t))
                    _.tryF(t.clearCache,[],t);

            //for refresh function
            if(!ns.$noReclaim){
                //restore dom id
                t=linb.$cache.reclaimId;
                (t[ns.key] || (t[ns.key]=[])).push(ns.serialId);
            }else delete ns.$noReclaim

            //clear cache point
            delete linb.$cache.profileMap[ns.domId];
            delete linb.$cache.profileMap[ns.$domId];
            if(ns.box)
                delete ns.box._namePool[ns.alias];

            //clear anti link
            ns.unLinkAll();


            if(ns.LayoutTrigger)
                ns.LayoutTrigger.length=0;
            if(ns.RenderTrigger)
                ns.RenderTrigger.length=0;

            //gc children
            if((t=ns.children).length){
                t=_.copy(t);
                for(var i=0;i<t.length;i++){
                    t[i][0].__gc();
                    t[i].length=0;
                }
                t.length=0;
            }
            //break
            _.breakO([ns.properties,ns.events, ns.CF, ns.CB, ns.CC, ns.CS, ns],2);
        },
        unlinkParent:function(){
            var profile=this;
            delete profile.parent;
            delete profile.childrenId;
            profile.unLink('$parent');
            return profile;
        },
        getRootNode:function(){
            return linb.getNodeData(this.renderId, 'element');
        },
        getRoot:function(){
            return linb([this.renderId],false);
        },
        linkParent:function(parentProfile, linkId){
            var profile=this;
            //unlink first
            profile.unlinkParent();

            //link
            profile.parent = parentProfile;
            profile.childrenId = linkId;
            profile.link(parentProfile.children, '$parent', [profile, linkId]);
            return profile;
        },
        _cacheR1:/^\w[\w_-]*$/,
        setDomId:function(id){
            var t=this, c=linb.$cache.profileMap;
            //ensure the value
            if(typeof id== 'string' && (t._cacheR1.test(id)||id==t.$domId) && !linb.Dom.byId(id)){
                //delete the original one
                if(t.domId!=t.$domId)delete c[t.domId];
                //set profile's domId
                t.domId=id;

                //change the dom Node id value
                if(t.renderId)
                    t.getRootNode().id=id;

                //if doesn't create yet, don't set it to linb.$cache:
                if(c[t.$domId])c[id]=t;
            }
            return t;
        },
        getDomId:function(){
            return this.domId;
        },
        clearCache:function(){
            var ns=this,
                t=ns.$_egetter;
            for(var i in t){
                t[i].length=0;
                delete t[i];
            }

            t=ns.$_domid;
            for(var i in t){
                 t[i].__gc();
                 delete t[i];
            }

            return ns;
        },
        //get events function from profile
        _getEV:function(funs,id, name){
            var self=this,
                $k = id+"+"+name,
                g = self.$_egetter ||(self.$_egetter={}),
                cache;
            if(g[$k]){
                Array.prototype.push.apply(funs,g[$k]);
                return;
            }else cache=g[$k]=[];

            var dom=linb.$cache.profileMap,
                t,key
                ;
            //for event attached on dom node
            if( (t=dom[id]) && (t=t.events) && (t=t[name]) )
                for(var i=0,l=t.length;i<l;i++)
                    if(typeof t[t[i]]=='function')
                        cache.push(funs[funs.length]=t[t[i]]);


            //for event attached on linb widgets
            //get event function path of cache
            key = id.split(":")[0].split("-")[1];

            //for priority intercept
            if(typeof (((t=self._CB) && (key?(t=t[key]):1)) && (t=t[name]))=='function')
                cache.push(funs[funs.length]=t);
            else{
                //get event function from customBehavior first
                if(typeof (((t=self.CB) && (key?(t=t[key]):1)) && (t=t[name]))=='function')
                    cache.push(funs[funs.length]=t);
                else{
                    //get event function from public behavior
                    if(typeof (((t=self.behavior) && (key?(t=t[key]):1)) && (t=t[name]))=='function')
                        cache.push(funs[funs.length]=t);
                }
            }
        },
        _cacheR2:/<!--([^>^\s]*)-->/g,
        toHtml:function(force){
            var self=this,
                c = self.box,
                h={},
                str,
                k1='linb.UIProfile',
                k2='linb.Profile',
                id, i, o, m, a, b, data;
            //before _dynamicTemplate
            data=c._prepareData(self);
            if(c._dynamicTemplate)c._dynamicTemplate(self);
            str = c._build(self, data);

            if((!c._dynamicRender||force) && (m=self.children)){
                for(i=0; o=m[i++];)
                    if(o[0][k1]){
                        id=o[1]||'';
                        a=h[id]||(h[id]=[]);
                        a[a.length]=o[0].toHtml(force);
                    }else if(!o[0][k2]){
                        b.ini.call(b,o[0]);
                        o[0]=b.get(0);
                    }
            }

            return str.replace(self._cacheR2, function(a,b){
                return h[b]?h[b].join(''):'';
            });
        },
        _buildItems:function(key, items){
            var self=this,
                box=self.box,
                str=box._rpt(self, linb.UI.$doTemplate(self, _.get(linb.$cache.template,[box.KEY, self._hash]), items, key));
            return linb.UI.$toDom(str.replace(self._cacheR2,''));
        },
        serialize:function(rtnString, keepHost){
            var t,m,
                self=this,
                o=(t=self.box._beforeSerialized)?t(self):self,
                r={
                    alias:o.alias,
                    key:o.key,
                    host:o.host
                };
            //host
            if(r.host===self){
                delete r.host;
            }else if(o.host && !keepHost ){
                if(rtnString!==false)
                    r.host='@this';
                else
                    delete r.host;
            }

            //domId
            if(o.$domId!=o.domId)r.domId=o.domId;

            //properties
            var c={}, p=o.box.$DataStruct, map=linb.absObj.$specialChars;
            _.merge(c,o.properties, function(o,i){return (i in p) &&  p[i]!==o && !map[i.charAt(0)]});
            if(!_.isEmpty(c))r.properties=c;

            //events
            if(!_.isEmpty(t=this.getEvents()))r.events=t;
            var eh = o.box.$EventHandlers;
            _.filter(r.events, function(o,i){
                return o!=eh[i];
            });
            if(_.isEmpty(r.events))delete r.events;

            if(!_.isEmpty(o.CS)) r.CS=_.copy(o.CS);
            if(!_.isEmpty(o.CB)) r.CB=_.copy(o.CB);
            if(!_.isEmpty(o.CC)) r.CC=_.copy(o.CC);
            if(!_.isEmpty(o.CF)) r.CF=_.copy(o.CF);

            //children
            if(o.children && o.children.length){
                o.children.sort(function(x,y){
                    x=parseInt(x[0].properties.tabindex);y=parseInt(y[0].properties.tabindex);
                    return x>y?1:x==y?0:-1;
                });
                t=r.children=[];
                _.arr.each(o.children,function(v){
                    m=[v[0].serialize(false, keepHost)];
                    if(v[1])m[1]=v[1];
                    t[t.length]=m
                });
            }
            return rtnString===false?r:_.serialize(r);
        },
        _applySetAction:function(fun, value, ovalue){
            if(this.renderId)
                return fun.call(this, value, ovalue);
        },
        getKey:function(id){
            var t;
            if(id.charAt(0)=='!')id=linb.use(id).id();
            if(id.indexOf(':')==-1)id=(t=linb.$cache.profileMap[id])&&(t.$domId);
            return id?id.split(":")[0]:"";
        },
        getSubId:function(id){
            var t;
            if(id.charAt(0)=='!')id=linb.use(id).id();
            if(id.indexOf(':')==-1)id=(t=linb.$cache.profileMap[id])&&(t.$domId);
            return id?id.split(":")[2]:"";
        },
        pickSubId:function(key){
            var self=this, r,o = self.cache_subid || (self.cache_subid={});
            if((o[key] || (o[key]=[]))[0])return o[key].shift();
            o = self.subId || (self.subId={});
            r=(o[key] || (o[key]=new _.id)).next();
            return r;
        },
        reclaimSubId:function(id, key){
            var o = this.cache_subid || (this.cache_subid={});
            (o[key] || (o[key]=[])).push(id);
        },
        /*
        *('KEY','-mouseover',false);
        */
        _cacheR3:/\./g,
        _cacheH1:{},
        getClass:function(key, tag){
            key=this.keys[key] || key;
            var self=this,
                hash=key+":"+(tag||'');
            return self._cacheH1[hash] || (self._cacheH1[hash]=key.replace(self._cacheR3,'-').toLowerCase().replace('linb-ui','linb') + (tag||''));
        },
        _getSubNodeId:function(key, subId){
            var arr = this.$domId.split(':');
            arr[0]=key;
            arr[2]=subId||'';
            key=arr.join(':');
            return key==this.$domId 
                ? linb.$cache.profileMap[key].domId
                : key;
        },
        //flag : remove from cache
        getSubNode:function(key, subId){
            var self=this;
                key=self.keys[key] || key;
            var r,t,s,h=self.$_domid||(self.$_domid={});

            // by key only
            if(subId===true)
                //key==self.keys.KEY for domId!=$domId
                r =linb([self.renderId]).query('*', 'id', key==self.keys.KEY?self.domId:new RegExp('^'+key+':'+self.serialId));
            else{
                if(!subId && h[key] && h[key]._nodes.length==1)return h[key];
                r = (t=linb.Dom.byId(s=self._getSubNodeId(key, subId))) ? linb([t]) : ((t=self.renderId) && linb.use(t).query('*', 'id', s));
                if(!subId)h[key]=r;
            }
            return r;
        },
        getSubNodes:function(arr,subId){
            var i=0,a=[],o;
            for(;o=arr[i++];)
                Array.prototype.push.apply(a,this.getSubNode(o,subId).get());
            return linb(a);
        },
        getSubNodeByItemId:function(key, itemId){
            return (itemId=this.getSubIdByItemId(itemId)) ? this.getSubNode(key, itemId) : linb();
        },
        getItemByItemId:function(itemId){
            var t;
            if((t=this.ItemIdMapSubSerialId) && (t=t[itemId]))
                return this.SubSerialIdMapItem[t];
        },
        getItemByDom:function(src){
            return this.SubSerialIdMapItem && this.SubSerialIdMapItem[
                this.getSubId( typeof src=='string'
                    ? src.charAt(0)=='!'
                        ? ((src=linb.use(src).get(0))&&src.id)
                        : src
                    : src.id )
             ];
        },
        getItemIdByDom:function(src){
            var t;
            return (t=this.getItemByDom(src)) && t.id;
        },
        getSubIdByItemId:function(itemId){
            var t;
            return (t=this.ItemIdMapSubSerialId) && t[itemId];
        },
        queryItems:function(items, fun, deep, single, flag){
            var r=[],
                me=arguments.callee,
                f = me.f || (me.f = function(items, fun, deep, single, r){
                    _.arr.each(items,function(o,i){
                        if(fun===true || fun.call(null, o, i, items)){
                            r.push(flag?[o,i,items]:o);
                            if(single)
                                return false;
                        }
                        if(deep && o.sub && o.sub.length)
                            f(o.sub, fun, deep, single, r);
                    });
                });
            f(items, fun, deep, single, r);
            return r;
        }
    },
    Static:{
        getFromDom:function(id){
            if(
                (
                id=typeof id=='string'
                    ? id.charAt(0)=='!'
                        ? ((id=linb.use(id).get(0)) && id.id)
                        :id
                    : (id && id.id)
                ) &&
                (id=linb.Event._getProfile(id)) && id['linb.UIProfile']
               )
                return id;
        }
    }
});

//UI Class
Class("linb.UI",  "linb.absObj", {
    Before:function(key, parent_key, o){
        linb.absBox.$type[key.replace("linb.UI.","").replace("linb.","")]=linb.absBox.$type[key]=key;
        return true;
    },
    After:function(){
        linb.absObj.After.apply(this,arguments);
        var self=this,me=arguments.callee,
            temp,t,k,u,c,i,j,e,w,v,b,d;

        self._ctrlId = new _.id();
        self._idCache=[];
        self.$cssKeys={};

        /*change keys*/
        t=self.$Keys;
        t.KEY = t.$key = self.KEY;
        self.addTemplateKeys(_.toArr(t,true));

        //Inheriates Behaviors
        v='$Behaviors';
        k={};
        if((t=self.$parent) && (e=t.length)){
            while(e--){
                b=t[e][v];
                for(i in b){
                    if(typeof b[i]=='object'){
                        if(_.isArr(b[i])){
                            u=k[i]||(k[i]=[]);
                            u.push.apply(u,b[i]);
                        }else{
                            u=k[i]||(k[i]={});
                            _.merge(u,b[i]);
                        }
                    }else
                        k[i]=b[i];
               }
            }
        }
        self[v]=k;

        //Inheriates Templates
        v='$Templates';
        k={};
        if((t=self.$parent) && (e=t[0]))
            for(i in e[v])
                if(i.charAt(0)!='$')
                    k[i]=e[v][i];
        self[v]=_.clone(k);

        //Inheriates Appearances
        v='$Appearances';
        k={};
        if((t=self.$parent) && (e=t.length))
        while(e--){
            b=t[e];
            for(i in b[v]){
                t=b[v][i];
                u=k[i]||(k[i]={});
                _.merge(u,t);
            }
        }
        self[v]=k;

        self.setTemplate(self.Templates);
        delete self.Templates;

        self.setBehavior(self.Behaviors||{});
        delete self.Behaviors;

        self.setAppearance(self.Appearances);
        delete self.Appearances;

        if(t=self.PublicAppearance){
            linb.UI.$cache_css += self.buildCSSText(t);
            delete self.PublicAppearance;
        }
    },
    Instance:{
        destroy:function(){
            this.each(function(o){
                _.tryF(o.$beforeDestroy,[],o);
                if(o.beforeDestroy && false===o.boxing().beforeDestroy())return;
                if(o.renderId)o.getRoot().remove();
                else o.__gc();
            });
            this._nodes.length=0;
        },
        serialize:function(rtnString, keepHost){
            var a=[];
            this.each(function(o){
                a[a.length]=o.serialize(false, keepHost);
            });
            return rtnString===false?a:a.length==1?" new "+a[0].key+"("+_.serialize(a[0])+")":"linb.UI.unserialize("+_.serialize(a)+")";
        },

        _toDomElems:function(){
            var arr=[];
            //collect those need to be rendered
            _.arr.each(this._nodes,function(o){
                if(!o.renderId)
                    arr.push(o);
            });
            //render those
            if(arr.length)
                linb.UI.pack(arr,false).render();

            //get rendered
            arr.length=0;
            _.arr.each(this._nodes,function(o){
                arr.push(o.renderId);
            });
            return arr;
        },

        _ini:function(properties, events, host, CS, CC, CB, CF){
            var self=this,
                c=self.constructor,
                profile,
                t='default',
                options,
                np=c._namePool,
                alias,temp;
            if(properties && properties['linb.Profile']){
                profile=properties;
                alias = profile.alias || c.pickAlias();
                linb.UIProfile.apply(profile,[host,self.$key,alias,c,null,events]);
            }else{
                if(properties && properties.key && linb.absBox.$type[properties.key]){
                    options=properties;
                    properties=null;
                    alias = options.alias;
                    alias = (alias&&!np[alias])?alias:c.pickAlias();
                }else
                    alias = c.pickAlias();
                profile=new linb.UIProfile(host,self.$key,alias,c,properties,events, options);
            }
            np[alias]=1;
            for(var i in (temp=c.$DataStruct))
                if(!(i in profile.properties))
                    profile.properties[i]=typeof temp[i]=='object'?_.copy(temp[i]):temp[i];

            profile.keys = c.$Keys;

            // custom
            profile.CS = CS || profile.CS || {};
            profile.CB = CB || profile.CB || {};
            profile.CC = CC || profile.CC || {};
            profile.CF = CF || profile.CF || {};

            profile.template = c.getTemplate();
            profile.behavior = c.$Behaviors;

            if(!profile.serialId)profile.serialId=c._pickSerialId();

            profile.$domId = profile.key + ":" + profile.serialId + ":";
            profile.domId = profile.domId || profile.$domId;

            profile.RenderTrigger=_.copy(c.$RenderTrigger);
            profile.LayoutTrigger=_.copy(c.$LayoutTrigger);

            //set links
            profile.link(linb.UI._cache,'UI').link(c._cache,'self').link(linb._pool,'linb');

            temp=profile.children;
            profile.children=[];
            if(temp && temp.length){
                for(var i=0,v;v=temp[i++];){
                    //from serialize
                    if(!v[0]['linb.UIProfile'])
                        v[0]=new (linb.SC(v[0].key))(v[0]).get(0);
                    v[0].linkParent(profile,v[1]);
                }
            }
            self._nodes.push(profile);

            return self;
        },
        busy:function(message,html,key){
            message=typeof message=='string'?message:'Loading...';
            html=typeof html=='string'?html:'<span style="background:'+ linb.UI.$bg('busy.gif','no-repeat left center')('linb.UI.Public') +';padding-left:16px;">'+message+'</span>';
            return this.each(function(profile){
                _.resetRun(profile.$linbid+':busy',function(){
                    var keys=profile.keys;
                    key=keys[key]||keys['BORDER']||keys['PANEL']||keys['KEY'];

                    var parentNode=profile.getSubNode(key),
                        size=parentNode.cssSize(),
                        node;
                    if(!(node=profile.$busy)){
                        node=profile.$busy=linb.create('<div style="left:0;top:0;z-index:10;position:absolute;background-color:#DDD;"></div><div style="left:0;top:0;z-index:20;text-align:center;position:absolute;"><div>'+html+'</div></div>');
                        linb([node.get(0)]).css({opacity:0.5});
                        linb(parentNode).append(node);
                    }
                    node.css({display:'',width:size.width+'px',height:size.height+'px'});
                    linb([node.get(1).firstChild]).html(html,false).css('paddingTop',size.height/2+'px');
                },50);
            });
        },
        free:function(){
            return this.each(function(profile){
                _.resetRun(profile.$linbid+':busy');
                if(profile.$busy)profile.$busy.css('display','none');
            });
        },
        reLayout:function(force){
            return this.each(function(o){
                if(!o.renderId)return;
                var p=o.properties;

                if((!o.$noB) && p.border && o.boxing()._border)
                    o.boxing()._border(null,false);

                if(p.dock && p.dock!='none'){
                    //set 0 to force resize
                    o.getRootNode().style.width=0;
                    o.getRootNode().style.height=0;
                    linb.UI.$dock(o,true,true);
                }else
                    linb.UI.$tryResize(o,p.width,p.height,force);
            });
        },
        toHtml:function(force){
            var a=[];
            _.arr.each(this._nodes,function(o){
                a[a.length]=o.toHtml(force);
            });
            return a.join('');
        },
        render:function(triggerLayOut){
            var ns=this, arr=[], i, l, o, n=ns._nodes, matrix, a=[],byId=linb.Dom.byId;

            linb.UI.$applyCSS();

            //get those no-html items
            for(i=0;o=n[i++];)
                if(!o.renderId && !linb.Dom.byId(o.domId) && !linb.Dom.byId(o.$domId))
                    arr[arr.length]=o;

            //build html and to dom
            if(l=arr.length){
                for(i=0;i<l;i++) a[a.length]=arr[i].toHtml();
                linb.UI.$toDom(a.join(''));
            }

            //render UIProfiles
            for(i=0;o=n[i++];)
                o._render(triggerLayOut);

            a.length=arr.length=0;
            return ns;
        },
        renderOnto:function(node, host){
            node=linb(node);
            if(node.isEmpty())return this;

            var self=this,
                pro=self.get(0),
                me=arguments.callee,
                para=me.para||(me.para=function(node){
                    var r = node.cssRegion();
                    r.tabindex=node.attr('tabIndex');
                    if(r.tabindex<=0)delete r.tabindex;
                    r.zIndex=node.css('zIndex');
                    r.position=node.css('position');
                    return r;
                }),
                id=node.id();

            _.merge(pro.properties, para(node),'all');
            pro.properties.dock='none';
            if(!pro.alias && id)
                pro.alias=id;
            if(pro.alias)
                self.host(host||window, pro.alias);
            self.render(true);
            node.replace(self.getRoot());

            if(id)
                self.setDomId(id);

            return self;
        },
        setDomId:function(id){
            this.get(0).setDomId(id);
            return this;
        },
        hide:function(){
            return this.each(function(o){
                if(o.renderId){
                    o.getRoot().hide();
                    o.properties.top=o.properties.left=-10000;
                    o.properties.dockIgnore=true;
                }
            });
        },
        show:function(parent,subId,left,top){
            return this.each(function(o){
                var t=o.properties,b;
                left=(left||left===0)?(parseInt(left)||0):null;
                top=(top||top===0)?(parseInt(top)||0):null;
                if(left!==null)t.left=left;
                if(top!==null)t.top=top;
                if(linb.getNodeData(o.renderId,'_linbhide')){
                    b=1;
                    t.dockIgnore=false;
                    o.getRoot().show(left&&(left+'px'), top&&(top+'px'));
                    if(t.dock && t.dock!='none')
                        linb.UI.$dock(o,false,true);
                //first call show
                }else if(!parent && (!o.renderId || (o.getRootNode().id || "").indexOf(linb.Dom._emptyDivId)===0))
                    parent=linb('body');
                var p=parent,n;
                if(p){
                    if(p['linb.UIProfile']){n=p.renderId;p=p.boxing()}
                    else if(p['linb.UI'])n=(n=p.get(0))&&n.renderId;
                    else n=(p=linb(p))&&p._nodes[0];
                    if(n){
                        p.append(o.boxing(),subId);
                        if(!b)o.getRoot().show(left&&(left+'px'), top&&(top+'px'));
                    }
                }
            });
        },
        clone:function(){
            var arr=[],f=function(p){
                //remove those
                delete p.alias;delete p.domId;
                if(p.children)
                    for(var i=0,c;c=p.children[i];i++)
                        f(c);
            };
            this.each(function(o){
                o=o.serialize(false,true);
                f(o);
                arr.push(o);
            });
            return this.constructor.unserialize(arr);
        },
        refresh:function(){
            var para,node,b,p,s,$linbid,serialId,fun,box,children;
            return this.each(function(o){
                if(!o.renderId)return;

                box=o.box;

                //save related id
                $linbid=o.$linbid;
                serialId=o.serialId;

                //keep parent
                if(b=!!o.parent){
                    p=o.parent.boxing();
                    para=o.childrenId;
                }else
                    p=o.getRoot().parent();

                //protect children's dom node
                //no need to trigger layouttrigger here
                node=linb.$getGhostDiv();
                o.boxing().getChildren().reBoxing().each(function(v){
                    node.appendChild(v);
                });
                node=null;

                //keep children
                children = _.copy(o.children);
                o.boxing().removeChildren();

                //unserialize
                s = o.serialize(false, true);
                fun = o.$addOns;

                //replace
                var replace = linb.create('span');
                o.getRoot().replace(replace);

                //destroy it
                //avoid reclaiming serialId
                o.$noReclaim=1;
                o.boxing().destroy();

                //set back
                _.merge(o,s,'all');
                o.$linbid=$linbid;
                o.serialId=serialId;

                //create
                o=new box(o).render();

                //for functions like: UI refresh itself
                if(fun)
                    fun.call(fun.target,o.get(0));

                //add to parent, and trigger RenderTrigger
                if(b)
                    p.append(o,para);
                else
                    p.append(o);

                //restore children
                _.arr.each(children,function(v){
                    delete v[0].$dockParent;
                    o.append.apply(o,v);
                });

                //back to original position
                replace.replace(o.get(0).getRoot());
                replace.remove();
                replace=null;
            });
        },
        append:function(target, subId){
            if(_.isHash(target) || _.isStr(target))
                target=linb.create(target);
            if(target['linb.UIProfile'])target=target.boxing();
            var pro=this.get(0),parentNode;

            if(pro.beforeAppend && false===this.beforeAppend(pro,target))
                return;
            
            if(subId!==false && target['linb.UI']){
                target.each(function(profile){
                    profile.linkParent(pro,subId);
                });
            }
            if(pro.renderId){
                if(subId=typeof subId=='string'?subId:null)subId=pro.getSubIdByItemId(subId);
                parentNode=pro.keys.PANEL?pro.getSubNode(pro.keys.PANEL, subId):pro.getRoot();
                if(!parentNode.isEmpty())
                    parentNode.append(target);
            }
            if(pro.afterAppend)
                this.afterAppend(pro,target);
            return this;
        },
        getChildren:function(subId){
            var a=[];
            _.arr.each(this.get(0).children,function(v){
                if(subId?v[1]==subId:1)
                    a.push(v[0]);
            });
            return linb.UI.pack(a);
        },
        removeChildren:function(subId, bDestroy){
            return this.each(function(o){
                var c=_.copy(o.children);
                _.arr.each(c,function(v){
                    if(subId?typeof subId=='string'?(v[1]==subId):(v[0]==(subId["linb.UI"]?subId.get(0):subId)):1){
                        if(o.beforeRemove && false===o.boxing().beforeRemove(o,v[0],v[1],bDestroy))
                            return;

                        v[0].unlinkParent();

                        if(o.afterRemove)
                            o.boxing().afterRemove(o,v[0],v[1],bDestroy);

                        if(bDestroy)
                            v[0].boxing().destroy();                    }
                });
            });
        },
        dragable:function(dragKey, dragData, key, options){
            return this.each(function(o){
                o.getSubNode(o.keys[key] || 'KEY', true)
                .beforeMousedown(dragKey?function(pro,e,src){
                    if(pro.properties.disabled)return;
                    options=options||{};
                    options.dragKey=dragKey;
                    options.dragData=typeof dragData == 'function'?dragData():dragData;
                    _.merge(options,{
                        dragCursor:'pointer',
                        dragType:'icon',
                        dragDefer:1
                    });
                    linb.use(src).startDrag(e, options);
                }:null,'_d',-1)
                .beforeDragbegin(dragKey?function(profile, e, src){
                    linb.use(src).onMouseout(true,{$force:true}).onMouseup(true);
                }:null,'_d',-1);
                if(!dragKey)
                    o.clearCache();
            });
        },
        setCustomFunction:function(key, value){
            return this.each(function(o){
                if(typeof key=='string'){
                    if(value) o.CF[key]=value;
                    else delete o.CF[key];
                }else
                    o.CF=key||{};
            });
        },
        setCustomClass:function(key, value){
            var me=arguments.callee,
                fun=(me.fun||(me.fun=function(pro,i, h, flag){
                    if(!h[i])return;
                    var node=pro.getSubNode(i,true),b;
                    if(!node.isEmpty())
                        _.arr.each(h[i].split(/\s+/),function(o){
                            node[flag?'removeClass':'addClass'](o);
                        });
                }));
            return this.each(function(o){
                var bak = _.copy(o.CC);

                //set key and value
                if(typeof key=='string'){
                    if(o.renderId)
                        if(key in bak)
                            fun(o, key, bak, true);

                    if(!value)
                        delete o.CC[key];
                    else{
                        o.CC[key]=value;
                        if(o.renderId)
                            fun(o, key, o.CC);
                    }
                //set hash dir
                }else if(!!key && typeof key=='object'){
                    if(o.renderId){
                        for(var i in key)
                            fun(o, i, bak, true);
                        for(var i in key)
                            fun(o, i, key);
                    }
                    o.CC=key;
                //clear all
                }else{
                    if(o.renderId)
                        for(var i in bak)
                            fun(o, i, bak, true);
                    o.CC={};
                }
            });
        },
        setCustomStyle:function(key,value){
            var me=arguments.callee,
                fun=(me.fun||(me.fun=function(pro,i,h, flag){
                    if(!h[i])return;
                    var node=pro.getSubNode(i,true),b;
                    if(!node.isEmpty())
                        _.arr.each(h[i].split(';'),function(o,i){
                            if((b=o.split(':')).length==2){
                                b[0]=b[0].replace(/\-(\w)/g,function(a,b){return b.toUpperCase()});
                                try{node.css(b[0], flag?'':b[1])}catch(e){}
                            }
                        });
                }));
            return this.each(function(o){
                var bak = _.copy(o.CS);

                //set key and value
                if(typeof key=='string'){
                    if(o.renderId)
                        if(key in bak)
                            fun(o, key, bak, true);

                    if(!value)
                        delete o.CS[key];
                    else{
                        o.CS[key]=value;
                        if(o.renderId)
                            fun(o, key, o.CS);
                    }
                //set hash dir
                }else if(!!key && typeof key=='object'){
                    if(o.renderId){
                        for(var i in key)
                            fun(o, i, bak, true);
                        for(var i in key)
                            fun(o, i, key);
                    }
                    o.CS=key;
                //clear all
                }else{
                    if(o.renderId)
                        for(var i in bak)
                            fun(o, i, bak, true);
                    o.CS={};
                }
            });
        },
        setCustomBehavior:function(key, value){
            return this.each(function(o){
                if(typeof key=='string'){
                    if(o.keys[key])
                        o.CB[key]=value||{};
                }else
                    o.CB=key||{};
                if(o.CB.KEY){
                    _.merge(o.CB, o.CB.KEY, 'all');
                    delete o.CB.KEY;
                }
                o.clearCache();
            });
        }
    },
    Initialize:function(){
        var ns=this.prototype;
        _.arr.each('getSubNode,getDomId,getRootNode,getRoot'.split(','),function(o){
            if(!ns[o])
                ns[o]=function(){
                    var p=this.get(0);
                    return p[o].apply(p,arguments);
                };
                ns[o].$original$='linb.UI';
        });

        var self=this, hash={};
        _.each(linb.UI.$ps,function(i,o){
            hash[o] = {
                ini:'auto',
                action:function(value){
                    var self=this,
                        p=self.properties,b=false,
                        args={$type:p.dock};

                    switch(p.dock){
                        case 'top':
                            if(o!='height'&&o!='top')return;
                            args.width=args.height=1;
                            break;
                        case 'bottom':
                            if(o!='height'&&o!='bottom')return;
                            args.width=args.height=1;
                            break;
                        case 'left':
                            if(o!='width'&&o!='left')return;
                            args.width=args.height=1;
                            break;
                        case 'right':
                            if(o!='width'&&o!='right')return;
                            args.width=args.height=1;
                            break;
                        case 'width':
                            if('width'==o)return;
                            args.width=1;
                            break;
                        case 'height':
                            if('height'==o)return;
                            args.height=1;
                            break;
                        case 'fill':
                        case 'cover':
                            if(o=='width'&&o=='height')return;
                            args.width=args.height=1;
                            break;
                    }
                    self.getRoot()[o]?self.getRoot()[o](value):linb.Dom._setPxStyle(self.getRootNode(),o,value);
                    if(p.dock!='none')_.tryF(self.$dock,[self, args],self);
                    if(o=='width'||o=='height'){
                        if(self.onResize)
                            self.boxing().onResize(self,o=='width'?value:null,o=='height'?value:null)
                    }else{
                        if(self.onMove)
                            self.boxing().onMove(self,o=='left'?value:null,o=='top'?value:null,o=='right'?value:null,o=='bottom'?value:null)
                    }                        
                }
            }
        });
        _.merge(hash,{
            renderer:{
                ini:null
            },
            //invalid after dom dom Node
            zIndex:{
                ini:1,
                action:function(value){
                    this.getRoot().css('zIndex',value);
                }
            },
            tabindex:{
                ini:1,
                action:function(value){
                    var ns=this,
                        reg=new RegExp("^"+ns.key+"[-\\w]*"+":"+ns.serialId+":");
                    ns.getRoot().query("*",function(n){
                        return n.id && reg.test(n.id) && n.getAttribute('tabIndex');
                    }).attr('tabIndex',value);
                }
            },
            position:{
                ini : 'absolute',
                listbox:['','static','relative','absolute'],
                action:function(value){
                    this.getRoot().css('position',value);
                }
            },
            visibility:{
                listbox:['','visible','hidden'],
                action:function(value){
                    this.getRoot().css('visibility',value);
                }
            },
            display:{
                listbox:['','none','block','inline','inline-block'],
                action:function(value){
                    if(value=='inline-block')
                        this.getRoot().setInlineBlock();
                    else
                        this.getRoot().css('display',value);
                }
            }
        });

        self.setDataModel(hash);

        linb.UI.$cache_css += linb.UI.buildCSSText({
            '.linb-html, .linb-html BODY':{
                overflow:'hidden',
                height:'100%',
                border:'0 none',
                margin:'0',
                padding:'0'
            },
            '.ui-ctr':{},
            '.ui-dragable':{},
            '.ui-btn, .ui-btni, .ui-btnc':{
                height:'22px',
                background:linb.UI.$bg('button.gif', 'no-repeat', true)
            },
            '.ui-btn':{
                $order:1,
                'white-space': 'nowrap',
                'vertical-align':'top',
                overflow:'hidden',
                'background-position':'right top',
                'padding-right':'4px',
                'font-size':'12px'
            },
            '.ui-btn *':{
                cursor:'pointer'
            },
            '.ui-btnc button, .ui-btnc a':{
                display:linb.$inlineBlock,
                zoom:linb.browser.ie?1:null,
                background:'transparent',
                border:0,
                margin:0,
                padding:0
            },
            '.ui-btnc a':{
                padding:'0 4px'
            },
            '.ui-btni':{
                $order:1,
                'background-position':'left -60px',
                'padding-left':'4px',
                'vertical-align':'top'
            },
            '.ui-btnc':{
                $order:1,
                'background-position':'left -30px',
                'background-repeat': 'repeat-x',
                'padding-top':'3px',
                'vertical-align':'top'
            },
            '.ui-btn-mouseover, .ui-btn-focus':{
                $order:2,
                'background-position':'right -90px'
            },
            '.ui-btn-mouseover .ui-btni, .ui-btn-focus .ui-btni':{
                $order:2,
                'background-position':'left -150px'
            },
            '.ui-btn-mouseover .ui-btnc, .ui-btn-focus .ui-btnc':{
                $order:2,
                'background-position':'left -120px'
            },
            '.ui-btn-mousedown, .ui-btn-checked':{
                $order:3,
                'background-position':'right -180px'
            },
            '.ui-btn-mousedown .ui-btni, .ui-btn-checked .ui-btni':{
                $order:3,
                'background-position':'left -240px'
            },
            '.ui-btn-mousedown .ui-btnc, .ui-btn-checked .ui-btnc':{
                $order:3,
                'background-position':'left -210px'
            },
            '.ui-icon':{
                'vertical-align':'middle',
                width:'16px',
                height:'16px',
                margin:'0 4px 0 2px'
            },
            '.uicmd-close, .uicmd-opt, .uicmd-land, .uicmd-toggle, .uicmd-toggle2, .uicmd-min, .uicmd-max,.uicmd-restore,.uicmd-pin, .uicmd-check, .uicmd-radio, .uicmd-add':{
                background: linb.UI.$bg('icons.gif', 'no-repeat 0 0', true),
                width:'16px',
                height:'16px',
                'margin-right':'2px',
                cursor:'default',
                'vertical-align':'middle'
            },
            '.uicmd-empty':{
                width:'16px',
                height:'16px',
                'margin-right':'2px',
                cursor:'default',
                'vertical-align':'middle'
            },
            '.uicmd-opt':{
                $order:1,
                'background-position' : '0 0'
            },
            '.uicmd-opt-mouseover':{
                $order:2,
                'background-position' : '0 -20px'
            },
            '.uicmd-opt-mousedown':{
                $order:3,
                'background-position' : '0 -40px'
            },
            '.uicmd-land':{
                $order:1,
                'background-position' : '-40px 0'
            },
            '.uicmd-land-mouseover':{
                $order:2,
                'background-position' : '-40px -20px'
            },
            '.uicmd-land-mousedown':{
                $order:3,
                'background-position' : '-40px -40px'
            },
            '.uicmd-pin':{
                $order:1,
                'background-position' : '-80px 0'
            },
            '.uicmd-pin-mouseover':{
                $order:2,
                'background-position': '-80px -20px'
            },
            '.uicmd-pin-mousedown':{
                $order:3,
                'background-position': '-80px -40px'
            },
            '.uicmd-pin-checked, .uicmd-pin-checked-mouseover, .uicmd-pin-checked-mousedown':{
                $order:4,
                'background-position':  '-80px -40px'
            },
            '.uicmd-min':{
                $order:1,
                'background-position' : '-120px 0'
            },
            '.uicmd-min-mouseover':{
                $order:2,
               'background-position': ' -120px -20px'
            },
            '.uicmd-min-mousedown':{
                $order:3,
               'background-position':  '-120px -40px'
            },
            '.uicmd-restore':{
                $order:1,
                'background-position' : '-160px 0'
            },
            '.uicmd-restore-mouseover':{
                $order:2,
               'background-position':  '-160px -20px'
            },
            '.uicmd-restore-mousedown':{
                $order:3,
               'background-position':  '-160px -40px'
            },
            '.uicmd-max':{
                $order:1,
                'background-position' : '-200px 0'
            },
            '.uicmd-max-mouseover':{
                $order:2,
               'background-position':  '-200px -20px'
            },
            '.uicmd-max-mousedown':{
                $order:3,
               'background-position':  '-200px -40px'
            },
            '.uicmd-close':{
                $order:1,
                'background-position' : '-240px 0'
            },
            '.uicmd-close-mouseover':{
                $order:2,
                'background-position' : '-240px -20px'
            },
            '.uicmd-close-mousedown':{
                $order:3,
                'background-position' : '-240px -40px'
            },
            '.uicmd-check':{
                $order:1,
                margin:'0 4px 0 2px',
                'background-position' : '-20px -70px'
            },
            '.uicmd-check-mouseover':{
                $order:2,
                'background-position' : '-20px -90px'
            },
            '.uicmd-check-mousedown':{
                $order:3,
                'background-position' : '-20px -110px'
            },
            '.uicmd-check-checked':{
                $order:4,
                'background-position' : '0 -70px'
            },
            '.uicmd-check-checked-mouseover':{
                $order:5,
                'background-position' : '0 -90px'
            },
            '.uicmd-check-checked-mousedown':{
                $order:6,
                'background-position' : '0 -110px'
            },
            '.uicmd-radio':{
                $order:1,
                margin:'0 4px 0 2px',
                'background-position' : '-60px -70px'
            },
            '.uicmd-radio-mouseover':{
                $order:2,
                'background-position' : '-60px -90px'
            },
            '.uicmd-radio-mousedown':{
                $order:3,
                'background-position' : '-60px -110px'
            },
            '.uicmd-radio-checked':{
                $order:4,
                'background-position' : '-40px -70px'
            },
            '.uicmd-radio-checked-mouseover':{
                $order:5,
                'background-position' : '-40px -90px'
            },
            '.uicmd-radio-checked-mousedown':{
                $order:6,
                'background-position' : '-40px -110px'
            },
            '.uicmd-add':{
                $order:1,
               'background-position':'-56px -222px'
            },
           '.uicmd-add-mouseover':{
                $order:2,
                'background-position':'-56px -222px'
           },
           '.uicmd-add-mousedown':{
                $order:3,
                'background-position':'-56px -222px'
           },


            '.uicmd-toggle':{
                $order:1,
                'margin-left':'3px',
                'background-position': '-160px -70px'
            },
            '.uicmd-toggle-mouseover':{
                $order:2,
                'background-position': '-160px -90px'
            },
            '.uicmd-toggle-mousedown':{
                $order:3,
                'background-position': '-160px -110px'
            },
            '.uicmd-toggle-checked':{
                $order:4,
                'background-position': '-180px -70px'
            },
            '.uicmd-toggle-checked-mouseover':{
                $order:5,
                'background-position': '-180px -90px'
            },
            '.uicmd-toggle-checked-mousedown':{
                $order:6,
                'background-position': '-180px -110px'
            },
            '.uicmd-toggle-busy':{
                $order:7,
                background: linb.UI.$bg('busy.gif', 'no-repeat center center', true)
            },
            '.uicmd-toggle2':{
                $order:1,
                'background-position': '-200px -70px'
            },
            '.uicmd-toggle2-mouseover':{
                $order:2,
                'background-position': '-200px -90px'
            },
            '.uicmd-toggle2-mousedown':{
                $order:3,
                'background-position': '-200px -110px'
            },
            '.uicmd-toggle2-checked':{
                $order:4,
                'background-position': '-220px -70px'
            },
            '.uicmd-toggle2-checked-mouseover':{
                $order:5,
                'background-position': '-220px -90px'
            },
            '.uicmd-toggle2-checked-mousedown':{
                $order:6,
                'background-position': '-220px -110px'
            },


            '.uibar-top, .uibar-bottom, .uibar-top-s, .uibar-bottom-s':{
                position:'relative',
                //for avoiding extra space after table in IE
                'vertical-align':'baseline',
                'font-size':0,
                'line-height':0
            },
            '.uibar-top td, .uibar-top-s td, .uibar-bottom td, .uibar-bottom-s td':{
                $order:1,
                background: linb.UI.$bg('bar_vertical.gif', 'no-repeat 0 0', true)
            },
//uibar-top
            /*set table height for ff2, set uibar height for performance*/
            '.uibar-top, .uibar-top .uibar-t':{
                height:'29px'
            },
            '.uibar-top .uibar-tdl':{
                $order:1,
                'padding-left':'4px',
                height:'100%',
                'background-position': '0 0'
            },
            '.uibar-top .uibar-tdm':{
                $order:1,
                'background-position': '0 -30px',
                'background-repeat': 'repeat-x'
            },
            '.uibar-top .uibar-tdr':{
                $order:1,
                'padding-left':'4px',
                'background-position': 'right -60px'
            },
            '.uibar-top-focus .uibar-tdl':{
                $order:2,
                'padding-left':'4px',
                height:'100%',
                'background-position': 'left -90px'
            },
            '.uibar-top-focus .uibar-tdm':{
                $order:2,
                'background-position': 'left -120px',
                'background-repeat': 'repeat-x'
            },
            '.uibar-top-focus .uibar-tdr':{
                $order:2,
                'padding-left':'4px',
                'background-position': 'right -150px'
            },
            '.uibar-top .uibar-cmdl':{
                '-moz-user-select':'none',
                overflow:'hidden',
                position:'absolute',
                left:0,
                top:'6px',
                width:'92%',
                height:'22px',
                'padding-left':'8px',
                'white-space': 'nowrap'
            },
            '.uibar-top .uibar-cmdr':{
                '-moz-user-select':'none',
                position:'absolute',
                top:'6px',
                right:'8px',
                'text-align':'right'
            },
            '.uicon-main':{
                position:'relative',
                'padding-left':'5px',
                'font-size':0,
                'line-height':0,
                'z-index':1,
                overflow:'visible',
                background: linb.UI.$bg('bar_horizontal.gif', 'repeat-y -595px top', true)
            },
            '.uicon-maini':{
                'padding-right':'5px',
                'font-size':0,
                'line-height':0,
                background: linb.UI.$bg('container_right.gif', '#AAD2FA repeat-y right top', true)
            },
//uibar-bottom
            '.uibar-bottom, .uibar-bottom .uibar-t':{
                height:'12px'
            },
            '.uibar-bottom .uibar-tdl':{
                $order:1,
                'padding-left':'5px',
                height:'100%',
                'background-position': 'left -189px'
            },
            '.uibar-bottom .uibar-tdm':{
                $order:1,
                'background-position': 'left -211px',
                'background-repeat': 'repeat-x'
            },
            '.uibar-bottom .uibar-tdr':{
                $order:1,
                'padding-left':'5px',
                'background-position': 'right -233px'
            },
//uibar-top-s
            '.uibar-top-s, .uibar-top-s .uibar-t':{
                $order:3,
                height:'7px'
            },
            '.uibar-top-s .uibar-tdl':{
                $order:3,
                height:'100%',
                'padding-left':'5px',
                'background-position': 'left -261px'
            },
            '.uibar-top-s .uibar-tdm':{
                $order:3,
                'background-position': 'left -283px',
                'background-repeat': 'repeat-x'
            },
            '.uibar-top-s .uibar-tdr':{
                $order:3,
                'padding-left':'5px',
                'background-position': 'right -305px'
            },
            '.uibar-top-s .uibar-cmdl':{
                $order:3,
                display:'none'
            },
            '.uibar-top-s .uibar-cmdr':{
                $order:3,
                display:'none'
            },
//uibar-bottom-s
            '.uibar-bottom-s, .uibar-bottom-s .uibar-t':{
                $order:3,
                height:'6px'
            },
            '.uibar-bottom-s .uibar-tdl':{
                $order:3,
                height:'100%',
                'padding-left':'5px',
                'background-position': 'left -327px'
            },
            '.uibar-bottom-s .uibar-tdm':{
                $order:3,
                'background-position': 'left -349px',
                'background-repeat': 'repeat-x'
            },
            '.uibar-bottom-s .uibar-tdr':{
                $order:3,
                'padding-left':'5px',
                'background-position': 'right -371px'
            }
        })
        + linb.UI.buildCSSText({
            '.ui-ctrl':{
                'vertical-align':'middle'
            },
            '.uiw-shell':{
                background:'transparent',
                display:linb.$inlineBlock,
                zoom:linb.browser.ie6?1:null,
                //overflow:'hidden',
                /*opera must be 0 not 'none'*/
                border:0,
                padding:0,
                margin:0
            },
            /*span*/
            '.uiw-frame':{
                $order:1,
                display:'block',
                position:'relative',
                //overflow:'hidden',
                border:0,
                padding:0,
                margin:0,
                width:'100%',
                height:'100%',
                '-moz-box-flex':'1'
            },
            /*span*/
            '.uiw-border':{
                $order:2,
                display:'block',
                position:'absolute',
                border:0,
                padding:0,
                margin:0,
                left:0,
                top:0,
                width:'100%',
                height:'100%'
            },
            '.ui-dirty':{
                $order:1,
                background: linb.UI.$bg('icons.gif', 'no-repeat', true),
                'background-position':'-390px -290px'
            },
            '.ui-disabled, .ui-disabled *':{
                color: '#808080'
            },
            '.ui-invalid, .ui-invalid *':{
                'background-color': '#FFEBCD'
            },
            '#linblangkey':{
                'vertical-align':'baseline'
            }
        })
        + linb.UI.buildCSSText({
            '.uibg-base':{
                'background-color':'#fff'
            },
            '.uibg-bar':{
                'background-color':'#aad2fa'
            },
            '.uiborder-inset':{
                border:'solid 1px',
                'border-color':'#648cb4 #c8e1fa #c8e1fa #648cb4'
            },
            '.uiborder-outset':{
                border:'solid 1px',
                'border-color':'#c8e1fa #648cb4 #648cb4 #c8e1fa'
            }
        });
    },
    $End:function(){
        linb.UI.$cache_css += this.buildCSSText(this.$Appearances);
    },
    Static:{
        $cache_css:'',
        $css_tag_dirty: "ui-dirty",
        $css_tag_invalid: "ui-invalid",
        $tag_left:"{",
        $tag_right:"}",
        $tag_special:'#',
        $ID:"#id#",
        $DOMID:'#domid#',
        $CLS:"#cls#",
        $tag_subId:"_serialId",
        $childTag:"<!--{id}-->",
        $onSize:function(profile,e){
            var style = profile.getRootNode().style;
            if(e.width||e.height)
                linb.UI.$tryResize(profile, style.width, style.height);
            style=null;
        },

        $theme:'default',
        $ps:{left:1,top:1,width:1,height:1,right:1,bottom:1},

        $toDom:function(str){
            //must use empty div for RenderTriggers
            var matrix=linb.Dom.getEmptyDiv().get(0), r=[];
            matrix.innerHTML=str;
            //add event handlers
            this.$addEventsHanlder(matrix);
            for(var i=0,t=matrix.childNodes,l=t.length;i<l;i++){
                //ensure the root nodes
                linb.$registerNode(t[i]);
                r[r.length]=t[i].$linbid;
            }
            matrix=null;
            return linb(r,false);
        },
        $addEventsHanlder:function(node, includeSelf){
            var ch=linb.$cache.UIKeyMapEvents,
                eh=linb.Event._eventHandler,
                children=_.toArr(node.getElementsByTagName('*')),
                i,l,j,k,id,t,v;

            if(includeSelf)
                children.push(node);
            if(l=children.length){
                for(i=0;i<l;i++){
                    if((node=children[i]).nodeType!=1)continue;
                    if(id=node.id){
                        if(t = ch[id] || ch[id.substr(0,id.indexOf(':'))] ){
                            v=linb.$registerNode(node);
                            v=v.eHandlers||(v.eHandlers={});
                            for(j in t){
                                //attach event handler to domPurgeData
                                v[j]=t[j];
                                //attach event handler to dom node
                                if(k=eh[j])
                                    v[k]=node[k]=t[j];
                            }
                        }
                    }
                }
            }
            children.length=0;
            node=null;
        },
        getFromDom:function(id){
            if(id=linb.UIProfile.getFromDom(id))
                return id.boxing();
        },
        unserialize:function(target,keepSerialId){
            if(typeof target=='string')target=_.unserialize(str);
            var f=function(o){
                if(_.isArr(o))o=o[0];
                delete o.serialId;
                if(o.children)_.arr.each(o.children,f);
            }, a=[];
            _.arr.each(target,function(o){
                if(!keepSerialId)f(o);
                a.push((new (linb.SC(o.key))(o)).get(0));
            });
            return this.pack(a,false);
        },

        _ensureValues:function(arr){
            var a=[],i=0,k=0,o,key=this.KEY,cache=linb.$cache.profileMap,getData=linb.getNodeData;
            if(arr['linb.absBox'])arr=arr._nodes;
            for(;o=arr[i++];)
                if((o.box && o.box[key]) || ((o=cache[getData(o.renderId?o.renderId:o,['element','id'])]) && o.box && o.box[key]))
                    a[k++]=o;
            return a.length<=1?a:this._unique(a);
        },

        __gc:function(){
            var self=this, k=self.$key, cache=linb.$cache;
            //clear templates memory in linb.$cache
            _.breakO([cache.template[k], cache.reclaimId[k], self._cache, self._idCache, self.$DataModel, self.$Templates,  self.$Behaviors, self],2);
            delete linb.absBox.$type[k.replace("linb.UI.","")];
            delete linb.absBox.$type[k];
            _.filter(linb.$cache.UIKeyMapEvents,function(o,i){
                return !(i==k||i.indexOf(k+'-')==0);
            });
            // add for base class
            Class.__gc(k);
        },
        _pickSerialId:function(){
            //get id from cache or id
            var arr = linb.$cache.reclaimId[this.$key];
            if(arr && arr[0])return arr.pop();
            return this._ctrlId.next();
        },
        $bg:function(path, para, forceKey){
            return function(key){
                var p=linb.ini.path + 'appearance/default/'+ (typeof forceKey=='string'?forceKey:forceKey?'Public':(p=key.split('.'))[p.length-1]) + "/" + path;
                //_.asyRun(function(){new Image().src=p;});
                return 'url(' + p +') '+ (para||'');
            }
        },
        $ieBg:function(path,  forceKey){
            return function(key){
                var p=linb.ini.path + 'appearance/default/'+ (typeof forceKey=='string'?forceKey:forceKey?'Public':(p=key.split('.'))[p.length-1]) + "/" + path;
                //_.asyRun(function(){new Image().src=p;});
                return 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="'+p+'",sizingMethod="crop")';
            }
        },

       /* deep template function
          template: string
          properties: hash

          $doTemplate("{a}{b}{c}{a}{b}{/c}", {a:'*',b:'#',c:[{a:'1',b:'.'},{a:'2',b:'.'},{a:'3',b:'.'},{a:'4',b:'.'}]})
              will return "*#1.2.3.4."
          doTemplate("{a}{b}{c}{}{/c}", {a:'*',b:'#',c:['1','2','3','4']})
              will return "*#1234"

          flag: default flase => no clear not mactched symbols
        */
        $doTemplate:function(profile, template, properties, tag, result){
            var self=arguments.callee,
                s,t,n,
                isA = properties.constructor == Array,
                temp = template[tag||''],
                r = !result,
                result= result || [];
            if(isA){
                if(typeof temp != 'function')temp = self;
                for(var i=0;t=properties[i++];)
                    temp(profile, template, t, tag, result);
            }else{
                if(t=properties.object){
                    //[properties] is for linb.Template
                    result[result.length]=t.toHtml();
                }else{
                    if(typeof temp == 'function')
                        temp(profile, template, properties, tag, result);
                    else{
                        tag = tag?tag+'.':'';
                        var a0=temp[0], a1=temp[1];
                        for(var i=0,l=a0.length;i<l;i++){
                            if(n=a1[i]){
                                if(n in properties){
                                    t=properties[n];
                                    //if sub template exists
                                    if(template[s=tag+n] && t)
                                        self(profile, template, t, s, result);
                                    else
                                        result[result.length]=t;
                                }
                            }else
                                result[result.length]=a0[i];
                        }
                    }
                }
            }
            if(r)return result.join('');
        },
        /*
        set properties default map and set properties handler
        It's a merge function, not replace

        this.$DataStruct: {a:,b:,c}
        this.$DataModel: from hash, for example:
        hash:{
            key1:{
                ini:xx,
                set:fun..,
                get:fun..,
                action: fun
            },
            key2:null,
            key3:'abc,
        }
        */
        $buildTemplate:function(profile, template, key, obj, arr){
            if(template && String(template.tagName).toLowerCase()=='text'){
                arr[arr.length] = template.text;
                return;
            }
            var self =arguments.callee,
                behavior = profile.behavior?key?profile.behavior[key]:profile.behavior:null,
                map1 = self.map1 ||(self.map1={tagName:1,text:1}),
                map2 = self.map2 ||(self.map2={image:1,input:1,br:1,meta:1,hr:1,abbr:1,embed:1}),
                r2=self.r2||(self.r2=/[a-z]/),
                r3=self.r3 || (self.r3=/^(on|before|after)/),
                r7=self.r7 || (self.r7=/([^{}]*)\{([\w]+)\}([^{}]*)/g),
                first=false,
                u=linb.UI,
                t, o , bak, lkey;

            if(!template)template=profile.template;
            lkey = key?profile.keys[key]:profile.key;

            //tagName
            if(!template.tagName)template.tagName="span";

            if(template.id!==null)
                //id
                template.id = key?lkey + ":" + u.$ID + ":" + u.$tag_left + u.$tag_subId + u.$tag_right:u.$DOMID;
            else
                delete template.id;

            if(template.className!==null){
                //className
                t = u.$CLS + (key?'-'+key.toLowerCase():'');
                //save bak
                bak = template.className || '';

                //default class first
                template['class'] =  t+' '+
                    //custom class here
                    bak+' '+
                    //add a special
                    (lkey==profile.key?' ui-ctrl ':'') +
                    //custom class
                    u.$tag_special + (key||'KEY') + '_CC'+u.$tag_special
                    ;
            }
            delete template.className;

            template.style = (template.style||'')+';'+ u.$tag_special + (key||'KEY') + '_CS'+u.$tag_special;

            var a=[], b={}, tagName=template.tagName, text= template.text, sc=linb.absObj.$specialChars;
            for(var i in template){
                if(!template[i])continue;
                if(!sc[i.charAt(0)] && !map1[i]){
                    o=template[i];
                    if(!r2.test(i)){
                        // collect sub node
                        if(typeof o == 'object'){
                            if(!o.$order)o.$order=0;
                            o.$key=i;
                            a[a.length]=o;
                        }
                    }else
                        b[i]=o;
                }
            }
            // sort sub node
            a.sort(function(x,y){
                x=x.$order;y=y.$order;
                return x>y?1:x==y?0:-1;
            });

            //first
            if(!arr){
                first=true;
                arr=[];
            }
            //<span id="" style="">
            arr[arr.length]='<'+tagName+' ';
            for(var i in b)
                if(b[i])
                    arr[arr.length]=i+'="'+b[i]+'" ';

            //set className bak
            if(template.className!==null)
                template.className = bak;

            delete template['class'];

            arr[arr.length]='{attributes}>';

            if(!map2[tagName] && text)
                arr[arr.length]=text;

            // add sub node
            for(var i=0,l=a.length;i<l;){
                o=a[i++];
                self(profile, o, o.$key, obj, arr)
            }

            if(!map2[tagName])
                arr[arr.length]='</'+tagName+'>';

            if(first){
                var a0=obj[0],a1=obj[1];
                arr.join('').replace(r7,function(a,b,c,d){
                    if(b)a0[a0.length]=b;
                    a1[a0.length]=a0[a0.length]=c;
                    if(d)a0[a0.length]=d;
                    return '';
                });
            }
        },
        _rpt:function(profile,temp){
            var me=arguments.callee,
                tag=linb.UI.$tag_special,
                r=me._r||(me._r=new RegExp( tag+'([0-9A-Z_]+)_C([SC])'+tag + '|'+ tag+'([\\w_\\-\\.]*)'+tag, 'img')),
                h1={
                    id:profile.serialId,
                    cls:profile.getClass('KEY'),
                    domid:profile.$domId
                },
                h2={
                    S:profile.CS,
                    C:profile.CC
                };
            return temp.replace(r, function(a,b,c,d){return h1[d] || h2[c][b] || ''});
        },
        _build:function(profile, data){
            var template, t, m,
                u=linb.UI,
                temp=[[],[]],
                self=this,
                key=self.KEY,
                cache=linb.$cache.template,
                hash = profile._hash =
                    'b:' + (profile.template._subid||'') + ';' +
                    '!' + (profile._exhash||'');

            //get template
            if(!(template = _.get(cache,[key, hash]))){
                //get main template
                u.$buildTemplate(profile,null,null,temp);
                //split sub template from main template

                //set main template
                _.set(cache, [key, hash, ''], temp);
                //set sub template
                if(t=profile.template.$submap)
                    for(var i in t){
                        if(typeof (m=t[i])!='function'){
                            var temp=[[],[]];
                            for(var j in m)
                                if(typeof m[j] == 'object')
                                    u.$buildTemplate(profile, m[j], j, temp);
                            m=temp;
                        }
                        _.set(cache, [key,hash,i], m);
                    }

                template = _.get(cache,[key, hash]);
            }
            if(!template)return '';

            //replace main template
            return self._rpt(profile, u.$doTemplate(profile, template, data));
        },
        /*
        allow function input, for some css bug
        */
        _setDefaultBehavior:function(hash){
            var self=this,
                me=arguments.callee,
                map=me._m||(me._m={'':1,KEY:1,$key:1}),
                f=me._f1||(me._f1=function(arr, type, mode){
                    var fun = function(profile, e, src){
                        var t,
                            id=linb.use(src).id(),
                            item,
                            cid = profile.getSubId(id),
                            prop = profile.properties,nodes,funs,box;
                        if(prop.disabled)return;
                        item = profile.SubSerialIdMapItem && profile.SubSerialIdMapItem[cid];
                        if(item && item.disabled)return;
                        switch(typeof arr){
                            case 'string':
                                nodes=profile.getSubNode(arr,cid)._get();
                                break;
                            case 'function':
                                funs=[arr];
                                break;
                            case 'object':
                                nodes=[];funs=[];
                                for(var o,i=0,l=arr.length;i<l;i++){
                                    o=arr[i];
                                    if(typeof o=='string')
                                        nodes.push.apply(nodes,profile.getSubNode(o,cid)._get());
                                    else
                                        funs.push(o);
                                }
                        }

                        if(nodes&&nodes.length){
                            nodes=linb(nodes);
                            box=profile.boxing();
                            if(mode==1){
                                if(type=='mouseover' && profile.beforeHoverEffect)
                                    if(false == box.beforeHoverEffect(profile, item, e, src, 'mouseover'))
                                        return;
                                if(type=='mousedown' && profile.beforeClickEffect)
                                    if(false == box.beforeClickEffect(profile, item, e, src, 'mousedown'))
                                        return;

                                //default action
                                nodes.tagClass('-'+type);
                            }else{
                                if(type=='mouseup'){
                                    if(profile.beforeClickEffect && false == box.beforeClickEffect(profile, item, e, src, 'mouseup'))
                                        return;
                                    nodes.tagClass('-mousedown', false);
                                }else{
                                    if(profile.beforeHoverEffect && false == box.beforeHoverEffect(profile, item, e, src, 'mouseout'))
                                        return;
                                    nodes.tagClass('(-mouseover|-mousedown)', false);
                                }
                            }
                        }
                        if(funs&&funs.length){
                            _.arr.each(funs,function(o){
                                _.tryF(o,[profile],profile)
                            });
                            funs.length=0;
                        }
                   };
                    return fun;
                }),
                hls={},t;
            if(!linb.SC.get('linb.absComposed'))
                Class('linb.absComposed','linb.absObj',{
                    Instance:{
                        addPanel:function(para, children, item){
                            var pro = _.copy(linb.UI.Panel.$DataStruct);
                            _.merge(pro, para, 'with');
                            _.merge(pro,{
                                dock:'fill',
                                tag:para.tag||para.id
                            },'all');

                            var pb = new linb.UI.Panel(pro),arr=[];
                            this.append(pb, item&&item.id);
                            _.arr.each(children,function(o){
                                arr.push(o[0]);
                            });
                            pb.append(linb.UI.pack(arr,false));
                            return this;
                        },
                        removePanel:function(){
                            this.destroy();
                        },
                        getPanelPara:function(){
                            return _.copy(this.get(0).properties);
                        },
                        getPanelChildren:function(){
                            return this.get(0).children;
                        },
                        _e1:function(profile, item, e, src, type){},
                        _e2:function(profile, key, control, shift, alt, e, src){},
                        _e3:function(profile, e, shift, src){},
                        _e4:function(profile, e, src, key, data, item){},
                        _e5:function(profile, e, src){}
                    },
                    Static:{
                        DataModel:{
                            dragKey:'',
                            dropKeys:''
                        },
                        $abstract:true
                    }
                });
            var src=linb.absComposed.prototype;

            if(hash.HoverEffected){
                _.each(hash.HoverEffected,function(o,i){
                    t=map[i]?hash:(hash[i]||(hash[i]={}));
                    if(!o)
                        t.afterMouseover = t.afterMouseout = null;
                    else{
                        t.afterMouseover = f(o,'mouseover', 1);
                        t.afterMouseout = f(o,'mouseout', 2);
                    }
                });
                hls.beforeHoverEffect=src._e1;
            }
            if(hash.ClickEffected){
                _.each(hash.ClickEffected,function(o,i){
                    t=map[i]?hash:(hash[i]||(hash[i]={}));
                    if(!o)
                        t.afterMousedown = t.afterMouseup = null;
                    else{
                        t.afterMousedown = f(o,'mousedown', 1);
                        t.afterMouseup = f(o,'mouseup', 2);
                    }
                });
                hls.beforeClickEffect=src._e1;
            }
            //for onHotKey
            if(hash.KeyHook){
                _.merge(hash,{
                    afterKeydown:function(profile, e, src){
                        if(profile.onHotKeydown){
                            var key = linb.Event.getKey(e);
                            return false !== profile.boxing().onHotKeydown(profile,key[0], !!key[1], !!key[2], !!key[3], e, src);
                        }
                    },
                    afterKeypress:function(profile, e, src){
                        if(profile.onHotKeypress){
                            var key = linb.Event.getKey(e);
                            return false !== profile.boxing().onHotKeypress(profile,key[0], !!key[1], !!key[2], !!key[3], e, src);
                        }
                    },
                    afterKeyup: function(profile, e, src){
                        if(profile.onHotKeyup){
                            var key = linb.Event.getKey(e);
                            return false !== profile.boxing().onHotKeyup(profile,key[0], !!key[1], !!key[2], !!key[3], e, src);
                        }
                    }
                },'all');
                hls.onHotKeydown=hls.onHotKeypress=hls.onHotKeyup=src._e2;
            }
            //for focus action
            if(hash.NavKeys){
                _.each(hash.NavKeys,function(o,i){
                    var map=arguments.callee, k, m1=map.m1||(map.m1={KEY:1,$key:1});
                    if(m1[i])return;
                    var m2=map.m2||(map.m2={input:1,textarea:1}),
                    m3=map.m3||(map.m3={tab:1,enter:1,up:1,down:1,left:1,right:1}),
                    m4=map.m4||(map.m4={tab:1,up:1,down:1,left:1,right:1}),
                    t=hash[i]||(hash[i]={});

                    if(null===o)
                        t.afterKeydown = null;
                    else{
                        t.afterKeydown = function(profile, e, src){
                            var k=linb.Event.getKey(e), key = k[0], ctrl=k[1], shift=k[2], alt=k[3], b=false;
                            if(m2[k=linb.use(src).get(0).tagName.toLowerCase()]){
                                if(m3[key]){
                                    var reg = linb.use(src).caret(),txt=linb.use(src).get(0).value;

                                    switch(key){
                                        case 'up':
                                            if(!/[\n\r]/.test(txt.substr(0,reg[0]))) b=true;
                                            break;
                                        case 'left':
                                            if((ctrl&&!shift) || (reg[0]===0 && (reg[1]!==txt.length || reg[1]===0))) b=true;
                                            break;
                                        case 'down':
                                            if(!/[\n\r]/.test(txt.substr(reg[1],txt.length))) b=true;
                                            break;
                                        case 'right':
                                            if((ctrl&&!shift) || (reg[1]===txt.length && (reg[0]!==0 || reg[1]===0))) b=true;
                                            break;
                                        case 'enter':
                                            if(k=='input' || alt)b=true;
                                            break;
                                        case "tab":
                                            b=true;
                                            break;
                                    }
                                }
                            }else
                                if(m4[key])
                                    b=true;
                            //hanlder focus
                            if(b){
                                //export event
                                if(profile.beforeNextFocus && false === profile.boxing().beforeNextFocus(profile,key,!!shift,e))return false;

                                if(key!='tab')
                                    linb.use(src).nextFocus(('up'==key || 'left'==key)?false:true);
                            }
                        }
                    }
                });
                hls.beforeNextFocus=src._e3;
            }
            if((t=hash.DropableKeys) && t.length){
                _.arr.each(t,function(o){
                    self._dropable(o)
                });

                t=self.prototype;
                _.arr.each('addPanel,removePanel,getPanelPara,getPanelChildren,getDropKeys,setDropKeys'.split(','),function(o){
                    if(!t[o])t[o]=src[o];
                });
                self.$DataModel.dropKeys=self.$DataStruct.dropKeys='';
                hls.onDragEnter=hls.onDragLeave=hls.onDrop=hls.onDropTest=hls.onDropMarkShow=hls.onDropMarkClear=src._e4;
            }
            if((t=hash.DragableKeys)&& t.length){
                _.arr.each(t,function(o){
                    self._dragable(o)
                });
                t=self.prototype;
                _.arr.each('getDragKey,setDragKey'.split(','),function(o){
                    if(!t[o])t[o]=src[o];
                });
                self.$DataModel.dragKey=self.$DataStruct.dragKey='';
                hls.onGetDragData=hls.onStartDrag=hls.onDragStop=src._e5;
            }
            self.setEventHandlers(hls);
        },

        addTemplateKeys:function(arr){
            var self=this, key=self.KEY, me=arguments.callee, reg=me._reg||(me._reg=/\./g);
            _.arr.each(arr,function(i){
                self.$cssKeys[i]=(self.$Keys[i]=i=='KEY'?key:key+"-"+i).replace(reg,'-').toLowerCase().replace('linb-ui','linb');
            });
            return self;
        },
        $CSSCACHE:{},
        $getCSSValue:function(cls, key){
            var cache=this.$CSSCACHE,
                ck=cls+'->'+key,
                me=arguments.callee;
            if(ck in cache)return cache[ck];
            var c=linb.Dom.getEmptyDiv().get(0),r;
            c.className=cls;
            r=cache[ck]=parseInt(linb.Dom.getStyle(c,key))||0;
            c.className="";
            return r;
        },
        getTheme:function(){
            return this.$theme;
        },
        setTheme:function(key){
            key=key||'default';
            var ns=this;
            if(key!=ns.$theme){
                if(key!='default')
                    linb.CSS.includeLink(linb.getPath('linb.appearance.'+key,'/theme.css'),'theme:'+key);
                var o=linb.CSS.get('id','theme:'+ns.$theme);
                if(o){
                    o.disabled=true;
                    linb(o).remove(false);
                }
                ns.$theme=key;
                ns.$CSSCACHE={};
                var count=0;
                _.asyRun(function(){
                    if(count>5)
                        throw new Error('errLoadTheme:'+key);
                    count++;
                    var s=linb.CSS.$getCSSValue('.setting-uikey','fontFamily');
                    if(s==key || key=='default'){
                        linb.UI.getAll().reLayout(true);
                        count=null;
                    }else
                        _.asyRun(arguments.callee,200*count);
                },100);
            }
            return this;
        },
        setAppearance:function(hash){
            _.merge(this.$Appearances,hash,'all');
            return this;
        },
        getAppearance:function(){
            return this.$Appearances;
        },
        /*replace mode*/
        setTemplate:function(hash, cacheId){
            if(hash){
                var self=this,
                    me=arguments.callee,
                    r2=me.r2||(me.r2=/[a-z]/),
                    sc=linb.absObj.$specialChars,
                    _ks=['KEY'],
                    fun = me._fun || (me._fun=function(hash, arr){
                        var o,i;
                        for(i in hash){
                            if(!sc[i.charAt(0)])
                                if(!r2.test(i)){
                                    arr[arr.length]=i;
                                    o=hash[i];
                                    if(typeof o == 'object')
                                        arguments.callee(o, arr)
                                }
                        };
                    })
                    ,t;
                fun(hash,_ks);
                self.addTemplateKeys(_ks);

                t = self.$Templates;

                // for sub template,
                if(typeof cacheId=='string'){
                    hash._subid = cacheId;
                    t[cacheId]=hash;
                }else
                    t._=hash;

                //set sub
                if(t=hash.$submap)
                    for(var i in t)
                        for(var j in t[i])
                            me.call(self, t[i], j);
            }
            return this;
        },
        getTemplate:function(cacheId){
            return this.$Templates[cacheId||'_'];
        },
        /*replace mode*/
        setBehavior:function(hash){
            if(hash){
                var self=this,
                    ch=linb.$cache.UIKeyMapEvents,
                    skey=self.$key,
                    check=linb.absObj.$specialChars,
                    handler = linb.Event.$eventhandler,
                    eventType=linb.Event._eventMap,
                    me=arguments.callee,
                    r1=me.r1||(me.r1=/[a-z]/),
                    r2=me.r2||(me.r2=/^(on|before|after)/),
                    t= self.$Behaviors,
                    m,i,j,k,o,v, type;
                //set shortcut first
                self._setDefaultBehavior(hash);
                //merge KEY
                if(hash.KEY){
                    _.merge(hash, hash.KEY, 'all');
                    delete hash.KEY;
                }

                //merge hash
                for(i in hash){
                    o=hash[i];
                    if(!check[i.charAt(0)]){
                        //only two layer
                        if(!r1.test(i)){
                            m=t[i]||(t[i]={});
                            for(j in o){
                                v=o[j];
                                if(!check[j.charAt(0)]){
                                    /*set to behavior*/
                                    if(v)
                                        m[j]=v;
                                    else
                                        delete m[j];
                                }
                            }
                        }else if(r2.test(i)){
                            /*set to behavior*/
                            if(o)
                                t[i]=o;
                            else
                                delete t[i];
                        //for those special keys
                        }else
                            t[i]=o;
                    }
                }

                //remove all handler cache
                _.filter(ch,function(o,i){
                    return !(i==skey||i.indexOf(skey+'-')==0);
                });
                //add handler cache
                for(i in t){
                    o=t[i];
                    if(!check[i.charAt(0)]){
                        //only two layer
                        if(!r1.test(i)){
                            for(j in o){
                                if(!check[j.charAt(0)] && o[j]){
                                    k=skey+'-'+i;
                                    (ch[k]||(ch[k]={}))['on'+eventType[j]]=handler;
                                }
                            }
                        }else if(r2.test(i) && o){
                            k=skey;
                            (ch[k]||(ch[k]={}))['on'+eventType[i]]=handler;
                        }
                    }
                }
            }

            return self;
        },
        getBehavior:function(){
            return this.$Behaviors;
        },
        $applyCSS:function( ){
            var self=linb.UI, cache=self.$cache_css;
            if(cache){
                if(!self.$cssNo)self.$cssNo=1;
                linb.CSS.addStyleSheet(cache, 'linb.UI-CSS'+(self.$cssNo++));
                linb.UI.$cache_css='';
            }
        },
        buildCSSText:function(hash){
            var self=this,
                me=arguments.callee,
                r1=me._r1||(me._r1=/(^|\s|,)([0-9A-Z_]+)/g),
                h=[], r=[],
                browser=linb.browser,
                ie6=browser.ie6,
                ie=browser.ie,
                gek=browser.gek,
                ks=self.$cssKeys,
                t,v,o;

            for(var i in hash){
                o=hash[i];
                t=i.replace(r1,function(a,b,c){return  b + '.' + (ks[c]||c)}).toLowerCase();
                o.$order=parseInt(o.$order)||0;
                o.$=t;
                h[h.length]=o;
            };
            h.sort(function(x,y){
                x=x.$order;y=y.$order;
                return x>y?1:x==y?0:-1;
            });

            for(var i=0,l=h.length;i<l;){
                o=h[i++];
                r[r.length]=o.$+"{";
                if(t=o.$before)r[r.length]=t;
                if(t=o.$text)r[r.length]=t;
                for(var j in o){
                    switch(j.charAt(0)){
                        case '$':continue;break;
                        case '_':if(!ie6)continue;break;
                        case '*':if(!ie)continue;break;
                        case '-':if(!gek)continue;break;
                    }
                    //neglect '' or null
                    if((v=o[j])||o[j]===0){
                        //put string dir
                        switch(typeof v){
                        case 'string':
                        case 'number':
                            r[r.length]=j+":"+v+";";break;
                        case 'function':
                            r[r.length]=j+":"+v(self.KEY)+";";break;
                        //arrray
                        default:
                            _.arr.each(v,function(k){
                                //neglect '' or null
                                if(k)r[r.length]=j+":"+k+";";
                            });
                        }
                    }
                }
                if(v=o.$after)r[r.length]=v;
                r[r.length]="}";
            }
            return r.join('');
        },
        _dropable:function(key){
            var self=this,
                h2=linb.Event.$eventhandler2,
                o=self.$Behaviors,
                v=key=='KEY'?o:(o[key]||(o[key]={})),
                handler=linb.$cache.UIKeyMapEvents,
                k2=key=='KEY'?self.KEY:(self.KEY+'-'+key),
                ch=handler[k2]||(handler[k2]={});

            //attach Behaviors
            _.merge(v, {
                beforeMouseover:function(profile, e, src){
                    if(profile.properties.disabled||profile.properties.readonly)return;
                    var ns=src,
                        dd = linb.DragDrop,
                        pp = dd.getProfile(),
                        key = pp.dragKey,
                        data = pp.dragData,
                        item,box,t,args
                        ;

                    //not include the dragkey
                    if(!key
                    || !data
                    || !(new RegExp('\\b'+key+'\\b')).test(profile.box.getDropKeys(profile, ns))
                    )return;

                    box=profile.boxing();
                    if(box.getItemByDom)
                        item=box.getItemByDom(src);

                    args=[profile, e, ns, key, data, item];
                    if((t=profile.onDropTest) && (false===box.onDropTest.apply(box,args)))
                        return;
                    if((t=profile.box._onDropTest) && (false===t.apply(profile.host||profile, args)))
                        return;
                    //for trigger onDrop
                    dd.setDropElement(src);
                    if(profile.onDropMarkShow && (false===box.onDropMarkShow.apply(box,args))){}
                    else if((t=profile.box._onDropMarkShow) && (false===t.apply(profile.host||profile, args))){}
                    else
                        //show region
                        _.resetRun('setDropFace', dd.setDropFace, 0, [ns], dd);

                    if(t=profile.box._onDragEnter)t.apply(profile.host||profile, args);
                    if(profile.onDragEnter)box.onDragEnter.apply(box,args);
                    //dont return false, multi layer dd wont work well
                    //return false;
                },
                beforeMouseout:function(profile, e, src){
                    if(profile.properties.disabled||profile.properties.readonly)return;
                    var dd = linb.DragDrop,
                        pp = dd.getProfile(),
                        key = pp.dragKey,
                        data = pp.dragData,
                        item, box, args;

                    //not include the dragkey
                    if(pp.dropElement==src){
                        box=profile.boxing();
                        if(box.getItemByDom)
                            item=box.getItemByDom(src);

                        args=[profile, e, src, key, data, item];
                        if(profile.onDropMarkClear && (false===box.onDropMarkClear.apply(box,args))){}
                        else if((t=profile.box._onDropMarkClear) && (false===t.apply(profile.host||profile, args))){}
                        else _.resetRun('setDropFace', dd.setDropFace, 0, [null], linb.DragDrop);

                        if(t=profile.box._onDragLeave)t.apply(profile.host||profile, args);
                        if(profile.onDragLeave)box.onDragLeave.apply(box,args);
                        dd.setDropElement(null);
                    }
                    //return false;
                },
                beforeDrop:function(profile, e, src){
                    var dd = linb.DragDrop,
                        pp = dd.getProfile(),
                        key = pp.dragKey,
                        data = pp.dragData,
                        item,t,args,
                        box=profile.boxing();
                    if(box.getItemByDom)
                        item=box.getItemByDom(src);
                    args=[profile, e, src, key, data, item];

                    if(profile.onDropMarkClear && (false===box.onDropMarkClear.apply(box,args))){}
                    else if((t=profile.box._onDropMarkClear) && (false===t.apply(profile.host||profile, args))){}

                    if(profile.onDrop && (false===box.onDrop.apply(box,args))){}
                    else if((t=profile.box._onDrop) && (false===t.apply(profile.host||profile, args))){}
                }
            }, 'all');
            _.merge(ch,{
                onmouseover:h2,
                onmouseout:h2,
                ondrop:h2
            });
            return self;
        },
        _dragable:function(key){
            var self=this,
                h2=linb.Event.$eventhandler2,
                o=self.$Behaviors,
                v=key=='KEY'?o:(o[key]||(o[key]={})),
                handler=linb.$cache.UIKeyMapEvents,
                k2=key=='KEY'?self.KEY:(self.KEY+'-'+key),
                ch=handler[k2]||(handler[k2]={});
            //attach Behaviors
            _.merge(v, {
                beforeMousedown:function(profile, e, src){
                    if(profile.properties.disabled)return;
                    //not resizable or drag
                    if(!profile.properties.dragKey)return;
                    var pos=linb.Event.getPos(e),box=profile.boxing(),args=[profile,e,src],t;
                    if(profile.onStartDrag && (false===box.onStartDrag.apply(box,args))){}
                    else if((t=profile.box._onStartDrag) && (false===t.apply(profile.host||profile, args))){}
                    else{
                        var con=profile.box;
                        linb.use(src).startDrag(e, {
                            dragType:'icon',
                            targetLeft:pos.left+12,
                            targetTop:pos.top+12,
                            dragCursor:'pointer',
                            dragDefer:1,
                            dragKey: con.getDragKey(profile, src),
                            dragData: con.getDragData(profile, e, src)
                        });
                    }
                },
                beforeDragbegin:function(profile, e, src){
                    linb.use(src).onMouseout(true,{$force:true}).onMouseup(true);
                },
                beforeDragstop:function(profile, e, src){
                    var t;
                    if(profile.onDragStop)profile.boxing().onDragStop(profile.e,src);
                    if(t=profile.box._onDragStop)t.apply(profile.host||profile, arguments);
                }
            }, 'all');
            _.merge(ch,{
                onmousedown:h2,
                ondragbegin:h2
            });

            return self;
        },
        /*copy item to hash, use 'without'
        exception: key start with $
        value(start with $) get a change to get value from lang setting
        */
        adjustData:function(profile, hashIn, hashOut){
            if(!hashOut)hashOut={};
            var i,o,w=linb.wrapRes,me=arguments.callee,r=me._r||(me._r=/\B\$([\w]+[\.][\w\.]+[\w])/g);
            for(i in hashIn){
                if(i.charAt(0)=='$')continue;
                if(hashIn.hasOwnProperty(i) &&  !hashOut.hasOwnProperty(i))
                    hashOut[i] = typeof (o=hashIn[i])=='string' ?
                             (
                                  ((o.indexOf('$')!=-1) ? (o=o.replace(r, function(a,b){return w(b)})) : o)
                                &&((o.charAt(0)=='@') ? (linb.SC.get(o.substr(1,o.length)) || o) : o)
                              ) : o;
            }

            if('disabled' in hashOut)
                hashOut.disabled=hashOut.disabled?'ui-disabled':'';

            //todo:remove the extra para
            hashOut.imageDisplay = (hashOut.imageClass||hashOut.image)?'':'display:none';
            if(hashOut.image)
                hashOut.backgroundImage="background-image:url("+ hashOut.image +");";
            if(hashOut.imagePos)
                hashOut.backgroundPosition='background-position:'+hashOut.imagePos+';';

            if((typeof (o=hashOut.renderer)=='function') || (typeof (o=hashIn.renderer)=='function'))
                hashOut.caption=o.call(profile,hashIn,hashOut);

            return hashOut;
        },

        cacheData:function(key, obj){
            _.set(linb.$cache,['UIDATA', key], obj);
            return this;
        },
        getCachedData:function(key){
            var r = _.get(linb.$cache,['UIDATA', key]);
            if(typeof r == 'function')r=r();
            return _.clone(r);
        },

        Behaviors:{
            onContextmenu:function(profile, e, src){
                return profile.boxing().onContextmenu(profile, e, src)!==false;
            }
        },
        DataModel:{
            tag:'',
            tagVar:{
                ini:{}
            },
            disabled:{
                ini:false,
                action: function(v){
                    this.getRoot().css('opacity',v?0.5:1);
                }
            },
            dock:{
                ini:'none',
                listbox:['none','top','bottom','left','right','center','middle','origin','width','height','fill','cover'],
                action:function(v){
                    linb.UI.$dock(this,true,true);
                }
            },
            dockIgnore:{
                ini:false,
                action:function(v){
                    var self=this;
                    if(self.properties.dock!='none')
                        linb.UI.$dock(self,true,true);
                }
            },
            dockOrder:{
                ini: 1,
                action:function(v){
                    var self=this;
                    if(self.properties.dock!='none')
                        linb.UI.$dock(self,true,true);
                }
            },
            dockMargin:{
                ini:{left:0,top:0,right:0,bottom:0},
                action:function(v){
                    var self=this;
                    if(self.properties.dock!='none')
                        linb.UI.$dock(self,true,true);
                }
            },
            dockFloat:{
                ini:false,
                action:function(v){
                    var self=this;
                    if(self.properties.dock!='none')
                        linb.UI.$dock(self,true,true);
                }
            },
            dockMinW:0,
            dockMinH:0,
            tips:''
        },
        EventHandlers:{
            onRender:function(profile){},
            onLayout:function(profile){},
            onResize:function(profile,width,height){},
            onMove:function(profile,left,top,right,bottom){},
            onDock:function(profile,region){},
            beforePropertyChanged:function(profile,name,value,ovalue){},
            afterPropertyChanged:function(profile,name,value,ovalue){},
            beforeAppend:function(profile,child){},
            afterAppend:function(profile,child){},
            beforeRemove:function(profile,child,subId,bdestroy){},
            afterRemove:function(profile,child,subId,bdestroy){},
            onDestroy:function(profile){},
            beforeDestroy:function(profile){},
            onShowTips:function(profile, node, pos){},
            onContextmenu:function(profile, e, node){}
        },
        RenderTrigger:function(){
            var self=this, b=self.boxing(),p=self.properties;
            //avoid the resize blazzing
            if(self.box._onresize){
                var style=self.getRootNode().style,t
                if((t=style.visibility)!='hidden'){
                   self._$v=t;
                   style.visibility='hidden';
                }
                linb.UI.$tryResize(self,p.width,p.height);
                style=null;
            }

            if(p.disabled)
                b.setDisabled(true,true);

            self.inValid=1;
        },
        $doResize:function(profile,w,h,force,key){
            if(force || ((w||h) && (profile._resize_w!=w || profile._resize_h!=h))){
                //destroyed before resize
                if(!profile.getRootNode())return false;
                
                profile._resize_w=w;
                profile._resize_h=h;
                _.tryF(profile.box._onresize,[profile,w,h,force,key],profile.box);
            }
            //to prevent the functioin in $tryResize
            if(profile._$resizetimer){
                clearTimeout(profile._$resizetimer);
                delete profile._$resizetimer;
            }
        },
        $tryResize:function(profile,w,h,force,key){
            var s=profile.box,t=s._onresize;
            if(t&&(force||w||h)){
                //adjust width and height
                w=parseInt(w)||null;
                h=((h===""||h=='auto')?"auto":parseInt(h))||null;
                
                //if it it has delay resize, overwrite arguments
                if('_$v' in profile){
                    var args=profile.$rs_args;
                    if(!args){
                        args=profile.$rs_args=[profile,null,null];
                        profile._$resizetimer=_.asyRun(function(){
//for performance checking
//console.log('delay resize',profile.$rs_args);
                            //for refresh:
                            if(profile && profile.$rs_args)
                                if(false!==linb.UI.$doResize.apply(null,profile.$rs_args)){
                                    var style=profile.getRootNode().style;
                                    //some control will set visible to recover the css class
                                    if(style.visibility!='visible')
                                        style.visibility=profile._$v;
                                    delete profile.$rs_args;
                                    delete profile._$v;
                                    style=null;
                                }
                        });
                    }
                    //keep the last one, neglect zero and 'auto'
                    args[1]=w;
                    args[2]=h;
                    args[3]=force;
                    args[4]=key;
                //else, call resize right now
                }else{
//for performance checking
//console.log('resize',profile.$linbid,w,h,force,key);
                    linb.UI.$doResize(profile,w,h,force,key);
                }
            }
        },
        LayoutTrigger:function(){
            var self=this, b=self.boxing(),p=self.properties;
            if(p.dock && p.dock != 'none'){
                //first time, ensure _onresize to be executed.
                if(!self.$laidout){
                    self.$laidout=1;
                    var stl=self.getRootNode().style;
                    switch(p.dock){
                        case 'top':
                        case 'bottom':
                        case 'width':
                            stl.width=0;
                            break;
                        case 'left':
                        case 'right':
                        case 'height':
                            stl.height=0;
                            break;
                        default:
                            stl.width=stl.height=0;
                    }
                }
                linb.UI.$dock(this,false,true);
            }
        },
        $dock_args:['top','bottom','left','right','center','middle','width','height'],
        $dock_map:{middle:1,center:1},
        $dock:function(profile, force, trigger){
            var prop = profile.properties,
                margin=prop.dockMargin,
                node = profile.getRoot(),
                value = prop.dock || 'none',
                p= node.parent(),
                auto = 'auto',
                pid=linb.Event.getId(p.get(0)),
                order=function(x,y){
                    x=parseInt(x.properties.dockOrder)||0;y=parseInt(y.properties.dockOrder)||0;
                    return x>y?1:x==y?0:-1;
                },
                region,
                inMatrix='$inMatrix',
                f,t,isWin,
                //for ie6 1px bug
                _adjust=function(v){return linb.browser.ie6?v-v%2:v}

            if(p.get(0)===document.body){
                pid='!document';
                isWin=true;
            }

            //attached to matrix
            if(pid && (pid==linb.Dom._ghostDivId || _.str.startWith(pid,linb.Dom._emptyDivId)))
                return;

            if(profile.$dockParent!=pid || profile.$dockType != value || force){
                profile.$dockParent=pid;
                profile.$dockType = value;

                //unlink first
                profile.unLink('$dock');
                profile.unLink('$dock1');
                profile.unLink('$dock2');

                //set the fix value first
                switch(value){
                    case 'middle':
                        region={right:auto, bottom:auto,left:prop.left||'',width:prop.width||'',height:prop.height||''};
                        break;
                    case 'center':
                        region={right:auto, bottom:auto,top:prop.top||'',width:prop.width||'',height:prop.height||''};
                        break;
                    case 'origin':
                        region={right:auto, bottom:auto,width:prop.width||'',height:prop.height||''};
                        break;
                    case 'top':
                        region={left:margin.left, right:margin.right, bottom:auto, height:prop.height||''};
                        //width top
                        break;
                    case 'bottom':
                        region={left:margin.left, right:margin.right, top:auto, height:prop.height||''};
                        //width bottom
                        break;
                    case 'left':
                        region={right:auto,width:prop.width||''};
                        //height top left
                        break;
                    case 'right':
                        region={left:auto,width:prop.width||''};
                        //height top right
                        break;
                    case 'width':
                        region={bottom:auto,height:prop.height||'',top:prop.top||''};
                        //width left
                        break;
                    case 'height':
                        region={right:auto,width:prop.width||'',left:prop.left||''};
                        //height top
                        break;
                    case 'fill':
                    case 'cover':
                        region={right:auto,bottom:auto};
                        break;
                    case 'none':
                        region={left:prop.left, top:prop.top, width:prop.width||'',height:prop.height||''};
                        break;
                }
                node.cssRegion(region,true);
                //if in body, set to window
                if(isWin){
                    p=linb.win;
                    if(!linb.$cache._resizeTime)linb.$cache._resizeTime=1;
                }
                //set dynamic part
                if(value != 'none'){
                    f = p.$getEvent('onSize','dock');
                    if(!f){
                        f=function(arg){
                            //get self vars
                            var me=arguments.callee,
                                map=linb.UI.$dock_map,
                                arr=linb.UI.$dock_args,
                                rePos=me.rePos,
                                // the dock parent is window
                                win= me.pid=="!window" || me.pid=="!document",
                                node=win?linb.win:linb(me.pid),
                                style=node.get(0).style,
                                obj,i,k,o,key,target
                            ;
                            //window resize: check time span, for window resize in firefox
                            //force call when input $dockid
                            //any node resize
                            if( arg.$dockid || !win || (_() - linb.$cache._resizeTime > 100)){
                                //recruit call, give a short change
                                obj = {left:0,top:0,right:0,bottom:0,width:parseInt(style&&style.width)||node.width(),height:parseInt(style&&style.height)||node.height()};

                                for(k=0;key=arr[k++];){
                                    target = me[key];
                                    if(target.length){
                                        if(!map[key])arg.width=arg.height=1;
                                        for(i=0;o=target[i++];)
                                            if(!o.properties.dockIgnore)
                                                rePos(o, obj, key, arg.$dockid, win||arg.width, win||arg.height);

                                    }
                                }
                                if(obj.later){
                                    _.each(obj.later, function(o){
                                        var profile;
                                        //for safari
                                        try{
                                            o.node.cssRegion(o, true);
                                            
                                            if((profile=linb.UIProfile.getFromDom(o.node.get(0))) && profile.onDock){
                                                delete o.node;
                                                profile.boxing().onDock(profile,o);
                                            }
                                        }catch(e){
                                            _.asyRun(function(){
                                                o.width+=1;o.height+=1;
                                                o.node.cssRegion(o);
                                                o.width-=1;o.height-=1;
                                                o.node.cssRegion(o, true);
                                                
                                                if((profile=linb.UIProfile.getFromDom(o.node.get(0))) && profile.onDock){
                                                    delete o.node;
                                                    profile.boxing().onDock(profile,o);
                                                }
                                            })
                                        }
                                    });
                                }

                                //if window resize, keep the timestamp
                                if(win)
                                    linb.$cache._resizeTime = _();
                            }
                            me=node=style=null;
                        };
                        f.pid=pid;
                        _.arr.each(linb.UI.$dock_args,function(key){
                            f[key]=[];
                        });
                        f.rePos=function(profile, obj, value, id, w, h){
                            //if $dockid input, and not the specific node, return
                            var flag=false;
                            if(id && profile.$linbid!=id)flag=true;
                            var prop = profile.properties,
                                flt=prop.dockFloat,
                                margin = prop.dockMargin,
                                node = profile.getRoot(),
                                style = profile.getRootNode().style,
                                left, top, right, bottom,temp, other,
                                x = parseInt(prop._dockBorderWidth) || 0,
                                y = parseInt(prop._dockBorderHeight) || 0,
                                region={}
                                ;
                            //top/bottom/left/right must be set by order first
                            switch(value){
                                case 'middle':
                                    //use height() is ok
                                    node.top((obj.height - node.height())/2);
                                    break;
                                case 'center':
                                    node.left((obj.width - node.width())/2);
                                    break;
                                case 'top':
                                    if(!flag){
                                        left=margin.left;
                                        right=margin.right;
                                        top=(flt?0:obj.top)+margin.top;
                                        if(parseFloat(style.top)!=top)region.top=top;
                                        temp=obj.width - left - right - x;
                                        if(parseFloat(style.width)!=temp)region.width=_adjust(temp);
                                        if(!_.isEmpty(region)){
                                            node.cssRegion(region,true);
                                        }
                                    }

                                    if(!flt)
                                        obj.top += (node.offsetHeight() + margin.top + margin.bottom);
                                    break;
                                case 'bottom':
                                    if(!flag){
                                        left=margin.left;
                                        right=margin.right;
                                        bottom=(flt?0:obj.bottom)+margin.bottom;
                                        if(parseFloat(style.bottom)!=bottom)region.bottom=bottom;
                                        temp=obj.width - left - right - x;
                                        if(parseFloat(style.width)!=temp)region.width=_adjust(temp);
                                        if(!_.isEmpty(region))node.cssRegion(region,true);
                                    }
                                    if(!flt)
                                        obj.bottom += (node.offsetHeight() + margin.top + margin.bottom);
                                    break;
                                case 'left':
                                    if(!flag){
                                        left=(flt?0:obj.left)+margin.left;
                                        top=(flt?0:obj.top)+margin.top;
                                        bottom=(flt?0:obj.bottom)+margin.bottom;
                                        if(parseFloat(style.left)!=left)region.left=left;
                                        if(parseFloat(style.top)!=top)region.top=top;
                                        temp=obj.height - top - bottom - y;
                                        if(parseFloat(style.height)!=temp)region.height=_adjust(temp);
                                        if(!_.isEmpty(region))node.cssRegion(region,true);
                                    }
                                    if(!flt)
                                        obj.left += (node.offsetWidth() + margin.left + margin.right);
                                    break;
                                case 'right':
                                    //if no top/bottom and change w only
                                    if(!flag){
                                        right=(flt?0:obj.right)+margin.right;
                                        top=(flt?0:obj.top)+margin.top;
                                        bottom=(flt?0:obj.bottom)+margin.bottom;
                                        if(parseFloat(style.right)!=right)region.right=right;
                                        if(parseFloat(style.top)!=top)region.top=top;
                                        temp=obj.height - top - bottom - y;
                                        if(parseFloat(style.height)!=temp)region.height=_adjust(temp);
                                        if(!_.isEmpty(region))node.cssRegion(region,true);
                                    }
                                    if(!flt)
                                        obj.right += (node.offsetWidth() + margin.left + margin.right);
                                    break;
                                case 'width':
                                    //if no top/bottom/left/right and change h only
                                    if(!w)return;
                                    left = (prop.dock=='cover'?0:(flt?0:obj.left)) + margin.left;
                                    right = (prop.dock=='cover'?0:(flt?0:obj.right))  + margin.right;
                                    top = prop.dock=='width'?(parseInt(prop.top) || 0):( (prop.dock=='cover'?0:(flt?0:obj.top)) + margin.top);
                                    //later call for w/h change once
                                    temp=obj.width - left - right - x;
                                    obj.later=obj.later||{};
                                    obj.later[profile.$linbid] = obj.later[profile.$linbid] || {};
                                    _.merge(obj.later[profile.$linbid],{
                                        node:node,
                                        width: _adjust(prop.dockMinW?Math.max(prop.dockMinW,temp):temp),
                                        left:left,
                                        top:top
                                    },'all');
                                    break;
                                case 'height':
                                    //if no top/bottom/left/right and change w only
                                    if(!h)return;
                                    top = (prop.dock=='cover'?0:(flt?0:obj.top)) + margin.top;
                                    bottom = (prop.dock=='cover'?0:(flt?0:obj.bottom))  + margin.bottom;
                                    left = prop.dock=='height'?(parseInt(prop.left) || 0):((prop.dock=='cover'?0:(flt?0:obj.left))+ margin.left);
                                    //later call for w/h change once
                                    temp=obj.height - top - bottom - y;
                                    obj.later=obj.later||{};
                                    obj.later[profile.$linbid] = obj.later[profile.$linbid] || {};
                                    _.merge(obj.later[profile.$linbid],{
                                        node:node,
                                        height: _adjust(prop.dockMinH?Math.max(prop.dockMinH,temp):temp),
                                        left:left,
                                        top:top
                                    },'all');

                                    break;
                            }
                        };

                        //add handler to window or node
                        p.onSize(f,'dock');
                    }
                    //set link to node
                    if(value=='fill' || value=='cover'){
                        profile.link(f.height, '$dock1');
                        profile.link(f.width, '$dock2');
                        f.height.sort(order);
                        f.width.sort(order);
                    }else if(value=='origin'){
                        profile.link(f.center, '$dock1');
                        profile.link(f.middle, '$dock2');
                    }else{
                        profile.link(f[value], '$dock');
                        f[value].sort(order);
                    }

                    //
                    linb.$cache._resizeTime=1;

                    //set shortuct
                    profile.$dockFun=f;

                    if(isWin){
                        linb('html').addClass('linb-html');
                        if(t=linb('body').get(0))
                            t.scroll='no';
                    }
                }
            }
            //run once now
            if(value != 'none' && trigger)
                profile.$dockFun({width:1, height:1, $dockid:_.arr.indexOf(['width','height','fill','cover'],value)!=-1?profile.$linbid:null, $type: value});
        },

        _beforeSerialized:function(profile){
            var r=profile.boxing(),b,t,o={};
            _.merge(o, profile, 'all');
            var p = o.properties = _.copy(profile.properties);
            switch(p.dock){
                case 'top':
                case 'bottom':
                    delete p.width;delete p.left;delete p.top;delete p.right;delete p.bottom;
                    break;
                case 'left':
                case 'right':
                    delete p.height;delete p.left;delete p.top;delete p.right;delete p.bottom;
                    break;
                case 'width':
                    delete p.width;delete p.left;delete p.right;
                    break;
                case 'height':
                    delete p.height;delete p.top;delete p.bottom;
                    break;
                case 'fill':
                case 'cover':
                    delete p.width;delete p.height;delete p.left;delete p.top;delete p.right;delete p.bottom;
                    break;
            }
            for(var i in linb.UI.$ps)
                if((i in p) && typeof p[i]!='number' && p[i]!='' && p[i]!='auto')p[i]=isNaN(p[i]=parseFloat(p[i]))?'auto':p[i];

            if(p.items && p.items.length){
                t=linb.absObj.$specialChars;
                p.items = _.clone(p.items,function(o,i){return !t[(i+'').charAt(0)]&&o!=undefined});
            }
            if(_.isEmpty(p.tagVar))
                delete p.tagVar;
            if((t=p.dockMargin)&&!t.left&&!t.top&&!t.right&&!t.bottom)
                delete p.dockMargin;
            if(p.items&&(p.items.length==0||p.listKey))
                delete p.items;

            return o;
        },
        getDropKeys:function(profile,node){
            return profile.properties.dropKeys;
        },
        getDragKey:function(profile,node){
            return profile.properties.dragKey;
        },
        getDragData:function(profile,event,node){
            return {
                profile:profile,
                domId:linb.use(node).id(),
                data: profile.onGetDragData ? profile.boxing().onGetDragData(profile,event,node) : null
            };
        },
        _prepareData:function(profile, data){
            var prop = profile.properties,
                dm = this.$DataModel,
                me = arguments.callee,
                map = me.map || (me.map=_.toArr('left,top,bottom,right,width,height')),
                a=[],
                ajd=linb.UI.adjustData,
                t
                ;
            data = data||{};
            //can't input id in properties
            if(prop.id)delete prop.id;

            //give default caption
            if('caption' in dm && prop.caption!==null)
                prop.caption = prop.caption===undefined ? profile.alias : prop.caption;

            //give border width
            if('$hborder' in dm)
                data.bWidth=prop.width - (prop.$hborder||0)*2;
            if('$vborder' in dm)
                data.bHeight=prop.height - (prop.$vborder||0)*2;

            //set left,top,bottom,right,width,height,position,z-index,visibility,display
            for(var j=0,i;i=map[j];j++){
                if(prop[i] || prop[i]===0){
                    if(String(parseFloat(prop[i]))==String(prop[i]))
                        a[a.length]=i+':'+(parseInt(prop[i])||0)+'px';
                    else if(prop[i]!='auto' && prop[i])
                        a[a.length]=i+':'+prop[i];
                }
            }
            if(prop.position)a[a.length] = 'position:'+prop.position;
            if(prop.visibility)a[a.length]= 'visibility:'+prop.visibility;
            if(prop.zIndex)a[a.length]= 'z-index:'+prop.zIndex;
            if(prop.display)a[a.length]= 'display:'+ (prop.display=='inline-block'? linb.browser.gek?'-moz-inline-block;display:-moz-inline-box;display:inline-block;':'inline-block' :prop.display)

            data._style = ';'+a.join(';')+';';

            if('href' in dm)data.href = prop.href || linb.$href;
            if('tabindex' in dm)data.tabindex = prop.tabindex || '-1';
            if('items' in dm){
                profile.ItemIdMapSubSerialId = {};
                profile.SubSerialIdMapItem = {};
                
                prop.items=profile.box._adjustItems(prop.items);
                data.items = this._prepareItems(profile, prop.items);
            }

            //default prepare
            data =  ajd(profile, prop, data);

            profile.prepared=true;
            return data;
        },
        _prepareItems:function(profile, items, pid, mapCache, serialId){
            var result=[],
                item,dataItem,t,
                SubID=linb.UI.$tag_subId,id ,
                tabindex = profile.properties.tabindex,
                ajd=linb.UI.adjustData;
            //set map
            for(var i=0,l=items.length;i<l;i++){
                if(typeof items[i]!='object')
                    items[i]={id:items[i]};
                item=items[i];
                if(!item.hasOwnProperty('caption'))item.caption=item.id;

                dataItem={id: item.id};
                if(pid)dataItem._pid = pid;

                id=dataItem[SubID]=typeof serialId=='string'?serialId:profile.pickSubId('items');

                if(false!==mapCache){
                    profile.ItemIdMapSubSerialId[item.id] = id;
                    profile.SubSerialIdMapItem[id] = item;
                }
                if(t=item.object){
                    t=dataItem.object=t['linb.absBox']?t.get(0):t;
                    //relative it.
                    if(t['linb.UIProfile'])
                        t.properties.position='relative';
                    item.$linbid=t.$linbid;
                    t.$item=item;
                    t.$holder=profile;
                    if(!profile.$attached)profile.$attached=[];
                    profile.$attached.push(t);
                }else{
                    dataItem._tabindex=tabindex;
                    //others
                    ajd(profile, item, dataItem);
                    if(this._prepareItem)
                        this._prepareItem(profile, dataItem, item, pid, mapCache, serialId);
                }
                result.push(dataItem);
            }

            return result;
        },
        _showTips:function(profile, node, pos){
            if(profile.onShowTips)
                return profile.boxing().onShowTips(profile, node, pos);
        }
    }
});
//absList cls
Class("linb.absList", "linb.absObj",{
    Instance:{
        activate:function(){
            var profile = this.get(0),
                items = profile.getSubNode('ITEM',true);
            if(!items.isEmpty())
                items.focus();
            return this;
        },
        /*
        [x] ,valid id   ,true  => insert [x] before node
        [x] ,valid id   ,false => insert [x ]after node
        [x] ,null ,true  => insert [x ] to head
        [x] ,null ,false => insert [x ] to tail
        */
        insertItems:function(arr, base, before){
            var node,arr2,
                items, index, r,
                data,box,
                b=this._afterInsertItems;
            return this.each(function(profile){
                box=profile.box;

                arr2=box._adjustItems(arr);

                items = profile.properties.items;
                index = _.arr.subIndexOf(items,'id',base);

                //if in dom, create it now
                if(profile.renderId){
                    // prepare properties format
                    data = box._prepareItems(profile, arr2, base);

                    r=profile._buildItems('items', data);
                    if(index==-1){
                        //if no base specified
                        node = profile.getSubNode(box._ITEMSKEY || profile.keys.ITEMS || profile.keys.KEY);
                        //items.length==1 for that one have fake item(for example: editable poll)
                        if(before)
                            node.prepend(r);
                        else
                            node.append(r);
                    }else{
                        node=profile.getSubNodeByItemId(box._ITEMKEY || 'ITEM', base);
                        if(before)
                            node.addPrev(r);
                        else
                            node.addNext(r);
                    }
                }

                //must be here
                if(index==-1){
                    items.push.apply(items,arr2);
                }else
                    _.arr.insertAny(items,arr2, before?index:index+1);
                    
                    
                if(b)
                    profile.boxing()._afterInsertItems(profile, data, base, before);
            });
        },
        removeItems:function(arr, key){
            if(!(arr instanceof Array))arr=[arr];
            var obj,v,
                b=this._afterRemoveItems;
                remove=function(profile, arr, target, ns, force){
                    var self=arguments.callee;
                    if(!ns)ns=linb();
                    _.filter(arr,function(o){
                        var serialId,b;
                        if(force || (b=(_.arr.indexOf(target,o.id)!=-1))){
                            if(profile.renderId){
                                if(serialId=profile.ItemIdMapSubSerialId[o.id]){
                                    // clear maps
                                    delete profile.SubSerialIdMapItem[serialId];
                                    delete profile.ItemIdMapSubSerialId[o.id];
                                    profile.reclaimSubId(serialId, 'items');

                                    //parent node is deleted
                                    if(!force){
                                        if(!(obj = profile.getSubNode(profile.keys[key]?key:(profile.box._ITEMKEY||'ITEM'), serialId) ).isEmpty() )
                                            ns.merge(obj);
                                        //for inner template or linb.UI
                                        if(o.$linbid)ns.get().push(linb.getObject(o.$linbid).getRootNode());
                                    }
                                }
                            }
                        }
                        //check sub
                        if(o.sub)self(profile, o.sub, target, ns, force || b);
                        //filter it
                        if(b){
                            for(var i in o)o[i]=null;
                            return false;
                        }
                    });
                    ns.remove();
                };
            return this.each(function(profile){
                var p=profile.properties;
                // clear properties
                remove(profile, p.items, arr);
                // clear value
                if(v=p.$UIvalue){
                    if((v=v.split(';')).length>1){
                        _.filter(v,function(o){
                            return _.arr.indexOf(arr,o)==-1;
                        });
                        p.$UIvalue=v.join(';');
                    }else{
                        if(_.arr.indexOf(arr,p.$UIvalue)!=-1)
                            p.$UIvalue=null;
                    }
                }
                if(b && profile.renderId)
                    profile.boxing()._afterRemoveItems(profile, arr);
            });
        },
        clearItems:function(key){
            return this.each(function(profile){
                if(!profile.SubSerialIdMapItem)return;
                //empty dom
                profile.getSubNode(profile.keys[profile.box._ITEMKEY||'ITEM'], true).remove();
                //save subid
                _.each(profile.SubSerialIdMapItem, function(o,serialId){
                    profile.reclaimSubId(serialId, 'items');
                });
                //delete items
                profile.properties.items.length=0;
                //clear cache
                profile.SubSerialIdMapItem={};
                profile.ItemIdMapSubSerialId={};

                //keep the value
                //profile.properties.value=null;
            });
        },
        updateItem:function(subId,options){
            var self=this,
                profile=self.get(0),
                box=profile.box,
                items=profile.properties.items,
                rst=profile.queryItems(items,function(o){return typeof o=='object'?o.id===subId:o==subId},true,true,true),
                item,serialId,node,sub,t;
            if(typeof options!='object')options={caption:options+''};
            //ensure the original id
            delete options.id;

            if(rst.length){
                rst=rst[0];
                if(typeof rst[0]!='object')
                    item=rst[2][rst[1]]={id:rst[0]};
                else
                    item=rst[0];

                //merge options
                _.merge(item, options, 'all');

                //prepared already?
                serialId=_.get(profile,['ItemIdMapSubSerialId',subId]);
                arr=box._prepareItems(profile, [item],item._pid,false, serialId);

                //in dom already?
                node=profile.getSubNodeByItemId('ITEM',subId);
                if(!node.isEmpty()){
                    //for the sub node
                    if(options.sub){
                        delete item._created;
                        delete item._checked;
                    }else if(item.sub){
                        sub=profile.getSubNodeByItemId('SUB',subId);
                    }
                    node.replace(profile._buildItems(arguments[2]||'items',arr),false);
                    //keep sub
                    if(sub && !sub.isEmpty()){
                        if(!(t=profile.getSubNodeByItemId('SUB',subId)).isEmpty())
                            t.replace(sub);
                    }
                }
            }
            return self;
        },
        getItems:function(type){
            var v=this.get(0).properties.items;
            if(type=='data')
                return _.clone(v,true);
            else if(type=='min'){
                var a=_.clone(v,true),b;
                _.arr.each(a,function(o,i){
                    a[i]=o.id;
                });
                return a;
            }else
                return v;
        },
        fireItemClickEvent:function(subId){
            this.getSubNodeByItemId('ITEM', subId).onClick();
            return this;
        }

    },
    Initialize:function(){
        var o=this.prototype;
        _.arr.each(_.toArr('getItemByItemId,getItemByDom,getSubIdByItemId,getSubNodeByItemId'),function(s){
            o[s]=function(){
                var t=this.get(0);
                return t[s].apply(t,arguments);
            };
            Class._fun(o[s],s,o.KEY);
        });
    },
    Static:{
        $abstract:true,
        DataModel:{
            listKey:{
                set:function(value){
                    var o=this,
                        t = o.box.getCachedData(value);
                    if(t)
                        o.boxing().setItems(t);
                    else
                        o.boxing().setItems(o.properties.items);
                    o.properties.listKey = value; 
                }
            },
            items:{
                ini:[],
                set:function(value){
                    var o=this;
                    if(o.renderId)
                        o.boxing().clearItems().insertItems(value);
                    else
                        o.properties.items = _.copy(value);
                }
            }
        },
        RenderTrigger:function(){
            this.destroyTrigger=function(){
                _.each(this.SubSerialIdMapItem,function(o){
                    _.breakO(o)
                });
                this.properties.items.length=0;
            };
        },
        _adjustItems:function(arr){
            if(!arr)arr=[_()+''];
            if(_.isStr(arr))arr=[arr];

            var a=_.copy(arr),m;
            _.arr.each(a,function(o,i){
                if(typeof o!= 'object')
                    a[i]={id:o+''};
                else{
                    a[i]=_.copy(o);
                    a[i].id=a[i].id?(a[i].id+''):_.id();
                }
            });
            return a;
        },
        //
        _showTips:function(profile, node, pos){
            if(profile.onShowTips)
                return profile.boxing().onShowTips(profile, node, pos);
            if(!linb.Tips)return;

            var t=profile.properties,
                id=node.id,
                sid=profile.getSubId(id),
                map=profile.SubSerialIdMapItem,
                item=map&&map[sid];

            if(t.disabled)return;
            if(item && item.disabled)return;
            if(item && item.tips){
                linb.Tips.show(pos, item);
                return true;
            }else
                return false;
        }
    }
});

Class("linb.absValue", "linb.absObj",{
    Instance:{
        /*
        getUIValue:         return $UIvalue
        setUIValue:         set $UIvalue,and _setCtrlValue                   beforeUIValueSet/afterUIValueSet
        getValue:           return value
        setValue:           set value, set $UIvalue, and _setCtrlValue       beforeValueSet/afterValueSet
        resetValue:         reset value,UIvalue,Ctrlvalue not trigger event
        updateValue:        set $UIvalue to value

        _setCtrlValue:      change control value                *need to be overwritten
        _getCtrlValue:      get value from control              *need to be overwritten
        _setDirtyMark:      mark UI ctrl when value!==UIvalue   *need to be overwritten
        */
        _getCtrlValue:function(){return this.get(0).properties.$UIvalue},
        _setCtrlValue:function(value){return this},
        _setDirtyMark:function(){return this},

        getValue:function(){return this.get(0).properties.value},
        getUIValue:function(){return this.get(0).properties.$UIvalue=this._getCtrlValue()},
        resetValue:function(value){
            var self=this;
            self.each(function(profile){
                var r;
                if(typeof (r=profile.box._ensureValue)=='function')
                    value = r.call(profile.box, profile, value);
                profile.boxing()._setCtrlValue(profile.properties.$UIvalue = profile.properties.value = value);
                if(typeof(r=profile.$onValueSet)=='function')r.call(profile,value);
                profile.inValid=1;
            });
            self._setDirtyMark();
            return self;
        },
        setUIValue:function(value, force){
            var self=this;
            this.each(function(profile){
                var prop=profile.properties, r,
                    ovalue = prop.$UIvalue,
                    box = profile.boxing();
                if(ovalue !== value || force){
                    if(
                        false===profile.box._checkValid(profile, value) ||
                        (profile.beforeUIValueSet && false===(r=box.beforeUIValueSet(profile, ovalue, value)))
                      )
                        return;
                    //can get return value
                    if(r!==undefined)value=r;
                    //before _setCtrlValue
                    if(typeof (r=profile.box._ensureValue)=='function')
                        value = r.call(profile.box, profile, value);
                    if(typeof(r=profile.$onValueUpdated)=='function')r.call(profile,value);
                    //before value copy
                    if(profile.renderId)box._setCtrlValue(value);
                    //value copy
                    prop.$UIvalue = value;

                    if(profile.renderId)box._setDirtyMark();
                    if(profile.afterUIValueSet)box.afterUIValueSet(profile, ovalue, value);
                }
            });
            return this;
        },
        updateValue:function(){
            this.each(function(profile){
                var prop = profile.properties,ins=profile.boxing();
                if(ins.checkValid())
                    prop.value = ins.getUIValue();
            });
            return this._setDirtyMark();
        },
        isDirtied:function(){
            var p = this.get(0).properties;
            return p.value !== p.$UIvalue;
        },
        checkValid:function(){
            var r=true;
            this.each(function(profile){
                var prop=profile.properties;
                //r must be at the end
                r = profile.box._checkValid(profile, prop.$UIvalue) && r;
                if(profile.renderId)
                    profile.boxing()._setDirtyMark();
            });
            return r;
        }
    },
    Static:{
        $abstract:true,
        DataModel:{
            dataBinder:{
                combobox:function(){
                    return _.toArr(linb.DataBinder._pool,true);
                },
                set:function(value,ovalue){
                    var profile=this,
                        p=profile.properties;
                    if(ovalue)
                        linb.DataBinder._unBind(ovalue, profile);
                    p.dataBinder=value;
                    linb.DataBinder._bind(value, profile);
                }
            },
            dataField:'',

            // setValue and getValue
            value:{
                ini:null,
                set:function(value){
                    var profile=this,
                        p=profile.properties,r,
                        ovalue = p.value,
                        box=profile.boxing(),
                        nv=value;

                    //check format
                    if(profile.box._checkValid(profile, nv)===false)return;
                    //if return false in beforeValueSet, not set
                    if(profile.beforeValueSet && false=== (r=box.beforeValueSet(profile, ovalue, nv)))return;
                    // can get return value
                    if(r!==undefined)nv=r;
                    //before _setCtrlValue
                    //ensure value
                    if(typeof (r=profile.box._ensureValue)=='function')
                        nv = r.call(profile.box, profile, nv);
                    if(typeof(r=profile.$onValueSet)=='function')r.call(profile,nv);
                    //before value copy
                    if(profile.renderId)box._setCtrlValue(nv);
                    //value copy
                    p.value = p.$UIvalue = nv;

                    profile.inValid=1;
                    if(profile.renderId)box._setDirtyMark();
                    if(profile.afterValueSet)box.afterValueSet(profile, ovalue, nv);
                }
            },
            dirtyMark:true
        },
        EventHandlers:{
           //$onValueSet
            beforeValueSet:function(profile, oldValue, newValue){},
            afterValueSet:function(profile, oldValue, newValue){},
            //$onValueUpdated
            beforeUIValueSet:function(profile, oldValue, newValue){},
            afterUIValueSet:function(profile, oldValue, newValue){},

            beforeDirtyMark:function(profile, dirty){}
        },
        RenderTrigger:function(){
            var self=this, b=self.boxing(),p=self.properties,t,value;
            p.$UIvalue = p.value;
            if(p.value !==undefined){
                value=p.value;
                if(typeof (t=self.box._ensureValue)=='function')
                    value = t.call(self.box, self, value);
                b._setCtrlValue(value);
            }

            if(t=p.dataBinder)b.setDataBinder(t,true);
            if(t=p.dataField)b.setDataField(t);
        },
        _checkValid:function(profile, value){
            return true;
        }
    }
});

//som base widgets Classes
new function(){
    var u='linb.UI';
    //Widget cls
    Class(u+".Widget", u,{
        Static:{
            Appearances:{
                KEY:{
                    'font-size':linb.browser.ie?0:null,
                    'line-height':linb.browser.ie?0:null
                }
            },
            Templates:{
                className:'uiw-shell ',
                style:'{_style}',
                FRAME:{
                    className:'uiw-frame ',
                    BORDER:{
                        style:'width:{bWidth}px;height:{bHeight}px;',
                        className:'uiw-border'
                    }
                }
            },
            Behaviors:{
                KeyHook:true,
                onSize:linb.UI.$onSize
            },
            DataModel:{
                width:100,
                height:100,
                //hide props
                $hborder:0,
                $vborder:0
            },
            RenderTrigger:function(){
                var self=this, p=self.properties, o=self.boxing();

                if(self.renderId)
                    if((!self.$noB) && p.border && o._border)o._border();

                if((!self.$noR) && p.resizer && o.setResizer)
                    o.setResizer(p.resizer,true);
                if((!self.$noS) && p.shadow && o._shadow)
                    o._shadow();
            },
            _onresize:function(profile,width,height){
                var t = profile.properties,
                    o = profile.getSubNode('BORDER'),
                    region,
                    ww=width,
                    hh=height,
                    left=Math.max(0, (t.$b_lw||0)-(t.$hborder||0)),
                    top=Math.max(0, (t.$b_tw||0)-(t.$vborder||0));
                if(ww&&'auto'!==ww){
                    ww -= Math.max((t.$hborder||0)*2, (t.$b_lw||0)+(t.$b_rw||0));
                    /*for ie6 bug*/
                    /*for example, if single number, 100% width will add 1*/
                    /*for example, if single number, attached shadow will overlap*/
                    if(linb.browser.ie6)ww=(parseInt(ww/2))*2;
                }
                if(hh&&'auto'!==hh){
                    hh -=Math.max((t.$vborder||0)*2, (t.$b_lw||0) + (t.$b_rw||0));

                    if(linb.browser.ie6)hh=(parseInt(hh/2))*2;
                    /*for ie6 bug*/
                    if(linb.browser.ie6&&null===width)o.ieRemedy();
                }
                region={left:left,top:top,width:ww,height:hh};
                o.cssRegion(region);

                /*for ie6 bug*/
                if((profile.$border||profile.$shadow||profile.$resizer) && linb.browser.ie)o.ieRemedy();

                return region;
            }
        }
    });
    Class(u+".Link", u,{
        Static:{
            Appearances:{
                KEY:{
                   'font-size':linb.browser.ie?'12px':null,
                   'line-height':linb.browser.ie?'14px':null
                }
            },
            Templates:{
                tagName:'a',
                style: '{_style}',
                href :"{href}",
                target:'{target}',
                tabindex: '{tabindex}',
                text:'{caption}'
            },
            Behaviors:{
                onClick:function(profile, e, src){
                    var r;
                    if(!profile.properties.disabled && profile.onClick)
                        r = profile.boxing().onClick(profile, e, src);
                    //**** if dont return false, this click will break sajax in IE
                    //**** In IE, click a fake(javascript: or #) href(onclick not return false) will break the current script downloading
                    var href=linb.use(src).attr('href');
                    return typeof r=='boolean'?r:(href.indexOf('javascript:')===0||href.indexOf('#')===0)?false:true;
                }
            },
            DataModel:{
                caption:{
                    ini:undefined,
                    action:function(v){
                        this.getRoot().html(v);
                    }
                },
                href:{
                    ini:linb.$href,
                    action:function(v){
                        this.getRoot().attr('href',v);
                    }
                },
                target:{
                    action:function(v){
                        this.getRoot().attr('target',v);
                    }
                }
            },
            EventHandlers:{
                onClick:function(profile, e){}
            }
        }
    });
    Class(u+".SLabel", u,{
        Static:{
            Templates:{
                style:'{_style}text-align:{hAlign}',
                text:'{caption}'
            },
            Appearances:{
                KEY:{
                   'padding-right':'6px'
                }
            },
            DataModel:{
                tabindex:null,
                caption:{
                    ini:undefined,
                    action: function(value){
                        this.getRoot().html(value);
                    }
                },
                hAlign:{
                    ini:'right',
                    listbox:['left','center','right'],
                    action: function(v){
                        this.getRoot().css('textAlign',v);
                    }
                }
            }
        }
    });
    Class(u+".SButton", u,{
        Instance:{
            activate:function(){
                this.getSubNode('FOCUS').focus();
                return this;
            }
        },
        Static:{
            Templates:{
                className:'{_clsName}',
                style:'{_style}',
                BTN:{
                    className:'ui-btn',
                    BTNI:{
                        className:'ui-btni',
                        BTNC:{
                            className:'ui-btnc',
                            FOCUS:{
                                tagName:'a',
                                tabindex: '{tabindex}',
                                href:linb.$href,
                                style:"{_align}",
                                text:'{caption}'
                            }
                        }
                    }
                }
            },
            Appearances:{
                BTN:{
                    overflow:'hidden'
                },
                'KEY-auto BTN, KEY-auto BTNI, KEY-auto BTNC, KEY-auto FOCUS':{
                    $order:1,
                    display:linb.$inlineBlock
                },
                'BTN,BTNI,BTNC':{
                    display:'block'
                },
                'KEY FOCUS':{
                    cursor:'default',
                    'font-size':'12px',
                    'line-height':'14px',
                    'text-align':'center',
                    display:'block'
                }
            },
            Behaviors:{
                HoverEffected:{BTN:['BTN']},
                ClickEffected:{BTN:['BTN']},
                NavKeys:{FOCUS:1},
                onClick:function(profile, e, src){
                    var p=profile.properties;
                    if(p.disabled)return false;
                    profile.getSubNode('FOCUS').focus();
                    if(profile.onClick)
                        profile.boxing().onClick(profile, e, src);
                }
            },
            DataModel:{
/*custom property test for UIDesigner
                test:{
                    ini:1,
                    custom:function(p,k,v,submit){
                        console.log(p,k,v);
                        _.asyRun(function(){
                            submit(++v);
                        });
                    }
                },
*/
                caption:{
                    ini:undefined,
                    action: function(value){
                        this.getSubNode('FOCUS').html(value);
                    }
                },
                hAlign:{
                    ini:'center',
                    listbox:['left','center','right'],
                    action: function(v){
                        this.getSubNode('FOCUS').css('textAlign',v);
                    }
                },
                width:{
                    ini:'auto',
                    action:function(value){
                        if(value=='auto'){
                            this.getRoot().width('auto').tagClass('-auto');
                        }else
                            this.getRoot().width(value).tagClass('-auto',false);
                    }
                },
                height:{
                    readonly:true
                }
            },
            EventHandlers:{
                onClick:function(profile, e, src, value){}
            },
            _prepareData:function(profile){
                var data=arguments.callee.upper.call(this, profile);
                data._align = 'text-align:'+data.hAlign+';';
                data._clsName=parseInt(data.width)?'':profile.getClass('KEY','-auto');
                return data;
            }
        }
    });
    Class(u+".SCheckBox", [u,"linb.absValue"],{
        Instance:{
            activate:function(){
                this.getSubNode('FOCUS').focus();
                return this;
            },
            _setCtrlValue:function(value){
                return this.each(function(profile){
                   profile.getSubNode('MARK').tagClass('-checked', !!value);
                });
            },
            //update UI face
            _setDirtyMark:function(){
                return this.each(function(profile){
                    if(!profile.properties.dirtyMark)return;
                    if(!profile.renderId)return;
                    var properties = profile.properties,
                        o=profile.getSubNode('CAPTION'),
                        flag=properties.value !== properties.$UIvalue,
                        d = linb.UI.$css_tag_dirty;

                    if(o.beforeDirtyMark && false===o.boxing().beforeDirtyMark(profile,flag))
                        return;

                    if(flag)
                        o.addClass(d);
                    else
                        o.removeClass(d);
                });
            }
        },
        Static:{
            Templates:{
                className:'{_clsName}',
                style:'{_style}',
                FOCUS:{
                    tagName:'a',
                    tabindex: '{tabindex}',
                    href:linb.$href,
                    MARK:{
                        className:'uicmd-check'
                    },
                    CAPTION:{
                        $order:1,
                        text:'{caption}'
                    }
                }
            },
            Appearances:{
                KEY:{
                    overflow:'visible'
                },
                FOCUS:{
                    cursor:'default',
                    'vertical-align':'middle',
                    padding:'2px 0',
                    'font-size':'12px',
                    'line-height':'14px'
                },
                CAPTION:{
                    'vertical-align': 'middle'
                }
            },
            Behaviors:{
                HoverEffected:{KEY:'MARK'},
                ClickEffected:{KEY:'MARK'},
                NavKeys:{FOCUS:1},
                onClick:function(profile, e, src){
                    var p=profile.properties,b=profile.boxing();
                    if(p.disabled)return false;
                    b.setUIValue(!p.$UIvalue);
                    if(profile.onChecked)b.onChecked(profile, e, p.$UIvalue);
                    profile.getSubNode('FOCUS').focus();
                },
                FOCUS:{
                    onKeydown:function(profile, e, src){
                        var key = linb.Event.getKey(e)[0];
                        if(key ==' ' || key=='enter'){
                            profile.getRoot().onClick(true);
                            return false;
                        }
                    }
                }
            },
            DataModel:{
                value:false,
                caption:{
                    ini:undefined,
                    action: function(value){
                        this.getSubNode('CAPTION').html(value);
                    }
                }
            },
            EventHandlers:{
                onChecked:function(profile, e, value){}
            },
            _ensureValue:function(profile, value){
                return !!value;
            }
        }
    });
    Class(u+".Div", u,{
        Static:{
            Appearances:{
                KEY:{
                   // overflow:(linb.browser.gek && !linb.browser.gek3)?'auto':null,
                    outline:linb.browser.gek?'none':null,
                    zoom:linb.browser.ie6?'1':null,
                    background:linb.browser.ie?'url('+linb.ini.file_bg+') no-repeat left top':null
                }
            },
            Templates:{
                tagName:'div',
                style:'{_style}',
                //for firefox div focus bug: outline:none; tabindex:'-1'
                tabindex:'-1',
                text:'{html}'+linb.UI.$childTag
            },
            DataModel:{
                disabled:null,
                width:'100',
                height:'100',
                html:{
                    action:function(v){
                        this.getRoot().html(v);
                    }
                }
            }
        }
    });
    Class(u+".Tag", u+".Div",{
        Static:{
            Templates:{
                tagName:'div',
                style:'overflow:auto;border:dashed blue 1px;text-align:center;background:#EBEADB;{_style}',
                text:'{tagKey}'+linb.UI.$childTag
            },
            DataModel:{
                html:null,
                tagKey:{
                    action:function(v){
                        this.getRoot().html(v);
                    }
                }
            },
            _l:_.toArr('left,top,bottom,right,width,height,zIndex,tabindex,position,dock,dockFloat,dockMinW,dockMinH,dockOrder,dockMargin'),
            //replace tag profile with other UI profile
            replace:function(tagProfile, profile, com){
                //reset properties
                _.arr.each(this._l,function(s){
                    if(s in tagProfile.properties)profile.properties[s]=tagProfile.properties[s];
                });
                _.merge(profile.CS,tagProfile.CS,'all');
                _.merge(profile.CC,tagProfile.CC,'all');

                //if parent exist, replace
                if(tagProfile.parent){
                    //get tag link
                    var clink = tagProfile.parent.children,
                        linkObj = clink['$'+tagProfile.$linbid],
                        index = _.arr.indexOf(clink,linkObj);
                    tagProfile.parent.boxing().append(profile, linkObj[1]);
                    // set to tag index
                    clink[index] = clink.pop();

                    //detach tag from parent
                    tagProfile.unLink('$parent');
                    delete tagProfile.parent;
                //for _nodes in com
                }else if(com){
                    _.arr.each(com._nodes,function(o,i){
                        if(o===tagProfile){
                            com._nodes[i]=profile;
                            return false;
                        }
                    });
                }

                if(tagProfile.renderId)
                    profile.boxing().renderOnto(tagProfile.getRootNode());
            }
        }
    });
    Class(u+".Pane", u+".Div",{
        Static:{
            Behaviors:{
                DropableKeys:['KEY']
            }
        }
    });
};Class("linb.UI.Image", "linb.UI",{
    Instance:{
        getRate:function(){
            return parseFloat(this.get(0)._rate) || 1;
        }
    },
    Static:{
        Templates:{
            tagName:'image',
            style:'{_style}',
            border:"0",
            width:"{width}",
            height:"{height}"
        },
        Behaviors:{
            HoverEffected:{KEY:'KEY'},
            ClickEffected:{KEY:'KEY'},
            DragableKeys:["KEY"],
            onError:function(profile, e, src){
                profile.boxing().onError(profile);
            },
            onLoad:function(profile, e, src){
                var i=new Image(), path=i.src=linb.use(src).get(0).src,
                    size=profile.box._adjust(profile,i.width,i.height);
                profile.boxing().afterLoad(profile, path, size[0], size[1]);
            }
        },
        RenderTrigger:function(){
            var self=this, pro=self.properties, v=pro.src;
            if(v){
                pro.value=pro.$UIvalue='';
                self.boxing().setSrc(v,true);
            }
        },
        EventHandlers:{
            onError:function(profile){},
            beforeLoad:function(profile){},
            afterLoad:function(profile, path, width, height){}
        },
        _adjust:function(profile,width,height){
            var pro=profile.properties,
                src=profile.getRootNode();

            if(width>0 && height>0){
                var r1=pro.maxWidth/width, r2=pro.maxHeight/height,r= r1<r2?r1:r2;
                if(r>=1)r=1;
                profile._rate=r;
                src.width=width*r;
                src.height=height*r;
                return [width*r, height*r];
            }
            return [0,0];
        },
        DataModel:{
            maxWidth:{
                ini:800,
                action:function(v){
                    var src=this.getRootNode();
                    this.box._adjust(this,src.width,src.height);
                }
            },
            maxHeight:{
                ini:600,
                action:function(v){
                    var src=this.getRootNode();
                    this.box._adjust(this,src.width,src.height);
                }
            },
            width:{
                ini:'',
                action:function(v){
                    var src=this.getRootNode();
                    src.width=v;
                }
            },
            height:{
                ini:'',
                action:function(v){
                    var src=this.getRootNode();
                    src.height=v;
                }
            },

            src:{
                //use asyn mode
                action:function(v){
                    var self=this;
                    if(false!==self.boxing().beforeLoad(this))
                        _.asyRun(function(){self.getRoot().attr({width:'0',height:'0',src:v})});
                }
            }
        }
    }
});//add/get/remove border to a dom node(display:block;position:absolute) / or a widget inherite from linb.UI.Widget
Class("linb.UI.Border","linb.UI",{
    Instance:{
        _attachTo:function(target, eventTrigger){
            var self=this, v=self.get(0), t;
            //add to dom
            target.append(self);
            //save id
            v.$edgeId = linb(target).id();
            v.$tieId = eventTrigger;
            v.$attached=true;
            //add event
            if(t=v.properties)
                if(v.properties.borderActive){
                    var tag='tag', n=v.domId;
                    if(linb(eventTrigger).get(0))
                        linb(eventTrigger).afterMouseover(function(p,e){
                            if(p.properties.disabled)return;
                            var profile=linb.$cache.profileMap[n];
                            _.tryF(profile.behavior.TAG.afterMouseover,[profile,e,profile.getRootNode()],this);
                        },tag).afterMouseout(function(p,e){
                            if(p.properties.disabled)return;
                            var profile=linb.$cache.profileMap[n];
                            _.tryF(profile.behavior.TAG.afterMouseout,[profile,e,profile.getRootNode()],this);
                        },tag).afterMousedown(function(p,e){
                            if(p.properties.disabled)return;
                            var profile=linb.$cache.profileMap[n];
                            _.tryF(profile.behavior.TAG.afterMousedown,[profile,e,profile.getRootNode()],this);
                        },tag).afterMouseup(function(p,e){
                            if(p.properties.disabled)return;
                            var profile=linb.$cache.profileMap[n];
                            _.tryF(profile.behavior.TAG.afterMouseup,[profile,e,profile.getRootNode()],this);
                        },tag);
                }
            return target;
        },
        _detach:function(){
            var self=this, v=self.get(0),n,t,nl=null,tag='tag';
            delete v.$attached;
            if(n=v.$tieId)
                if(n=linb.Dom.byId(n))
                    linb(n).afterMouseover(nl,tag).afterMouseout(nl,tag).afterMousedown(nl,tag).afterMouseup(nl,tag);
            return self;
        }
    },
    Initialize:function(){

        //for linb.Dom
        _.each({
            addBorder :function(properties){
                var target = linb([this.get(0)]), eventTrigger=arguments[1]||target.id();
                return new linb.UI.Border(properties)._attachTo(target, eventTrigger);
            },
            $getBorder:function(){
                var s = this.id(), b;
                _.arr.each(linb.UI.Border._cache,function(o){
                    if(o.$edgeId==s){b=o;return false;}
                });
                return b && b.boxing();
            },
            removeBorder:function(){
                var s = this.id();
                _.arr.each(linb.UI.Border._cache,function(o){
                    if(o.$edgeId==s)
                        o.boxing()._detach().destroy();
                });
                return this;
            }
        },function(o,i){
            linb.Dom.plugIn(i,o);
        });
        //for linb.UI.Widget
        _.each({
            _border:function(properties,flag){
                return this.each(function(o){
                    var t=o.properties,target = o.getSubNode(t._customBorder||'BORDER'),k;

                    if(!properties)properties={};

                    if(t._customBorder)
                        k=(properties._bkey=o.getClass('KEY'));
                    else k='linb-border';
                        
                    var key='setting-'+k, sk;
                    sk='borderLeftWidth';
                    t.$b_lw=linb.UI.$getCSSValue(key,sk);
                    sk='borderRightWidth';
                    t.$b_rw=linb.UI.$getCSSValue(key,sk);
                    sk='borderTopWidth';
                    t.$b_tw=linb.UI.$getCSSValue(key,sk);
                    sk='borderBottomWidth';
                    t.$b_bw=linb.UI.$getCSSValue(key,sk);

                    if(flag!==false){
                        if(target.$getBorder())return;
                        o.$border=target.addBorder(properties);
                        o.clearCache().boxing().reLayout();
                    }
                });
            },
            _unBorder:function(){
                return this.each(function(o){
                    var target = o.getSubNode('BORDER'),t=o.properties;
                    if(!target.$getBorder())return;
                    target.removeBorder()

                    delete o.$border;

                    delete t.$b_lw;
                    delete t.$b_rw;
                    delete t.$b_tw;
                    delete t.$b_bw;
                    o.clearCache().boxing().reLayout();
                });
            }
        },function(o,i){
            linb.UI.Widget.plugIn(i,o);
        });
        linb.UI.Widget.setDataModel({
            border:{
                ini:false,
                action: function(v){
                    var b=this.boxing();
                    if(v)
                        b._border();
                    else
                        b._unBorder();
                }
            }
        });
    },
    Static:{
        Templates:{
            tagName:'div',
            TAG:{},
            T:{className:'{cls_t}'},
            RT:{className:'{cls_rt}',$order:1},
            R:{className:'{cls_r}'},
            RB:{className:'{cls_rb}',$order:1},
            B:{className:'{cls_b}'},
            LB:{className:'{cls_lb}',$order:1},
            L:{className:'{cls_l}'},
            LT:{className:'{cls_lt}',$order:1}
        },
        Appearances:{
            KEY:{
                //don't use width/height to trigger hasLayout in IE6
                width:0,
                height:0,
                _display:'inline',
                'font-size':0,
                'line-height':0
            },
            'TAG,T, RT, R, RB, B, LB, L, LT':{
                position:'absolute',
                display:'block',
                'font-size':0,
                'line-height':0
            },
            '.setting-linb-border':{
                'border-style':'solid',
                'border-top-width':'1px',
                'border-bottom-width':'1px',
                'border-left-width':'1px',
                'border-right-width':'1px'
            },
            T:{
                width:'100%',
                left:0,
                top:'-1px',
                height:'3px',
                background: linb.UI.$bg('vertical.gif', 'repeat-x left top')
            },
            B:{
                width:'100%',
                left:0,
                bottom:'-1px',
                height:'3px',
                background: linb.UI.$bg('vertical.gif', 'repeat-x left bottom')
            },
            L:{
                height:'100%',
                top:0,
                left:'-1px',
                width:'3px',
                background: linb.UI.$bg('horizontal.gif', 'repeat-y left top')
            },
            R:{
               height:'100%',
               top:0,
               right:'-1px',
               width:'3px',
               background: linb.UI.$bg('horizontal.gif', 'repeat-y right top')
            },
            LT:{
                top:'-1px',
                left:'-1px',
                width:'3px',
                height:'3px',
                background: linb.UI.$bg('corner.gif', 'no-repeat left top')
            },
            RT:{
               top:'-1px',
               right:'-1px',
               width:'3px',
               height:'3px',
               background: linb.UI.$bg('corner.gif', 'no-repeat right top')
            },
            RB:{
                right:'-1px',
                bottom:'-1px',
                width:'3px',
                height:'3px',
                background: linb.UI.$bg('corner.gif', 'no-repeat right bottom')
            },
            LB:{
                left:'-1px',
                bottom:'-1px',
                width:'3px',
                height:'3px',
                background: linb.UI.$bg('corner.gif', 'no-repeat left bottom')
            }/*,
            'KEY-mouseover T, KEY-mouseover B':{
                $order:1,
                'background-image':linb.UI.$bg('vertical_mouseover.gif')
            },
            'KEY-checked T, KEY-checked B, KEY-mousedown T, KEY-mousedown B':{
                $order:2,
                'background-image':linb.UI.$bg('vertical_mousedown.gif')
            },
            'KEY-mouseover L, KEY-mouseover R':{
                $order:1,
                'background-image': linb.UI.$bg('horizontal_mouseover.gif')
            },
            'KEY-checked L, KEY-checked R, KEY-mousedown L, KEY-mousedown R':{
                $order:2,
                'background-image': linb.UI.$bg('horizontal_mousedown.gif')
            },
            'KEY-mouseover LT, KEY-mouseover RT, KEY-mouseover RB, KEY-mouseover LB':{
                $order:1,
                'background-image': linb.UI.$bg('corner_mouseover.gif')
            },
            'KEY-checked LT, KEY-checked RT, KEY-checked RB, KEY-checked LB, KEY-mousedown LT, KEY-mousedown RT, KEY-mousedown RB, KEY-mousedown LB':{
                $order:2,
                'background-image': linb.UI.$bg('corner_mousedown.gif')
            }*/
        },
        Behaviors:{
            HoverEffected:{TAG:'KEY'},
            ClickEffected:{TAG:'KEY'}
        },
        DataModel:{
            _bkey:"",
            borderActive:false
        },
        _prepareData:function(profile){
            var data = arguments.callee.upper.call(this, profile),
                pk=profile.properties._bkey;

            data.cls_t = pk?pk+"-b-t":"";
            data.cls_rt = pk?pk+"-b-rt":"";
            data.cls_r = pk?pk+"-b-r":"";
            data.cls_rb = pk?pk+"-b-rb":"";
            data.cls_b = pk?pk+"-b-b":"";
            data.cls_lb = pk?pk+"-b-lb":"";
            data.cls_l = pk?pk+"-b-l":"";
            data.cls_lt = pk?pk+"-b-lt":"";

            return data;
        }
    }
});//shadow class, add a plugin to linb.Dom
Class("linb.UI.Shadow","linb.UI",{
    Instance:{
        _attachTo:function(obj){
            //to linb.Dom
            obj=obj.reBoxing();
            var self=this;
            //set target first
            self.get(0)._target=obj.get(0);
            // add dom for dom node
            obj.append(self);
            return obj;
        }
    },
    Initialize:function(){
        //for linb.Dom
        _.each({
            addShadow :function(properties){
                return new linb.UI.Shadow(properties)._attachTo(linb([this.get(0)]));
            },
            $getShadow:function(){
                var s=this.get(0),b;
                _.arr.each(linb.UI.Shadow._cache,function(o){
                    if(o._target==s){b=o;return false;}
                });
                return b && b.boxing();
            },
            removeShadow:function(){
                var s = this.get();
                _.arr.each(linb.UI.Shadow._cache,function(o){
                    if(_.arr.indexOf(s,linb(o._target).get(0))!=-1)
                        o.boxing().destroy();
                });
                return this;
            }
        },function(o,i){
            linb.Dom.plugIn(i,o);
        });
        //for linb.UI.Widget
        _.each({
            _shadow:function(key){
                return this.each(function(o){
                    var target = o.getSubNode('BORDER');
                    if(target.$getShadow())return;

                    var d = o.properties;
                    o.$shadow=target.addShadow({shadowSize:d._shadowSize});
                });
            },
            _unShadow:function(){
                return this.each(function(o){
                    var target = o.getSubNode('BORDER');
                    if(!target.$getShadow())return;
                    target.removeShadow();
                    delete o.$shadow
                });
            }
        },function(o,i){
            linb.UI.Widget.plugIn(i,o);
        });
        linb.UI.Widget.setDataModel({
            shadow:{
                ini:false,
                action: function(v){
                    var b=this.boxing();
                    if(v)b._shadow();
                    else b._unShadow();
                }
            },
            _shadowSize:this.SIZE
        });
    },
    Static:{
        SIZE:8,
        Templates:{
            tagName:'div',
            R:{
                tagName: 'div',
                style:'top:{shadowOffset}px;width:{shadowSize}px;right:-{pos}px;'
            },
            RB:{
                tagName: 'div',
                style:'height:{rbsize}px;width:{rbsize}px;right:-{pos}px;bottom:-{pos}px;'
            },
            B:{
                tagName: 'div',
                style: 'left:{shadowOffset}px;height:{shadowSize}px;bottom:-{pos}px;'
            }
        },
        Appearances:{
            KEY:{
               width:0,
               height:0,
               _display:'inline',
               '_font-size':0,
               '_line-height':0
            },
            'B, RB, R':{
                position:'absolute',
                display:'block',
                '*font-size':0,
                '*line-height':0,
                'z-index':'-1'
            },
            B:{
                left:0,
                width:'100%',
                background: linb.browser.ie6 ? '' : linb.UI.$bg('bottom.png', 'repeat-x left bottom'),
                _filter: linb.UI.$ieBg('bottom.png')
            },
            RB:{
                background: linb.browser.ie6?'':linb.UI.$bg('right_bottom.png', 'left top'),
                _filter: linb.UI.$ieBg('right_bottom.png')
            },
            R:{
                top:0,
                height:'100%',
                background: linb.browser.ie6?'': linb.UI.$bg('right.png', 'repeat-y right top'),
                _filter: linb.UI.$ieBg('right.png')
            }
        },
        DataModel:{
            shadowSize:{
                ini:8,
                action: function(value){
                    var self=this,
                    shadowOffset =self.properties.shadowOffset;
                    self.getSubNode('R').cssRegion({width:value,top:shadowOffset,right:-value-shadowOffset});
                    self.getSubNode('RB').cssRegion({width:value,height:value,right:-value-shadowOffset+1,bottom:-value-shadowOffset+1});
                self.getSubNode('B').cssRegion({height:value,left:shadowOffset,bottom:-value-shadowOffset});
                }
            },
            shadowOffset:{
                ini:0,
                action: function(value){
                    this.boxing().setShadowSize(this.properties.shadowSize, true);
                }
            }
        },
        _prepareData:function(profile){
            var t = arguments.callee.upper.call(this, profile);
            t.pos = (parseInt(t.shadowSize)||0) + (parseInt(t.shadowOffset)||0);
            t.rbsize=t.shadowSize+4;
            return t;
        },
        LayoutTrigger:function(){
            // refresh height for IE6
            if(linb.browser.ie) this.getRoot().ieRemedy()
        } 
    }
});//resizer class, add a plug in to linb.Dom
Class("linb.UI.Resizer","linb.UI",{
    Instance:{
        _attachTo:function(target, parent){
            var self=this, v=self.get(0);

            //set target first
            v._target= linb(target);
            v._parent= parent || linb('body');

            //add to dom
            v._parent.append(self);

            v.$resizeId = linb(target).id();

            return self;
        },
        show:function(){
            var self=this;
            self.each(function(o){
                o.getRoot().css('display',o.$display||'block');
            });
            if(linb.browser.ie)
                self.reBoxing().ieRemedy();
            return self;
        },
        hide:function(){
            var self=this;
            self.each(function(o){
                o.$display = o.getRoot().css('display');
            });
            self.reBoxing().css('display','none');
            return self;
        }
    },
    Initialize:function(){
        this.addTemplateKeys(['HANDLER','HIDDEN','MOVE','L','R','T','B','LT','RT','LB','RB']);
        _.each({
            // add resizer to linb.Dom plugin
            addResizer:function(properties, onUpdate){
                var target=linb([this.get(0)]);
                properties=properties||{};
                _.merge(properties,{
                    _attached:true
                });

                var r = new linb.UI.Resizer(properties)._attachTo(target, target);

                //set event
                if(onUpdate) r.onUpdate(onUpdate);
                return r;
            },
            removeResizer:function(){
                var s = this.id();
                _.arr.each(linb.UI.Resizer._cache,function(o){
                    if(o.$resizeId==s)
                        o.boxing().destroy();
                });
                return this;
            },
            $getResizer:function(){
                var s = this.id(), b;
                _.arr.each(linb.UI.Resizer._cache,function(o){
                    if(o.$resizeId==s){b=o;return false;}
                });
                return b && b.boxing();
            }
        },function(o,i){
            linb.Dom.plugIn(i,o);
        });

        //for linb.UI.Widget
        _.each({
            _resizer:function(key, args){
                return this.each(function(o){
                    var target = o.getSubNode('BORDER'),
                        d = o.properties;
                    if(target.$getResizer())return;
                    args = args || {};
                    var update = function(pro, target, size, cssPos){
                        var profile=arguments.callee.profile,
                            node=profile.getRoot(),
                            prop=profile.properties,
                            t
                        ;
                        if(size){
                            var w=null,h=null;
                            if(t=size.width){
                                node.widthBy(t);
                                prop.width = w = node.width();
                            }
                            if(t=size.height){
                                node.heightBy(t);
                                prop.height = h = node.height();
                            }
                            linb.UI.$tryResize(profile,w,h,true);
                        }
                        if(cssPos){
                            if((t=cssPos.left) && !(prop.left=='auto'&&parseInt(prop.right)>=0)){
                                node.leftBy(t);
                                prop.left= node.left();
                            }
                            if((t=cssPos.top) && !(prop.top=='auto'&&parseInt(prop.bottom)>=0)){
                                node.topBy(t);
                                prop.top = node.top();
                            }
                        }
                    };
                    update.profile = o;

                    o.$resizer = target.addResizer(args, update);
                    
                    o.$resizer.get(0).$parentUIProfile=o;
                });
            },
            _unResizer:function(){
                return this.each(function(o){
                    var target = o.getSubNode('BORDER');
                    if(!target.$getResizer())return;
                    target.removeResizer();

                    delete o.$resizer.get(0).$parentUIProfile;
                    delete o.$resizer;
                });
            }
        },function(o,i){
            linb.UI.Widget.plugIn(i,o);
        });
        linb.UI.Widget.setDataModel({
            resizer:{
                ini:false,
                action: function(v){
                    var b=this.boxing();
                    if(v){
                        var t = this.properties,
                            arg={};
                        _.each('minHeight,minWidth,maxHeight,maxWidth'.split(','),function(i){
                            if(i in t)arg[i]=t[i];
                        });
                        b._resizer(v,arg);
                    }else
                        b._unResizer();
                }
            }
        });

    },
    Static:{
        Templates:{
            tagName:'div',
            style:'{_style};'
        },
        Appearances:{
            KEY:{
                position:'absolute',
                margin:'0 -1px -1px 0',
                visibility: 'visible',
                'font-size':0,
                'line-height':0,

                //for ie
                '*background': 'url('+linb.ini.path+'bg.gif)',
                /*for get top Index, when it's static*/
                'z-index':60,
                cursor:'move'
            },
            MOVE:{
                position:'absolute',
                display:'block',
                'z-index':100,
                visibility: 'visible',
                background: linb.UI.$bg('icons.gif', 'no-repeat -17px -244px', true),
                'font-size':0,
                'line-height':0
            },
            HANDLER:{
                $order:0,
                position:'absolute',
                display:'block',
                border:'solid 1px',
                'background-color':'#fff',
                'z-index':100,
                visibility: 'visible',
                'font-size':0,
                'line-height':0
            },
            T:{
               $order:1,
               left:'50%',
               cursor: 'n-resize'
            },
            RT:{
               $order:1,
               cursor: 'ne-resize',
               'z-index': 110
            },
            R:{
               $order:1,
               top:'50%',
               cursor: 'e-resize'
            },
            RB:{
               $order:1,
                cursor: 'se-resize',
                'z-index': 110
            },
            B:{
               $order:1,
                left:'50%',
                cursor: 's-resize'
            },
            LB:{
               $order:1,
                cursor: 'sw-resize',
                'z-index': 110
            },
            L:{
               $order:1,
                top:'50%',
                cursor: 'w-resize'
            },
            LT:{
               $order:1,
                cursor: 'nw-resize',
                'z-index': 110
            },
            //must after HANDLER
            HIDDEN:{
                $order:10,
                'background-color':'transparent',
                'border-width': 0
            }
        },
        Behaviors:{
            onMousedown:function(profile, e, src){
                profile.box._onMousedown(profile, e, src, {move:true});
            },
            onDragbegin:function(profile, e, src){
                profile.box._onDragbegin(profile, e, src);
            },
            onDrag:function(profile, e, src){
                profile.box._onDrag(profile, e, src, {move:true});
            },
            onDragstop:function(profile, e, src){
                profile.box._onDragstop(profile, e, src, {move:true} );
            },
            LT:{
                onMousedown:function(profile, e, src){
                    profile.box._onMousedown(profile, e, src, {left:true, top:true});
                    return false;
                },
                onDragbegin:function(profile, e, src){
                    profile.box._onDragbegin(profile, e, src);
                },
                onDrag:function(profile, e, src){
                    profile.box._onDrag(profile, e, src, {left:true, top:true});
                },
                onDragstop:function(profile, e, src){
                    profile.box._onDragstop(profile, e, src, {left:true, top:true});
                }
            },
            RT:{
                onMousedown:function(profile, e, src){
                    profile.box._onMousedown(profile, e, src, {right:true, top:true});
                    return false;
                },
                onDragbegin:function(profile, e, src){
                    profile.box._onDragbegin(profile, e, src);
                },
                onDrag:function(profile, e, src){
                    profile.box._onDrag(profile, e, src, {right:true, top:true});
                },
                onDragstop:function(profile, e, src){
                    profile.box._onDragstop(profile, e, src, {right:true, top:true});
                }
            },
            LB:{
                onMousedown:function(profile, e, src){
                    profile.box._onMousedown(profile, e, src, {left:true, bottom:true});
                    return false;
                },
                onDragbegin:function(profile, e, src){
                    profile.box._onDragbegin(profile, e, src);
                },
                onDrag:function(profile, e, src){
                    profile.box._onDrag(profile, e, src, {left:true, bottom:true});
                },
                onDragstop:function(profile, e, src){
                    profile.box._onDragstop(profile, e, src, {left:true, bottom:true});
                }
            },
            RB:{
                onMousedown:function(profile, e, src){
                    profile.box._onMousedown(profile, e, src, {right:true, bottom:true});
                    return false;
                },
                onDragbegin:function(profile, e, src){
                    profile.box._onDragbegin(profile, e, src);
                },
                onDrag:function(profile, e, src){
                    profile.box._onDrag(profile, e, src, {right:true, bottom:true});
                },
                onDragstop:function(profile, e, src){
                    profile.box._onDragstop(profile, e, src, {right:true, bottom:true});
                }
            },
            L:{
                onMousedown:function(profile, e, src){
                    profile.box._onMousedown(profile, e, src, {left:true});
                    return false;
                },
                onDragbegin:function(profile, e, src){
                    profile.box._onDragbegin(profile, e, src);
                },
                onDrag:function(profile, e, src){
                    profile.box._onDrag(profile, e, src, {left:true});
                },
                onDragstop:function(profile, e, src){
                    profile.box._onDragstop(profile, e, src, {left:true});
                }
            },
            T:{
                onMousedown:function(profile, e, src){
                    profile.box._onMousedown(profile, e, src, {top:true});
                    return false;
                },
                onDragbegin:function(profile, e, src){
                    profile.box._onDragbegin(profile, e, src);
                },
                onDrag:function(profile, e, src){
                    profile.box._onDrag(profile, e, src, {top:true});
                },
                onDragstop:function(profile, e, src){
                    profile.box._onDragstop(profile, e, src, {top:true});
                }
            },
            R:{
                onMousedown:function(profile, e, src){
                    profile.box._onMousedown(profile, e, src, {right:true});
                    return false;
                },
                onDragbegin:function(profile, e, src){
                    profile.box._onDragbegin(profile, e, src);
                },
                onDrag:function(profile, e, src){
                    profile.box._onDrag(profile, e, src, {right:true});
                },
                onDragstop:function(profile, e, src){
                    profile.box._onDragstop(profile, e, src, {right:true});
                }
            },
            B:{
                onMousedown:function(profile, e, src){
                    profile.box._onMousedown(profile, e, src, {bottom:true});
                    return false;
                },
                onDragbegin:function(profile, e, src){
                    profile.box._onDragbegin(profile, e, src);
                },
                onDrag:function(profile, e, src){
                    profile.box._onDrag(profile, e, src, {bottom:true});
                },
                onDragstop:function(profile, e, src){
                    profile.box._onDragstop(profile, e, src, {bottom:true});
                }
            }
        },
        DataModel:{
            // attached to a dom node for resizer function.
            _attached:false,

//<< can be used in addResizer({*})
            // handler visible?
            forceVisible:false,
            // movable
            forceMovable:false,

            // only show right/bottom handlers
            singleDir:false,
            // can change width
            vertical :true,
            // can chang height
            horizontal :true,

            minHeight: 12,
            minWidth: 12,
            maxHeight: 5000,
            maxWidth: 5000,

            handlerSize:4,
            handlerOffset:0,
//>>

            left: 100,
            top: 100,
            height: 100,
            width: 100,
            position:'absolute',
            display:'block'
        },
        EventHandlers:{
            onUpdate:function(profile, target, size, cssPos){}
        },
        _dynamicTemplate:function(profile){
            var pro = profile.properties,size,pos,temp,
                hash = profile._exhash =
                    "$" +
                    '_attached:' + pro._attached + ';' +
                    'forceVisible:' + pro.forceVisible + ';' +
                    'singleDir:' + pro.singleDir + ';' +
                    'vertical:' + pro.vertical + ';' +
                    'horizontal:' + pro.horizontal + ';' +
                    'forceMovable:' + pro.forceMovable + ';'
            ;

            var map= arguments.callee.map || (arguments.callee.map={
                //move icon size 13*13
                MOVE:{tagName:'div', style:'top:50%;left:50%;margin-left:-6px;margin-top:-6px;width:13px;height:13px;'},
                T:{tagName:'div', style:'top:-{extend}px;margin-left:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                RT:{tagName:'div', style:'top:-{extend}px;right:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                R:{tagName:'div', style:'right:-{extend}px;margin-top:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                RB:{tagName:'div', style:'bottom:-{extend}px;right:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                B:{tagName:'div', style:'bottom:-{extend}px;margin-left:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                LB:{tagName:'div',style:'bottom:-{extend}px;left:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                L:{tagName:'div', style:'left:-{extend}px;margin-top:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                LT:{tagName:'div', style:'left:-{extend}px;top:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                cover:{
                    T:{tagName:'div', style:'width:100%;left:0;top:-{extend}px;height:{handlerSize}px;'},
                    RT:{tagName:'div', style:'top:-{extend}px;right:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                    R:{tagName:'div', style:'height:100%;top:0;right:-{extend}px;width:{handlerSize}px;' },
                    RB:{tagName:'div', style:'right:-{extend}px;bottom:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                    B:{tagName:'div', style:'width:100%;left:0;bottom:-{extend}px;height:{handlerSize}px;'},
                    LB:{tagName:'div', style:'left:-{extend}px;bottom:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'},
                    L:{tagName:'div', style:'height:100%;top:0;left:-{extend}px;width:{handlerSize}px;' },
                    LT:{tagName:'div', style:'top:-{extend}px;left:-{extend}px;width:{handlerSize}px;height:{handlerSize}px;'}
                }
            });

            /* dynamic template set here
                template._id is main id, which can input by create arg
                template._did is sub id, which must be built on fly, and cached
            */
            var template = profile.box.getTemplate(hash);
            // set template dynamic
            if(!template){
                var t,n;
                template = _.clone(profile.box.getTemplate());

                // cover or not?
                t = pro._cover?map.cover:map;
                // can move?
                if(pro._move)template.MOVE = map.MOVE;

                // change height only
                if(pro.vertical){
                    if(!pro.singleDir)
                        template.T = t.T;
                    template.B = t.B;
                }
                // change width only
                if(pro.horizontal){
                    if(!pro.singleDir)
                        template.L = t.L;
                    template.R = t.R;
                    // change height and width
                    if(pro.vertical){
                        if(!pro.singleDir){
                            template.LB = t.LB;
                            template.RT = t.RT;
                            template.LT = t.LT;
                        }
                        template.RB = t.RB;
                    }
                }

                n = profile.getClass('KEY', '-handler') + " ";
                if(t=template.T)t.className = n;
                if(t=template.RT)t.className = n;
                if(t=template.R)t.className = n;
                if(t=template.RB)t.className = n;
                if(t=template.B)t.className = n;
                if(t=template.LB)t.className = n;
                if(t=template.L)t.className = n;
                if(t=template.LT)t.className = n;

                // if hidden
                if(!pro._visible){
                    n = profile.getClass('KEY', '-hidden') + " ";
                    if(t=template.T)t.className += n;
                    if(t=template.RT)t.className += n;
                    if(t=template.R)t.className += n;
                    if(t=template.RB)t.className += n;
                    if(t=template.B)t.className += n;
                    if(t=template.LB)t.className += n;
                    if(t=template.L)t.className += n;
                    if(t=template.LT)t.className += n;

                }
                // set template
                profile.box.setTemplate(template, hash);
            }
            profile.template = template;
        },
        _prepareData:function(profile){
            var t = profile.properties;
            //default is true
            t._visible=true;
            t._cover=false;
            t._move=true;
            // for _attached type
            if(t._attached){
                t._visible=false;
                t._cover=true;
                t._move=false;

                t.position = 'static';
                t.display = 'inline';
                t.left = t.top = t.width = t.height = 0;
            }
            if(t.forceVisible){
                t._visible=true;
                t._cover=false;
            }
            if(t.forceMovable)
                t._move=true;

            t.extend =  (parseInt(t.handlerSize)||0)/2 + (parseInt(t.handlerOffset)||0);

            return arguments.callee.upper.call(this, profile);
        },
        RenderTrigger:function(){
            var self=this;
            linb.setNodeData(self.renderId,'zIndexIgnore',1)
            // set ini update function
            if(!self.onUpdate)
                self.onUpdate = self.box.onUpdate;
        },
        onUpdate:function(profile, target, size, cssPos){
            if(target){
                if(size)target.widthBy(size.width,true).heightBy(size.height,true);
                if(cssPos){
                    var t=target.get(0).style;
                    if(t.left=='auto'&&(parseInt(t.right)>=0)){}else
                    target.leftBy(cssPos.left)
                    if(t.top=='auto'&&(parseInt(t.bottom)>=0)){}else
                    target.topBy(cssPos.top);
                }
            }
        },
        //
        _onMousedown:function(profile, e, src, ddparas){
            var puip=profile.$parentUIProfile;
            if(puip && puip['linb.UIProfile'] && puip.beforeResizerDrag && false=== _.tryF(puip.beforeResizerDrag,[puip,profile,ddparas],puip.boxing()))
                return;

            var pos=linb.Event.getPos(e);
            linb.use(src).startDrag(e,{
                dragDefer:1,
                targetReposition:false,
                dragType:'blank',
                dragCursor:true,
                targetLeft:pos.left,
                targetTop:pos.top
            });
        },
        _onDragbegin:function(profile, e){
            var 
            //set target to specific target
            //or, set target to resizer
            o = profile.properties._attached?profile._target:linb([profile.renderId]),
            w = o.width(),
            h = o.height();
            if(profile.properties._attached){
                var pos =o.offset();
                //custom proxy
                profile.proxy = linb.Dom.getEmptyDiv();
                profile.proxy
                .html(' ',false)
                .css({border:'1px dashed',visibility:'visible'})
                .offset(pos)
                .width(w)
                .height(h)
                .css('zIndex',linb.Dom.TOP_ZINDEX+20);
            }else
                //set proxy to itself
                profile.proxy = o;

            //get pos for target and proxy
            profile.o_pos = profile.proxy.cssPos();
            //get current w h from target
            profile.o_w2 =profile.o_w =w;
            profile.o_h2 =profile.o_h = h;

            profile.$onDrag = true;
        },
        _onDrag:function(profile, e,src, ddparas){
            var o=ddparas;
            //get dragdop off set
            profile.oos = profile.oos ||{};
            var os = linb.DragDrop.getProfile().offset;
            if(os.x == profile.oos.width && os.y == profile.oos.height)return;
            profile.oos=os;

            var x,y,w,h,t=profile.properties;

            if(o.left){
                // width of proxy
                w = profile.o_w - os.x;
                // left of proxy
                x = profile.o_pos.left + os.x;
                if(w<t.minWidth){
                    w=t.minWidth;
                    x = profile.o_w+profile.o_pos.left - w;
                }else if(w>t.maxWidth){
                    w=t.maxWidth;
                    x= profile.o_w+profile.o_pos.left - w;
                }
                profile.proxy.width(w).left(x);
            }else if(o.right){
                w = profile.o_w + os.x;
                if(w<t.minWidth)w=t.minWidth;
                else if(w>t.maxWidth)w=t.maxWidth;
                profile.proxy.width(w);
            }
            if(o.left || o.right){
                //resize inner region block
                var byw = w-profile.o_w2;
                if(profile.regions && byw!==0){
                    profile.regions.widthBy(byw);
                    profile.o_w2=w;
                }
            }

            if(o.top){
                h = profile.o_h - os.y;
                y = profile.o_pos.top + os.y;
                if(h<t.minHeight){
                    h=t.minHeight;
                    y=profile.o_h+profile.o_pos.top - h;
                }else if(h>t.maxHeight){
                    h=t.maxHeight;
                    y=profile.o_h+profile.o_pos.top - h;
                }
                profile.proxy.height(h).top(y);
            }else if(o.bottom){
                h= profile.o_h + os.y;
                if(h<t.minHeight)h=t.minHeight;
                else if(h>t.maxHeight)h=t.maxHeight;
                profile.proxy.height(h);
            }
            if(o.top || o.bottom){
                //resize inner region block
                var byh = h-profile.o_h2;
                if(profile.regions && byh!==0){
                    profile.regions.heightBy(byh);
                    profile.o_h2=h;
                }
            }

            if(o.move){
                x = profile.o_pos.left + os.x;
                y = profile.o_pos.top + os.y;
                profile.proxy.top(y).left(x);
            }
        },
        _onDragstop:function(profile, e, src, args){
            var cssPos,size,pos,o=profile.proxy;

            if(!args.move)
                size = { width :o.width()-profile.o_w, height :o.height()-profile.o_h};

            if(args.left || args.top || args.move){
                cssPos = o.cssPos();
                pos = {left :cssPos.left-profile.o_pos.left,  top :cssPos.top-profile.o_pos.top};
            }
            profile.boxing().onUpdate(profile, profile._target, size, pos);

            if(profile.properties._attached){
                if(linb.browser.ie6)profile._target.ieRemedy();
                profile.proxy.html('',false).css({visibility:'hidden',border:'none',zIndex:'0',width:'0',height:'0'});
            }
            //profile.boxing().active();
            profile.$onDrag = false;
        }
    }
});Class("linb.UI.Block", "linb.UI.Widget",{
    Initialize:function(){
        var self=this,
            t = self.getTemplate();
        //modify
        _.merge(t.FRAME.BORDER,{
            className:'uiw-border {clsBorderType1}',
            PANEL:{
                tagName:'div',
                className:'{clsBorderType2} uibg-bar',
                style:'{background}',
                text:'{html}'+linb.UI.$childTag
            }
        },'all');
        //set back
        self.setTemplate(t);

        //get default Appearance
        t = self.getAppearance();
        //modify
        _.merge(t,{
            PANEL:{
                position:'relative',
                overflow:'hidden'
            }
        });
        //set back
        self.setAppearance(t);
    },
    Static:{
        Behaviors:{
            DropableKeys:['PANEL']
        },
        DataModel:{
            //delete those properties
            disabled:null,
            tips:null,
            html:{
                action:function(v){
                    this.getSubNode('PANEL').html(v);
                }
            },
            borderType:{
                ini:'outset',
                listbox:['none','inset','outset','groove','ridge'],
                action:function(v){
                    var ns=this,
                        p=ns.properties,
                        n1=ns.getSubNode('BORDER'), n2=ns.getSubNode('PANEL'),
                        reg=/^uiborder-/,
                        ins='uiborder-inset',
                        outs='uiborder-outset',
                        root=ns.getRoot();
                    n1.removeClass(reg);
                    n2.removeClass(reg);
                    switch(v){
                        case 'inset':
                        n1.addClass(ins);
                        break;
                        case 'outset':
                        n1.addClass(outs);
                        break;
                        case 'groove':
                        n1.addClass(ins);
                        n2.addClass(outs);
                        break;
                        case 'ridge':
                        n1.addClass(outs);
                        n2.addClass(ins);
                        break;
                    }

                    //force to resize
                    ns.box._setB(ns);
                    linb.UI.$tryResize(ns,root.get(0).style.width,root.get(0).style.height,true);
                }
            },
            background:{
                ini:'',
                action:function(v){
                    this.getSubNode('PANEL').css('background',v);
                }
            },
            width:100,
            height:100
        },
        _setB:function(profile){
            var p=profile.properties,type=p.borderType;
            p.$hborder=p.$vborder=p.$iborder=0;
            if(type=='inset'||type=='outset'){p.$hborder=p.$vborder=1;p.$iborder=0;}
            else if(type=='groove'||type=='ridge'){p.$hborder=p.$vborder=p.$iborder=1;}
        },
        LayoutTrigger:function(){
            var v=this.properties.borderType;
            if(v!='none')this.boxing().setBorderType(v,true);
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile);
            data.background= data.background?'background:'+data.background:'';
            return data;
        },        
        _onresize:function(profile,width,height){
            var size = arguments.callee.upper.apply(this,arguments),
                p=profile.properties,
                b=(p.$iborder||0)*2;
            if(size.width)size.width-=b;
            if(size.height&&'auto'!==size.height)
                size.height-=b;
            profile.getSubNode('PANEL').cssSize(size,true);
        }
    }
});

Class("linb.UI.Label", "linb.UI.Widget",{
    Instance:{
        _shadowText:function(key){
            return this.each(function(o){
                o.getSubNode('SHADOW').css('display','block');
            });
        },
        _unShadowText:function(key){
            return this.each(function(o){
                o.getSubNode('SHADOW').css('display','none');
            });
        }
    },
    Initialize:function(){
        //modify default template from parent
        var t = this.getTemplate();
        _.merge(t.FRAME.BORDER,{
            SHADOW:{
                $order:1,
                style:'display:none;',
                SICON:{
                    $order:0,
                    className:'ui-icon {imageClass}',
                    style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                },
                SCAPTION:{
                    text : '{caption}',
                    style:'color:#cdcdcd;',
                    $order:1
                }
            },
            BOX:{
                $order:2,
                ICON:{
                    $order:0,
                    className:'ui-icon {imageClass}',
                    style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                },
                CAPTION:{
                    text : '{caption}',
                    $order:1
                }
            }
        },'all');
        this.setTemplate(t);
    },
    Static:{
        Appearances:{
            KEY:{
                'font-size':'12px',
                'line-height':'14px'
            },
            BOX:{
                position:'absolute'
            },
            SHADOW:{
                position:'absolute',
                top:'4px'
            }
        },
        DataModel:{
            tabindex:null,
            // setCaption and getCaption
            caption:{
                ini:undefined,
                // ui update function when setCaption
                action: function(value){
                    var self=this,p=self.properties,b=self.boxing(),k=self.keys;
                    self.getSubNodes(['CAPTION','SCAPTION']).html(value,false);
                    if(p.hAlign!='left')b.setHAlign(p.hAlign,true);
                    if(p.vAlign!='top')b.setVAlign(p.vAlign,true);
                }
            },
            image:{
                action: function(value){
                    var self=this,k=self.keys;
                    self.getSubNodes(['ICON','SICON'])
                        .css('display',value?'':'none')
                        .css('backgroundImage','url('+(value||'')+')');
                }
            },
            imagePos:{
                action: function(value){
                    var self=this,k=self.keys;
                    self.getSubNodes(['ICON','SICON'])
                        .css('backgroundPosition', value);
                }
            },
            shadowText:{
                ini:false,
                action: function(v){
                    var b=this.boxing();
                    //for string input
                    v = String(v).toLowerCase()!='false';
                    if(v)
                        b._shadowText(v);
                    else
                        b._unShadowText();
                }
            },
            hAlign:{
                ini:'right',
                listbox:['left','center','right'],
                action: function(v){
                    var self=this,c=self.getSubNode('BOX'),
                        d=self.getSubNode('SHADOW'),
                        t=self.properties;
                    switch(v){
                        case 'left':
                            c.css({left:0,right:'auto','marginLeft':'auto'});
                            d.css({left:t._textSshadowSize+'px',right:'auto','marginLeft':'auto'});
                            break;
                        case 'right':
                            c.css({left:'auto',right:t._textSshadowSize+'px','marginLeft':'auto'});
                            d.css({left:'auto',right:0,'marginLeft':'auto'});
                            break;
                        case 'center':
                            c.css({left:'50%',right:'auto','marginLeft':-1*c.get(0).offsetWidth/2+'px'});
                            d.css({left:'50%',right:'auto','marginLeft':-1*c.get(0).offsetWidth/2 + t._textSshadowSize+'px'});
                            break;
                    }
                }
            },
            vAlign:{
                ini:'top',
                listbox:['top','middle','bottom'],
                action: function(v){
                    var self=this,c=self.getSubNode('BOX'),
                        d=self.getSubNode('SHADOW'),
                        t=self.properties;
                    switch(v){
                        case 'top':
                            c.css({top:0,bottom:'auto','marginTop':'auto'});
                            d.css({top:t._textSshadowSize+'px',bottom:'auto','marginTop':'auto'});
                            break;
                        case 'bottom':
                            c.css({top:'auto',bottom:t._textSshadowSize+'px','marginTop':'auto'});
                            d.css({top:'auto',bottom:0,'marginTop':'auto'});
                            break;
                        case 'middle':
                            c.css({top:'50%',bottom:'auto','marginTop':-1*c.get(0).offsetHeight/2+'px'});
                            d.css({top:'50%',bottom:'auto','marginTop':-1*c.get(0).offsetHeight/2+ t._textSshadowSize+'px'});
                            break;
                    }
                }
            },
            'fontSize':{
                action: function(value){
                    var self=this;
                    self.getSubNodes(['CAPTION','SCAPTION'])
                        .css('fontSize', value);
                }
            },
            'fontWeight':{
                action: function(value){
                    var self=this;
                    self.getSubNodes(['CAPTION','SCAPTION'])
                        .css('fontWeight', value);
                }
            },
            width:120,
            height:20,

            _textSshadowSize:4
        },
        RenderTrigger:function(){
            var p = this.properties, o=this.boxing();
            if(p.fontSize)o.setFontSize(p.fontSize,true);
            if(p.fontWeight)o.setFontWeight(p.fontWeight,true);
            if(p.shadowText)o.setShadowText(true,true);
        },
        LayoutTrigger:function(){
            var p = this.properties, o=this.boxing(),s=p.shadowText;
            if(p.hAlign!='left' || s)o.setHAlign(p.hAlign,true);
            if(p.vAlign!='top'|| s)o.setVAlign(p.vAlign,true);
        }
    }
});Class("linb.UI.ProgressBar", ["linb.UI.Widget","linb.absValue"] ,{
    Instance:{
        _setCtrlValue:function(value){
            return this.each(function(profile){
                profile.getSubNode('FILL').width(value+"%");
                profile.getSubNode('CAP').text(profile.properties.captionTpl.replace(/\{value\}/g,value));
            });
        }
    },
    Initialize:function(){
        var self=this,
            t = self.getTemplate();
        //modify
        _.merge(t.FRAME.BORDER,{
            FILL:{
                tagName:'div',
                style:'width:{value}%;{fillBG}',
                text:'{html}'+linb.UI.$childTag
            },
            INN:{
                $order:2,
                tagName:'div',
                CAP:{
                    tagName:'div'
                }
            }
        },'all');
        //set back
        self.setTemplate(t);

        //get default Appearance
        t = self.getAppearance();
        //modify
        _.merge(t,{
            BORDER:{
                border:'1px solid #95B611',
                'font-size':0,
                'line-height':0
            },
            INN:{
                display:'table',
                position:'absolute',
                left:0,
                top:0,
                width:'100%',
                height:'100%'
            },
            CAP:{
                'text-align':'center'
            },
            FILL:{
                position:'absolute',

                width:'1px',
                left:0,
                top:0,
                height:'100%',
                background: linb.UI.$bg('bar.gif', '#96E115 repeat-x left top'),
                width:0
            }
        });
        //set back
        self.setAppearance(t);
    },
    Static:{
        DataModel:{
            value:0,
            width:300,
            height:22,
            captionTpl:{
                ini:'{value}%',
                action:function(){
                    this.boxing()._setCtrlValue(this.properties.$UIvalue);
                }
            },
            fillBG:{
                ini:'',
                action:function(v){
                    this.getSubNode('FILL').css('background',v);
                }
            },
            $hborder:1,
            $vborder:1
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile);
            data.fillBG = data.fillBG?'background:'+data.fillBG:'';
            return data;
        },
        _ensureValue:function(profile,value){
            return parseInt(value)||0;
        },
        _onresize:function(profile,width,height){
            var size = arguments.callee.upper.apply(this,arguments),h;
            if(size.height){
                h=size.height+'px';
                profile.getSubNodes(['INN','CAP','FILL']).css({height:h,'line-height':h});
            }
        }
    }
});

Class("linb.UI.Button", ["linb.UI.Widget","linb.absValue"],{
    Instance:{
        activate:function(){
            this.getSubNode('FOCUS').focus();
            return this;
        },
        _setCtrlValue:function(value){
            if(_.isNull(value) || !_.isDefined(value))value=false;
            return this.each(function(profile){
                var pp=profile.properties;
                if(pp.type!='status')return;
                profile.getSubNode('BORDER').tagClass('-checked', value);

                if(pp.border){
                    var b = profile.getSubNode('BORDER').$getBorder();
                    if(b)b.get(0).getRoot().tagClass('-checked', value);
                }
            });
        }
    },
    Initialize:function(){
        this.addTemplateKeys(['DROP']);
        //modify default template for shell
        var t = this.getTemplate();
        _.merge(t.FRAME,{
            FOCUS:{
                $order:2,
                tagName:'a',
                href :"{href}",
                tabindex: '{tabindex}',
                TB:{
                    cellpadding:"0",
                    cellspacing:"0",
                    width:'100%',
                    height:'100%',
                    border:'0',
                    tagName:'table',
                    TR:{
                        tagName:'tr',
                        TDL:{
                            tagName:'td'
                        },
                        TD:{
                            $order:1,
                            align:'{hAlign}',
                            valign:'{vAlign}',
                            tagName:'td',
                            width:'100%',
                            height:'100%',
                            BOX:{
                                ICON:{
                                    $order:1,
                                    className:'ui-icon {imageClass}',
                                    style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                                },
                                CAPTION:{
                                    $order:2,
                                    text: '{caption}'
                                }
                            }
                        },
                        TDR:{
                            $order:2,
                            tagName:'td',
                            className:'{dropCls}',
                            TDRI:{}
                        }
                    }
                }
            }
        },'all');
        this.setTemplate(t);
    },
    Static:{
        Appearances:{
            KEY:{
                'font-size':'12px',
                'line-height':'14px'
            },
            BORDER:{
                'font-size':0,
                'line-height':0,
                'background-color':'#D2D7DF'
            },
            'BORDER-mouseover':{
                $order:2,
                'background-color':'#F7D928'
            },
            'BORDER-mousedown, BORDER-checked':{
                $order:2,
                'background-color':'#F9E56A'
            },
            'DROP':{
                $order:10,
                background: linb.UI.$bg('drop.gif', 'no-repeat left bottom','Button'),
                'padding-left':'16px'
            },
            'DROP-mouseover':{
                $order:11,
                'background-position':'-16px bottom'
            },
            'DROP-mousedown':{
                $order:12,
                'background-position':'right bottom'
            },
            'TDR,TDL':{
                'padding-left':'6px'
            },
//border<<<
            '.setting-linb-button':{
                'border-top-width':'1px',
                'border-bottom-width':'1px',
                'border-left-width':'1px',
                'border-right-width':'1px'
            },
            'KEY-b-t':{
                top:'-1px',
                height:'10px',
                background: linb.UI.$bg('vertical.gif', 'repeat-x left top','Button')
            },
            'KEY-b-b':{
                bottom:'-1px',
                height:'10px',
                background: linb.UI.$bg('vertical.gif', 'repeat-x left bottom','Button')
            },
            'BORDER-mouseover KEY-b-t, BORDER-mouseover KEY-b-b':{
                $order:1,
                'background-image':linb.UI.$bg('vertical_mouseover.gif','','Button')
            },
            'BORDER-checked KEY-b-t, BORDER-checked KEY-b-b, BORDER-mousedown KEY-b-t, BORDER-mousedown KEY-b-b':{
                $order:2,
                'background-image':linb.UI.$bg('vertical_mousedown.gif','','Button')
            },
            'KEY-b-l':{
                left:'-1px',
                width:'4px',
                background: linb.UI.$bg('horizontal.gif', 'repeat-y left top','Button')
            },
            'KEY-b-r':{
               right:'-1px',
               width:'4px',
               background: linb.UI.$bg('horizontal.gif', 'repeat-y right top','Button')
            },
            'BORDER-mouseover KEY-b-l, BORDER-mouseover KEY-b-r':{
                $order:1,
                'background-image': linb.UI.$bg('horizontal_mouseover.gif','','Button')
            },
            'BORDER-checked KEY-b-l, BORDER-checked KEY-b-r, BORDER-mousedown KEY-b-l, BORDER-mousedown KEY-b-r':{
                $order:2,
                'background-image': linb.UI.$bg('horizontal_mousedown.gif','','Button')
            },
            'KEY-b-lt':{
                top:'-1px',
                left:'-1px',
                width:'4px',
                height:'10px',
                background: linb.UI.$bg('corner.gif', 'no-repeat left top','Button')
            },
            'KEY-b-rt':{
               top:'-1px',
               right:'-1px',
               width:'4px',
               height:'10px',
               background: linb.UI.$bg('corner.gif', 'no-repeat right top','Button')
            },
            'KEY-b-rb':{
                right:'-1px',
                bottom:'-1px',
                width:'4px',
                height:'10px',
                background: linb.UI.$bg('corner.gif', 'no-repeat right bottom','Button')
            },
            'KEY-b-lb':{
                left:'-1px',
                bottom:'-1px',
                width:'4px',
                height:'10px',
                background: linb.UI.$bg('corner.gif', 'no-repeat left bottom','Button')
            },
            'BORDER-mouseover KEY-b-lt, BORDER-mouseover KEY-b-rt, BORDER-mouseover KEY-b-rb, BORDER-mouseover KEY-b-lb':{
                $order:1,
                'background-image': linb.UI.$bg('corner_mouseover.gif','','Button')
            },
            'BORDER-checked KEY-b-lt, BORDER-checked KEY-b-rt, BORDER-checked KEY-b-rb, BORDER-checked KEY-b-lb, BORDER-mousedown KEY-b-lt, BORDER-mousedown KEY-b-rt, BORDER-mousedown KEY-b-rb, BORDER-mousedown KEY-b-lb':{
                $order:2,
                'background-image' : linb.UI.$bg('corner_mousedown.gif','','Button')
            },
//border>>>
            /*a*/
            FOCUS:{
                overflow:'hidden',
                display:'block',
                left:0,
                top:0,
                'z-index':'20',
                width:'100%',
                height:'100%',
                position:'absolute',
                '-moz-outline-offset':'-1px !important'
            },
            /*span*/
            BOX:{
                display:'inline',
                'white-space':'nowrap'
            },
            CAPTION:{
                cursor:'pointer',
                'vertical-align':'middle',
                display:'inline',
                'font-size':'12px',
                'line-height':'14px'
            }
        },
        Behaviors:{
            HoverEffected:{KEY:['BORDER']},
            ClickEffected:{KEY:['BORDER']},
            NavKeys:{FOCUS:1},
            onClick:function(profile, e, src){
                var p=profile.properties;
                if(p.disabled)return false;

                //before event
                profile.getSubNode('FOCUS').focus();

                var b=profile.boxing();

                if(p.type=='status'){
                    b.setUIValue(!p.$UIvalue);
                    if(profile.onChecked)
                        b.onChecked(profile, e, p.$UIvalue);
                }

                //onClick event
                if(profile.onClick)
                    b.onClick(profile, e, src, p.$UIvalue);

            },
            TDR:{
                onMousedown:function(profile,e,src){
                    if(profile.properties.type!='drop')return;
                    linb.use(src).addClass(profile.getClass('DROP','-mousedown'));
                    return false;
                },
                onMouseup:function(profile,e,src){
                    if(profile.properties.type!='drop')return;
                    linb.use(src).removeClass(profile.getClass('DROP','-mousedown'));
                    return false;
                },
                onMouseover:function(profile,e,src){
                    if(profile.properties.type!='drop')return;
                    linb.use(src).addClass(profile.getClass('DROP','-mouseover'));
                },                
                onMouseout:function(profile,e,src){
                    if(profile.properties.type!='drop')return;
                    linb.use(src).removeClass(profile.getClass('DROP','-mouseover')).removeClass(profile.getClass('DROP','-mousedown'));
                },
                onClick:function(profile, e, src){
                    if(profile.properties.type!='drop')return;
                    profile.boxing().onClickDrop(profile, e, src);
                    return false;
                }
            }
        },
        DataModel:{
            caption:{
                ini:undefined,
                // ui update function when setCaption
                action: function(value){
                    this.getSubNode('CAPTION').get(0).innerHTML = value;
                }
            },
            image:{
                action: function(value){
                    this.getSubNode('ICON')
                        .css('display',value?'':'none')
                        .css('backgroundImage','url('+(value||'')+')');
                }
            },
            imagePos:{
                action: function(value){
                    this.getSubNode('ICON')
                        .css('backgroundPosition', value);
                }
            },
            hAlign:{
                ini:'center',
                listbox:['left','center','right'],
                action: function(v){
                    this.getSubNode('TD').attr('align',v);
                }
            },
            vAlign:{
                ini:'middle',
                listbox:['top','middle','bottom'],
                action: function(v){
                    this.getSubNode('TD').attr('valign',v);
                }
            },
            href:linb.$href,
            value:false,
            type:{
                ini:'normal',
                listbox:['normal','status','drop'],
                action:function(value){
                    var self=this,
                        root=self.getRoot(),
                        tdr=self.getSubNode('TDR'),
                        drop=self.getClass('DROP');
                    if(value=='drop')
                        tdr.addClass(drop);
                    else
                        tdr.removeClass(drop);
                    self.box._onresize(self);
                }
            },
            width:120,
            height:22,
            _customBorder:'BORDER',
            border:true
        },
        _ensureValue:function(profile,value){
            return !!value;
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile);
            data.dropCls = data.type=='drop'?profile.getClass('DROP'):'';
            return data;
        },
        RenderTrigger:function(){
            var self=this,p = self.properties, o=self.boxing();
            //set value later
            if(p.type=='status' && p.value)
                o.setValue(true, true);
        },
        EventHandlers:{
            onClick:function(profile, e, src, value){},
            onClickDrop:function(profile, e, src){},
            onChecked:function(profile, e, value){}
        }
    }
});Class("linb.UI.CheckBox", "linb.UI.Button",{
    Instance:{
        _setCtrlValue:function(value){
            return this.each(function(profile){
               profile.getSubNode('MARK').tagClass('-checked', !!value);
            });
        },
        //update UI face
        _setDirtyMark:function(){
            return this.each(function(profile){
                if(!profile.properties.dirtyMark)return;
                if(!profile.renderId)return;
                var properties = profile.properties,
                    o=profile.getSubNode('CAPTION'),
                    flag=properties.value !== properties.$UIvalue,
                    d = linb.UI.$css_tag_dirty;

                if(o.beforeDirtyMark && false===o.boxing().beforeDirtyMark(profile,flag))
                    return;

                if(flag)
                    o.addClass(d);
                else
                    o.removeClass(d);
            });
        }
    },
    Initialize:function(){
        //modify default template for shell
        var t = this.getTemplate();
        _.merge(t.FRAME.FOCUS.TB.TR.TD.BOX,{
            MARK:{
                $order:0,
                className:'uicmd-check'
            }
        },'all');
        this.setTemplate(t);
    },
    Static:{
        Appearances:{
            KEY:{
                'font-size':'12px',
                'line-height':'14px',
                border:0,
                cursor:'pointer'
            },
            BORDER:{},
            /*a*/
            FOCUS:{
                overflow:'hidden',
                display:'block',
                position:'absolute',
                left:0,
                top:0,
                'z-index':'200',
                width:'100%',
                height:'100%',
                '-moz-outline-offset':'-1px !important'
            },
            /*span*/
            BOX:{
                display:linb.$inlineBlock,
                zoom:linb.browser.ie6?1:null,
                'font-size':'12px',
                'line-height':'14px',
                overflow:'hidden',
                'vertical-align':'middle',
                'white-space':'nowrap'
            },
            TD:{
                background:'transparent'
            },
            TDR:{
                background:'transparent'
            },
            TDL:{
                background:'transparent'
            },
            CAPTION:{
                display:'inline',
                'white-space':'normal',
                'vertical-align':'middle',
                cursor:'pointer',
                zoom:linb.browser.ie?0:null
            }
        },
        Behaviors:{
            HoverEffected:{KEY:'MARK'},
            ClickEffected:{KEY:'MARK'},
            onClick:function(profile, e, src){
                var p=profile.properties,b=profile.boxing();
                if(p.disabled)return false;
                //onClick event
                b.setUIValue(!p.$UIvalue);

                if(profile.onChecked)b.onChecked(profile, p.$UIvalue);
                profile.getSubNode('FOCUS').focus();
            },
            FOCUS:{
                onKeydown:function(profile, e, src){
                    var key = linb.Event.getKey(e)[0];
                    if(key ==' ' || key=='enter'){
                        profile.getRoot().onClick(true);
                        return false;
                    }
                }
            }
        },
        DataModel:{
            type:null,
            value:false,
            hAlign:'left',
            _customBorder:false,
            border:false
        },
        EventHandlers:{
            onClick:null
        },
        _ensureValue:function(profile, value){
            return !!value;
        }
    }
});
Class("linb.UI.Slider", ["linb.UI","linb.absValue"],{
    Instance:{
        _setCtrlValue:function(value){
            return this.each(function(profile){
                var p=profile.properties,
                    steps=p.steps,
                    fun=function(k){return profile.getSubNode(k)},
                    a=fun('IND1'),
                    b=fun('IND2'),
                    arr = profile.box._v2a(profile,value),
                    ori=p.type=='vertical'?'top':'left';
                a[ori](arr[0]+'%');
                if(p.isRange)
                    b[ori](arr[1]+'%');
            });
        },
        _setDirtyMark:function(){
            return this.each(function(profile){
                if(!profile.properties.dirtyMark)return;
                if(!profile.renderId)return;
                var properties = profile.properties,
                    flag=properties.value !== properties.$UIvalue;

                if(profile._dirtyFlag==flag)return;
                profile._dirtyFlag=flag;
                    
                var o=profile.getSubNode('BOX'),
                    cls=linb.UI.$css_tag_dirty;

                if(profile.beforeDirtyMark && false===profile.boxing().beforeDirtyMark(profile,flag))
                    return;

                if(flag)
                    o.addClass(cls);
                else
                    o.removeClass(cls);
            });
        }
    },
    Static:{
        Templates:{
            style:'{_style}',
            BOX:{
                tagName:'div',
                className:'{_cls}',
                BG:{
                    tagName:'div'
                },
                RULER:{
                    $order:1,
                    tagName:'div',
                    RULERLEFT:{},
                    RULERRIGHT:{}
                },
                IND:{
                    $order:2,
                    IND1:{
                        tagName:'a',
                        style:'{_showD}',
                        href:linb.$href,
                        tabindex:'{tabIndex}'
                    },
                    IND2:{
                        tagName:'a',
                        href:linb.$href,
                        tabindex:'{tabIndex}',
                        style:'{_showD2}'
                    }
                },
                DECREASE:{
                    tagName:'a',
                    style:'{_showDes}',
                    href:linb.$href,
                    tabindex:'{tabIndex}'
                },
                INCREASE:{
                    tagName:'a',
                    style:'{_showIns}',
                    href:linb.$href,
                    tabindex:'{tabIndex}'
                }
            }
        },
        Appearances:{
            'IND, BT, RULER, RULERLEFT, RULERRIGHT, IND1, IND2, DECREASE, INCREASE':{
                'font-size':0,
                'line-height':0,
                position:'absolute'
            },
            BOX:{
                position:'relative',
                left:0,
                top:0,
                width:'100%',
                height:'100%'
            },
            'BOX-h DECREASE, BOX-h INCREASE':{
                top:'50%',
                width:'17px',
                height:'17px',
                'margin-top':'-8px'
            },            
            'BOX-v DECREASE, BOX-v INCREASE, BOX-h DECREASE, BOX-h INCREASE, BOX-h IND1,BOX-h IND2, BOX-v IND1,BOX-v IND2':{
                background: linb.UI.$bg('icons.gif', 'no-repeat',true)
            },
            'BOX-h DECREASE':{
                $order:1,
                left:0,
                'background-position': '-80px -70px'
            },
            'BOX-h INCREASE':{
                $order:1,
                right:0,
                'background-position': '-100px -70px'
            },
            'BOX-h DECREASE-mouseover':{
                $order:2,
                'background-position':'-80px -90px'
            },
            'BOX-h DECREASE-mousedown':{
                $order:3,
                'background-position':'-80px -110px'
            },
            'BOX-h INCREASE-mouseover':{
                $order:2,
                'background-position':'-100px -90px'
            },
            'BOX-h INCREASE-mousedown':{
                $order:3,
                'background-position':'-100px -110px'
            },
            'BOX-h BG':{
                top:'50%'                
            },
            'BOX-h IND, BOX-h RULER':{
                'z-index':1,
                top:'50%',
                height:'6px',
                'margin-top':'-3px'
            },
            'BOX-h RULER, BOX-h RULERLEFT, BOX-h RULERRIGHT':{
                background: linb.UI.$bg('bar_vertical.gif', 'repeat-x',true)
            },
            'BOX-h RULER':{
                $order:2,
                'background-position':'left -482px'
            },
            'BOX-h RULERLEFT, BOX-h RULERRIGHT':{
                'z-index':1,
                height:'6px',
                width:'5px'
            },
            'BOX-h RULERLEFT':{
                $order:2,
                'background-position':'left -474px',
                left:'-4px',
                top:0
            },
            'BOX-h RULERRIGHT':{
                $order:2,
                'background-position':'left -490px',
                right:'-4px',
                top:0
            },
            'BOX-h IND1,BOX-h IND2':{
                $order:1,
                'z-index':2,
                'background-position': '-21px -282px',
                height:'18px',
                width:'8px',
                left:0,
                top:0,
                'margin-top':'-6px'
            },
            'BOX-h IND1-mouseover,BOX-h IND2-mouseover':{
                $order:2,
                'background-position':'-31px -282px'
            },
            'BOX-h IND1-mousedown,BOX-h IND2-mousedown':{
                $order:3,
                'background-position':'-41px -282px'
            },

            'BOX-v DECREASE, BOX-v INCREASE':{
                $order:10,
                left:'50%',
                width:'17px',
                height:'17px',
                'margin-left':'-8px'
            },            
            'BOX-v DECREASE':{
                $order:10,
                top:0,
                'background-position': '-120px -70px'
            },
            'BOX-v INCREASE':{
                $order:10,
                bottom:0,
                'background-position': '-140px -70px'
            },
            'BOX-v DECREASE-mouseover':{
                $order:11,
                'background-position':'-120px -90px'
            },
            'BOX-v DECREASE-mousedown':{
                $order:12,
                'background-position':'-120px -110px'
            },
            'BOX-v INCREASE-mouseover':{
                $order:11,
                'background-position':'-140px -90px'
            },
            'BOX-v INCREASE-mousedown':{
                $order:12,
                'background-position':'-140px -110px'
            },
            'BOX-v BG':{
                $order:10,
                left:'50%'                
            },
            'BOX-v IND, BOX-v RULER':{
                $order:10,
                'z-index':1,
                left:'50%',
                width:'6px',
                'margin-left':'-3px'
            },
            'BOX-v RULER, BOX-v RULERLEFT, BOX-v RULERRIGHT':{
                background: linb.UI.$bg('bar_horizontal.gif', 'repeat-y',true)
            },
            'BOX-v RULER':{
                $order:10,
                'background-position':'-482px top'
            },
            'BOX-v RULERLEFT, BOX-v RULERRIGHT':{
                $order:10,
                'z-index':1,
                width:'6px',
                height:'5px'
            },
            'BOX-v RULERLEFT':{
                $order:12,
                'background-position':'-490px top',
                top:'-4px',
                left:0
            },
            'BOX-v RULERRIGHT':{
                $order:12,
                'background-position':'-474px top',
                bottom:'-4px',
                left:0
            },
            'BOX-v IND1,BOX-v IND2':{
                $order:10,
                'z-index':2,
                'background-position': 'left -272px',
                width:'18px',
                height:'8px',
                left:0,
                top:0,
                'margin-left':'-6px'
            },
            'BOX-v IND1-mouseover,BOX-v IND2-mouseover':{
                $order:11,
                'background-position':'left -282px'
            },
            'BOX-v IND1-mousedown,BOX-v IND2-mousedown':{
                $order:12,
                'background-position':'left -292px'
            }
        },
        Behaviors:{
            HoverEffected:{IND1:'IND1',IND2:'IND2',DECREASE:'DECREASE',INCREASE:'INCREASE'},
            ClickEffected:{IND1:'IND1',IND2:'IND2',DECREASE:'DECREASE',INCREASE:'INCREASE'},
            onSize:linb.UI.$onSize,
            IND:{
                onClick:function(profile, e, src){
                    var p=profile.properties,
                        p1=linb.use(src).offset(),
                        p2=linb.Event.getPos(e),
                        arr=profile.box._v2a(profile,profile.properties.$UIvalue),
                        i1,i2,
                        type=p.type=='vertical',
                        k1=type?'top':'left',
                        k2=type?'offsetTop':'offsetLeft',
                        k3=type?'offsetHeight':'offsetWidth',
                        cur=p2[k1]-p1[k1],
                        v=(cur/linb.use(src).get(0)[k3])*100;
                    if(!p.isRange)
                        arr[0]=v;
                    else{
                        i1=profile.getSubNode('IND1')[k2](),
                        i2=profile.getSubNode('IND2')[k2]();
                        if(Math.abs(i1-cur)<Math.abs(i2-cur))
                            arr[0]=v;
                        else arr[1]=v;
                    }
                    profile.boxing().setUIValue(profile.box._adjustValue(profile,arr));
                }
            },
            IND1:{
                onKeydown:function(profile, e, src){
                    var p=profile.properties,
                        type=p.type=='vertical',
                        key=linb.Event.getKey(e)[0];
                    if(key==(type?'up':'left'))
                        profile.box._auto(profile, false);
                    if(key==(type?'down':'right'))
                        profile.box._auto(profile, true);
                },
                onKeyout:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onKeyup:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMousedown:function(profile, e, src){
                    var p=profile.properties,
                        type=p.type=='vertical',
                        k2=type?'offsetTop':'offsetLeft',
                        k3=type?'offsetHeight':'offsetWidth',
                        box=profile.box;
                    linb.use(src).startDrag(e,{
                        widthIncrement:p.steps?profile._size/p.steps:null,
                        dragType:'none',
                        targetReposition:true,
                        horizontalOnly:type?true:null,
                        verticalOnly:type?null:true,
                        maxLeftOffset: linb.use(src).get(0)[k2],
                        maxRightOffset: linb.use(src).parent().get(0)[k3]-linb.use(src).get(0)[k2],
                        dragCursor:'default'
                    });

                    linb.use(src).css('zIndex',10).focus();
                    profile.getSubNode('IND2').css('zIndex',5);
                },
                beforeDragbegin:function(profile, e, src){
                    var type=profile.properties.type=='vertical';
                    linb(src)[type?'top':'left'](profile.__x=linb.use(src).get(0)[type?'offsetTop':'offsetLeft']);
                },
                onDrag:function(profile, e, src){
                    var offset=linb.DragDrop.getProfile().offset,
                        type=profile.properties.type=='vertical',
                        arr=profile.box._v2a(profile,profile.properties.$UIvalue);
                    arr[0]=((profile.__x+offset[type?'y':'x'])/linb.use(src).parent().get(0)[type?'offsetHeight':'offsetWidth'])*100;
                    profile.boxing().setUIValue(profile.box._adjustValue(profile,arr));
                },
                onDragstop:function(profile, e, src){
                    linb(src).onMouseout(true,{$force:true}).onMouseup(true);
                },
                onClick:function(){return false}
            },
            IND2:{
                onKeydown:function(profile, e, src){
                    var p=profile.properties,
                        type=p.type=='vertical',
                        key=linb.Event.getKey(e)[0];
                    if(key==(type?'up':'left'))
                        profile.box._auto(profile, false);
                    if(key==(type?'down':'right'))
                        profile.box._auto(profile, true);
                },
                onKeyout:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onKeyup:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMousedown:function(profile, e, src){
                    var p=profile.properties,
                        type=p.type=='vertical',
                        k2=type?'offsetTop':'offsetLeft',
                        k3=type?'offsetHeight':'offsetWidth',
                        box=profile.box;
                    linb.use(src).startDrag(e,{
                        widthIncrement:p.steps?profile._size/p.steps:null,
                        dragType:'none',
                        targetReposition:true,
                        horizontalOnly:type?true:null,
                        verticalOnly:type?null:true,
                        maxLeftOffset: linb.use(src).get(0)[k2],
                        maxRightOffset: linb.use(src).parent().get(0)[k3]-linb.use(src).get(0)[k2],
                        dragCursor:'default'
                    });

                    linb.use(src).css('zIndex',10).focus();
                    profile.getSubNode('IND1').css('zIndex',5);
                },
                beforeDragbegin:function(profile, e, src){
                    var type=profile.properties.type=='vertical';
                    linb(src)[type?'top':'left'](profile.__x=linb.use(src).get(0)[type?'offsetTop':'offsetLeft']);

                },
                onDrag:function(profile, e, src){
                    var offset=linb.DragDrop.getProfile().offset,
                        type=profile.properties.type=='vertical',
                        arr=profile.box._v2a(profile,profile.properties.$UIvalue);
                    arr[1]=((profile.__x+offset[type?'y':'x'])/linb.use(src).parent().get(0)[type?'offsetHeight':'offsetWidth'])*100;
                    profile.boxing().setUIValue(profile.box._adjustValue(profile,arr));
                },
                onDragstop:function(profile, e, src){
                    linb(src).onMouseout(true,{$force:true}).onMouseup(true);
                },
                onClick:function(){return false}
            },
            RULERRIGHT:{
                onClick:function(profile, e, src){
                    var p=profile.properties,
                        b=profile.boxing(),
                        c=profile.box,
                        arr=c._v2a(profile,p.$UIvalue);
                    if(!p.isRange)
                        arr[0]=100;
                    else
                        arr[1]=100;
                    b.setUIValue(profile.box._adjustValue(profile,arr));
                }
            },
            DECREASE:{
                onMousedown:function(profile){
                    profile.box._auto(profile, false);
                },
                onMouseout:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMouseup:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                }
            },
            INCREASE:{
                onMousedown:function(profile){
                    profile.box._auto(profile, true);
                },
                onMouseout:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMouseup:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                }
            }
        },
        DataModel:{
            position:'absolute',
            width:{
                ini:200
            },
            height:{
                ini:50
            },
            steps:0,
            value:'0:0',
            type:{
                listbox:['vertical', 'horizontal'],
                ini:'horizontal',
                action:function(v){
                    this.boxing().refresh();
                }
            },
            isRange:{
                ini:true,
                action:function(v){
                    this.boxing().refresh();
                }
            },
            showIncreaseHandle:{
                ini:true,
                action:function(v){
                    this.boxing().refresh();
                }
            },
            showDecreaseHandle:{
                ini:true,
                action:function(v){
                    this.boxing().refresh();
                }
            }
        },
        _prepareData:function(profile){
            var d=arguments.callee.upper.call(this, profile),
                N='display:none';
            d._showDes=d.showDecreaseHandle?'':N,
            d._showIns=d.showIncreaseHandle?'':N,
            d._showD2=d.isRange?'':N;
            d._cls=profile.getClass('BOX',d.type=='vertical'?'-v':'-h');
            return d;
        },
        _adjustValue:function(profile,value){
            var p = profile.properties,
                b=[];
            b[0]=parseFloat(value[0])||0;
            b[1]=parseFloat(value[1])||0;
            if(p.steps){
                value=100/p.steps;
                b[0]=Math.ceil(b[0]/value);
                if(p.isRange)
                    b[1]=Math.ceil(b[1]/value);
            }
            return b.join(':');
        },
        _ensureValue:function(profile, value){
            var p = profile.properties,
                a = String(value).split(':'),
                min=0,
                max=p.steps?p.steps:100,
                b=[],
                f1=function(a){return parseFloat(a)||0},
                f2=function(a){return Math.min(max, Math.max(min,a))};
            b[0]= f1(a[0]);
            if(p.isRange){
                b[1]= f1(a[1]);
                if(b[0]>b[1]){
                    a=b[1];
                    b[1]=b[0];
                    b[0]=a;
                }
            }
            b[0]= f2(b[0]);
            if(p.isRange)
                b[1]= f2(b[1]);
            return p.isRange?b.join(':'):(b[0]+'');
        },
        _v2a:function(profile,v){
            var steps=profile.properties.steps,t;
            v = typeof v == 'string'? v.split(':') : v;
            v[0]=parseFloat(v[0])||0;v[1]=parseFloat(v[1])||0;
            if(steps)v[0]=v[0]*100/steps;
            if(steps)v[1]=v[1]*100/steps;
            if(v[0]>v[1]){
                t=v[0];
                v[1]=v[0];
                v[0]=t;
            }
            return v;
        },
        _auto:function(profile, flag){
            var id=profile.$linbid+':auto';
            if(linb.Thread.isAlive(id))return;
            var p=profile.properties,t,
                //%
                off=(p.steps?100/p.steps:1)*(flag?1:-1),
                task={delay:300},
                arr=profile.box._v2a(profile,p.$UIvalue),
                fun=function(){
                    arr[0] += off;
                    if(p.isRange)
                        arr[1] += off;
                    profile.boxing().setUIValue(profile.box._adjustValue(profile,arr));
                    task.delay *=0.8;
                };
            task.task=fun;
            linb.Thread(id,[task],500,null,fun,null,true).start();
        },
        _onresize:function(profile, width, height){
            var p=profile.properties,
            type=p.type,
            f=function(k){return profile.getSubNode(k)},

            ruler=f('RULER'),
            ind=f('IND'),

            ru1=f('RULERLEFT');
            if(type=='vertical'){
                var w=ru1.height(),
                w1=p.showDecreaseHandle?f('DECREASE').height():0,
                w2=p.showIncreaseHandle?f('INCREASE').height():0,
                w3=f('IND1').height();
    
                if(height){
                    ruler.top(w1+w).height(height-w1-w2-2*w);
                    ind.top(w1).height(profile._size=height-w1-w2-w3);
                }
            }else{
                var w=ru1.width(),
                w1=p.showDecreaseHandle?f('DECREASE').width():0,
                w2=p.showIncreaseHandle?f('INCREASE').width():0,
                w3=f('IND1').width();
    
                if(width){
                    ruler.left(w1+w).width(width-w1-w2-2*w);
                    ind.left(w1).width(profile._size=width-w1-w2-w3);
                }
            }
        }
    }
});Class("linb.UI.Input", ["linb.UI.Widget","linb.absValue"] ,{
    Instance:{
        _setTB:function(type){
            var profile=this.get(0), p=profile.properties, o, t;
            if(!profile.host|| !p.tipsBinder)return;

            t = profile.tips = profile.tips||p.tips||'';
            o = linb.getObject(p.tipsBinder)|| ((o=profile.host[p.tipsBinder]) &&o.get(0) );
            if(o && (o.key=='linb.UI.Div'||o.key=='linb.UI.SLabel')){
                if(o.renderId){
                    //use innerHTML, not setHtml
                    o.getRootNode().innerHTML =  t.charAt(0)=='$'?linb.wrapRes(t):t;
                    o.getRoot().css('color', type==1?'gray':type==2?'red':'#000');
                }
            }
        },
        activate:function(){
            var profile = this.get(0);
            if(profile.renderId){
                var node=profile.getSubNode('INPUT').get(0);
                node.focus();
                if(!node.readOnly && node.select)node.select();
            }
            return this;
        },
        _setCtrlValue:function(value){
            if(_.isNull(value) || !_.isDefined(value))value='';
            return this.each(function(profile){
                profile.getSubNode('INPUT').attr('value',value+"");
            });
        },
        _getCtrlValue:function(){
            return this.getSubNode('INPUT').attr('value');
        },
        _setDirtyMark:function(){
            return this.each(function(profile){
                if(!profile.properties.dirtyMark)return;
                var properties = profile.properties,
                    o=profile.getSubNode('INPUT'),
                    cls=profile.box,
                    box=profile.boxing(),
                    d=linb.UI.$css_tag_dirty,
                    v=linb.UI.$css_tag_invalid,
                    flag=properties.value !== properties.$UIvalue;
                //dirty mark
                if(profile.beforeDirtyMark && false===box.beforeDirtyMark(profile,flag)){}
                else{
                    if(flag)
                        o.addClass(d);
                    else
                        o.removeClass(d);
                }
                //format statux
                if(profile.beforeFormatMark && false===box.beforeFormatMark(profile, profile.inValid==2)){}
                else{
                    var err = profile.getSubNode('ERROR');
                    if(profile.inValid==2){
                        o.addClass(v);
                        err.css('display','block');
                    }else{
                        o.removeClass(v);
                        err.css('display','none');
                    }
                }
                if(profile.inValid==2){
                    //display tips
                    profile.tips = properties.tipsErr || properties.tips;
                    if(properties.mask)
                        _.asyRun(function(){
                            box.setUIValue(o.get(0).value=profile.$Mask)
                        });
                }else{
                    if(profile.inValid==1)
                        profile.tips = properties.tips;
                    else{
                        profile.tips = properties.tipsOK || properties.tips;
                    }
                }
                box._setTB(profile.inValid);
            });
        }
    },
    Initialize:function(){
        //modify default template fro shell
        var t = this.getTemplate();
        _.merge(t.FRAME.BORDER,{
            style:'',
            BOX:{
                WRAP:{
                    tagName : 'div',
                    INPUT:{
                        tagName : 'input',
                        type : '{_type}',
                        tabindex:'{tabindex}',
                        cursor:'{cursor}',
                        style:'{_css}'
                    }
                }
            }
        },'all');
        t.FRAME.ERROR = {};
        this.setTemplate(t)
    },
    Static:{
        _maskMap:{
            '~':'[+-]',
    		'1':'[0-9]',
    		'a':'[A-Za-z]',
    		'*':'[A-Za-z0-9]'
        },
        _maskSpace:'_',
        Appearances:{
            KEY:{
                'font-family': '"Verdana", "Helvetica", "sans-serif"',
                position:'relative'
            },
            BORDER:{
                'line-height':'0px',
                'font-size':'0px'
            },
            WRAP:{
                left:0,
                //for firefox bug: cursor not show
                position:'absolute',
                overflow:linb.browser.gek?'auto':'hidden'
            },
            BOX:{
                left:0,
                top:0,
                position:'absolute',
                'background-color':'#fff',
                'border':'solid 1px #648CB4',
                'z-index':10
            },
            'BOX-focus, BOX-mouseover':{
                'border-color':'#FAE100'
            },
            INPUT:{
               //don't change it in custom class or style
               'padding-top':'2px',
               'padding-left':'2px',

               'background-color':'#fff',
               border:0,
               margin:0,

               'margin-top':linb.browser.ie?'-1px':null,
               'font-size':'12px',
               position:'relative',
               //give default size
               width:'102px',

               overflow:'auto',
               'overflow-y':'auto',
               'overflow-x':'hidden'
            },
            ERROR:{
                width:'16px',
                height:'16px',
                position:'absolute',
                right:'2px',
                top:'2px',
                display:'none',
                'font-size':0,
                background: linb.UI.$bg('icons.gif', 'no-repeat left -244px', true),
                'z-index':'50'
            },
//border<<<
            '.setting-linb-input':{
                'border-style':'solid',
                'border-top-width':'1px',
                'border-bottom-width':'1px',
                'border-left-width':'1px',
                'border-right-width':'1px'
            },
            'KEY-b-t':{
                height:'2px',
                top:'-1px',
                background: linb.UI.$bg('vertical.gif', 'repeat-x left top','Input')
            },
            'KEY-b-b':{
                height:'2px',
                bottom:'-1px',
                background: linb.UI.$bg('vertical.gif', 'repeat-x left bottom','Input')
            },
            'BOX-focus KEY-b-t, BOX-focus KEY-b-b, BOX-mouseover KEY-b-t, BOX-mouseover KEY-b-b':{
                $order:1,
                'background-image':linb.UI.$bg('vertical_mouseover.gif','','Input')
            },
            'KEY-b-l':{
                width:'2px',
                left:'-1px',
                background: linb.UI.$bg('horizontal.gif', 'repeat-y left top','Input')
            },
            'KEY-b-r':{
               width:'2px',
               right:'-1px',
               background: linb.UI.$bg('horizontal.gif', 'repeat-y right top','Input')
            },
            'BOX-focus KEY-b-l, BOX-focus KEY-b-r, BOX-mouseover KEY-b-l, BOX-mouseover KEY-b-r':{
                $order:1,
                'background-image': linb.UI.$bg('horizontal_mouseover.gif','','Input')
            },
            'KEY-b-lt':{
                width:'2px',
                height:'2px',
               left:'-1px',
               top:'-1px',
                background: linb.UI.$bg('corner.gif', 'no-repeat left top','Input')
            },
            'KEY-b-rt':{
               width:'2px',
               height:'2px',
               right:'-1px',
               top:'-1px',
               background: linb.UI.$bg('corner.gif', 'no-repeat right top','Input')
            },
            'KEY-b-rb':{
                width:'2px',
                height:'2px',
                right:'-1px',
                bottom:'-1px',
                background: linb.UI.$bg('corner.gif', 'no-repeat right bottom','Input')
            },
            'KEY-b-lb':{
                width:'2px',
                height:'2px',
                left:'-1px',
                bottom:'-1px',
                background: linb.UI.$bg('corner.gif', 'no-repeat left bottom','Input')
            },
            'BOX-focus KEY-b-lt, BOX-focus KEY-b-rt, BOX-focus KEY-b-rb, BOX-focus KEY-b-lb, BOX-mouseover KEY-b-lt, BOX-mouseover KEY-b-rt, BOX-mouseover KEY-b-rb, BOX-mouseover KEY-b-lb':{
                $order:1,
                'background-image': linb.UI.$bg('corner_mouseover.gif','','Input')
            }
//border>>>
        },
        Behaviors:{
            HoverEffected:{BOX:['BOX']},
            NavKeys:{INPUT:1},
            INPUT:{
                onChange:function(profile, e, src){
                    var p=profile.properties,b=profile.box,
                        o=profile.inValid,
                        value=linb.use(src).get(0).value;

                    profile.boxing().setUIValue(value);
                    //input/textarea is special, ctrl value will be set before the $UIvalue
                    p.$UIvalue=value;
                    if(o!==profile.inValid) if(profile.renderId)profile.boxing()._setDirtyMark();

                    b._asyCheck(profile);
                },
                //if properties.mask exists, onHotKeyxxx wont be tigger any more
                onKeydown:function(profile, e, src){
                   var p=profile.properties,b=profile.box,
                        m=p.multiLines,
                        evt=linb.Event,
                        k=evt.getKey(e);
                    //fire onchange first
                    if(k[0]=='enter'&& (!m||k[3]))
                        linb.use(src).onChange();

                    b._asyCheck(profile);

                    if(p.mask){
                        if(k[0].length>1)profile.$ignore=true;
                        else delete profile.$ignore;
                        switch(k[0]){
                            case 'backspace':
                                b._changeMask(profile,linb.use(src).get(0),'',false);
                                return false;
                            case 'delete':
                                b._changeMask(profile,linb.use(src).get(0),'');
                                return false;
                        }
                    }
                },
                onKeypress:function(profile, e, src){
                    var p=profile.properties,b=profile.box,cls=profile.box,map=cls._maskMap;

                    b._asyCheck(profile);

                    if(p.mask){
                        if(profile.$ignore){
                            delete profile.$ignore;
                            return true;
                        }
                        var evt=linb.Event,
                            k=evt.getKey(e);
                        if(k[1]||k[3])return true;

                        cls._changeMask(profile,linb.use(src).get(0),k[0],true);
                        return false;
                    }
                },
                onKeyup:function(profile, e, src){
                    var p=profile.properties,b=profile.box;
                    if(p.dynCheck){
                        profile.box._checkValid(profile, linb.use(src).get(0).value);
                        profile.boxing()._setDirtyMark();
                    }

                    b._asyCheck(profile);
                },
                onFocus:function(profile, e, src){
                    var p=profile.properties,b=profile.box;
                    if(p.disabled)return false;
                    if(profile.onFocus)profile.boxing().onFocus(profile);
                    profile.getSubNode('BORDER').tagClass('-focus');
                    //if no value, add mask
                    if(p.mask){
                        var value=linb.use(src).get(0).value;
                        if(!value)
                            _.asyRun(function(){
                                profile.boxing().setUIValue(value=profile.$Mask);
                                b._setCaret(profile,linb.use(src).get(0))
                            });
                    }
                    //show tips color
                    profile.boxing()._setTB(3);

                    b._asyCheck(profile);
                },
                onBlur:function(profile, e, src){
                    var p=profile.properties,b=profile.box;
                    if(p.disabled)return false;
                    if(profile.onBlur)profile.boxing().onBlur(profile);

                    profile.getSubNode('BORDER').tagClass('-focus',false);
                    var value=linb.use(src).get(0).value;
                    //onblur check it
                    if(p.$UIvalue==value)
                        profile.box._checkValid(profile, value);
                    profile.boxing()._setDirtyMark();

                    b._asyCheck(profile);
                }
            }
        },
        DataModel:{
            _customBorder:'BOX',
            tipsErr:'',
            tipsOK:'',
            border:true,

            dynCheck:false,
            valueFormat:{
                helpinput:[
                    {caption : 'required', id: "[^.*]"},
                    {caption : 'email',id:"^[\\w\\.=-]+@[\\w\\.-]+\\.[\\w\\.-]{2,4}$"},
                    {caption : 'charOnly',id:"^[a-zA-Z]*$"},
                    {caption : 'words',id:"^[\\w ]*$"},
                    {caption : 'integer',id:"^-?\\d\\d*$"},
                    {caption : 'positiveInteger',id:"^\\d\\d*$"},
                    {caption : 'number',id:"^-?(\\d\\d*\\.\\d*$)|(^-?\\d\\d*$)|(^-?\\.\\d\\d*$)"},
                    {caption : 'filepath',id:"([\\/]?[\\w_]+)+\\.\\w{1,9}$"},
                    {caption : 'URL', id:"^(http|https|ftp)\\:\\/\\/[\\w\\-\\_\\.]+[\\w\\-\\_](:[\\w]*)?\\/?([\\w\\-\\._\\?\\,\\'\\/\\\\\\+&amp;%\\$#\\=~])*$"},
                    {caption : 'color',id:"^\\#[0-9A-Fa-f]{6}$"},
                    {caption : "HH:MM", id:"^\(\([0-1][0-9]\)|\([2][0-3])\)\:\([0-5][0-9]\)$"},
                    {caption : "HH:MM:SS", id:"^\(\([0-1][0-9]\)|\([2][0-3])\)\:\([0-5][0-9]\)\\:\([0-5][0-9]\)$"},
                    {caption : "YYYY-MM-DD",id:"^\([0-9]{4}\)\\-\(\([0][0-9]\)|\([1][0-2]\)\)\\-\([0-3][0-9]\)$"},
                    {caption : "DD/MM/YYYY",id:"^\(\([0-2][0-9]\)|\([3][0-1]\)\)\/\(\([0][0-9]\)|\([1][0-2]\)\)\/\([0-9]{4}\)$"}
                ]
            },
            mask:{
                action:function(value){
                    var ns=this,
                        b=ns.box;
                    if(value){
                        ns.$MaskFormat=function(ns, v){
                            var m=ns._maskMap,a=[],r=/[A-Za-z0-9]/;
                            _.arr.each(v.split(''),function(o,i){
                                a.push(m[o]||(r.test(o)?"":"\\")+o)
                            });
                            return '^'+a.join('')+'$';
                        }(b, value);
                        ns.$Mask = function(ns, v){
                            var m=ns._maskMap,a=[],s=ns._maskSpace;
                            _.arr.each(v.split(''),function(o,i){
                                a.push(m[o]?s:o);
                            });
                            return  a.join('');
                        }(b,value);

                        //visibility mask string
                        ns.boxing()._setCtrlValue(ns.$Mask);
                   }else{
                        delete ns.$MaskFormat;
                        delete ns.$Mask;
                   }
                }
            },
            value:'',
            width:120,
            height:22,
            disabled:{
                ini:false,
                action: function(v){
                    this.getRoot().css('opacity',v?0.5:1);
                    this.getSubNode('INPUT').attr('disabled',v);
                }
            },
            readonly:{
                ini:false,
                action: function(v){
                    this.getSubNode('INPUT').attr('readonly',v).css('cursor',v?'default':'');
                }
            },
            type:{
                ini:'text',
                listbox:['text','password'],
                action: function(value){
                    this.getSubNode('INPUT').attr('type',value);
                }
            },
            multiLines:{
                ini:false,
                action: function(value){
                    this.boxing().refresh();
                }
            },
            tipsBinder:{
                ini:'',
                set:function(value){
                    if(value['linb.UIProfile'])
                        value=value.$linbid;
                    if(value['linb.UI'] && (value=value.get(0)))
                        value=value.$linbid;
                    this.properties.tipsBinder = value +'';
                }
            }
        },
        EventHandlers:{
            onFocus:function(profile){},
            onBlur:function(profile){},
            onChange:function(profile, value){},
            beforeFormatCheck:function(profile, value){},
            beforeFormatMark:function(profile, formatErr){}
        },
        _prepareData:function(profile){
            var d=arguments.callee.upper.call(this, profile);
            d.cursor = d.readonly?'default':'';
            d._type = d.type || '';
            if(linb.browser.kde)
                d._css='resize:none;';
            return d;
        },
        _dynamicTemplate:function(profile){
            var properties = profile.properties,t,
                hash = profile._exhash = "$" +'multiLines:'+properties.multiLines,
                template = profile.box.getTemplate(hash);

            properties.$UIvalue = properties.value;

            // set template dynamic
            if(!template){
                template = _.clone(profile.box.getTemplate());
                if(properties.multiLines){
                    t=template.FRAME.BORDER.BOX.WRAP.INPUT;
                    t.tagName='textarea';
                    delete t.type;
                }

                // set template
                profile.box.setTemplate(template, hash);
            }
            profile.template = template;
        },
        RenderTrigger:function(){
            var ns=this,p=ns.properties;
            _.asyRun(function(){
                ns.boxing()._setTB(1);
            });
            ns.getSubNode('WRAP').$firfox2();
            if(p.readonly)
                ns.boxing().setReadonly(true,true);
            if(p.tipsBinder)
                ns.boxing().setTipsBinder(p.tipsBinder,true);
            //add event for cut/paste text
            var ie=linb.browser.ie,
                src=ns.getSubNode('INPUT').get(0),
                b=ns.box,
                f=function(o){
                    if(ie && ('propertyName' in o) && o.propertyName!='value')return;
                    b._asyCheck(ns);
                };
            if(ie){
                src.attachEvent("onpropertychange",f);
                src.attachEvent("ondrop",f);
                ns.$ondestory=function(){
                    var ns=this,
                        src=ns.getSubNode('INPUT').get(0);
                    src.detachEvent("onpropertychange",f);
                    src.detachEvent("ondrop",f);
                    src=null;
                }
            }else{
                src.addEventListener("input",f,false);
                //firefox drop
                if(linb.browser.gek)
                    src.addEventListener("dragdrop",f,false);

                ns.$ondestory=function(){
                    var ns=this,
                        src=ns.getSubNode('INPUT').get(0);
                    src.removeEventListener("input",f,false);
                    if(linb.browser.gek)
                        src.removeEventListener("dragdrop",f,false);
                    src=null;
                }
            }
            src=null;
        },
        LayoutTrigger:function(){
            var p = this.properties;
            if(p.mask)this.boxing().setMask(p.mask,true);
        },
    //v=value.substr(0,caret);
    //i=v.lastIndexOf(ms);

        _changeMask:function(profile,src,v,dir){
            var ns=this,
                p=profile.properties,
                map=ns._maskMap,
                ms=ns._maskSpace,
                maskTxt=p.mask,
                maskStr = profile.$Mask,
                input = linb(src),
                caret = input.caret();
            //for backspace
            if(dir===false && caret[0]==caret[1] && caret[0]>0)
                input.caret(caret[0]-1,caret[0]);

            //for delete
            if(dir===undefined && caret[0]==caret[1])
                input.caret(caret[0],caret[0]+1);

            //for caret is from a fix char, nav to the next 'input allow' char
            if(dir===true){
                if(maskStr.charAt(caret[0])!=ms){
                    var from = caret[0] + maskStr.substr(caret[0],maskStr.length).indexOf(ms);
                    input.caret(from,Math.max(caret[1],from))
                }
            }

            var caret = input.caret(),
                value=src.value,
                reg = ns._maskMap[p.mask.charAt(caret[0])],
                i,t;
            if(reg && new RegExp('^'+reg+'$').test(v) || v==''){
                t=value;
                //if select some text
                if(caret[0]!=caret[1])
                    t=t.substr(0,caret[0]) + maskStr.substr(caret[0],caret[1]-caret[0]) + t.substr(caret[1],t.length-caret[1]);
                //if any char input
                if(v)
                    t=t.substr(0,caret[0])+v+t.substr(caret[0]+1,t.length-caret[0]-1);

                //get corret string according to maskTxt
                var a=[];
                _.arr.each(maskTxt.split(''),function(o,i){
                    a.push( (new RegExp('^'+(map[o]?map[o]:'\\'+o)+'$').test(t.charAt(i))) ? t.charAt(i) : maskStr.charAt(i))
                });

                //if input visible char
                if(dir===true){
                    v=maskStr.substr(caret[0]+1,value.length-caret[0]-1);
                    i=v.indexOf(ms);
                    i=caret[0] + (i==-1?0:i) + 1;
                }else
                    i=caret[0];
                //in opera, delete/backspace cant be stopbubbled
                //add a dummy maskSpace
                if(linb.browser.opr){
                    //delete
                    if(dir===undefined)
                        _.arr.insertAny(a,ms,i);
                    //backspace
                    if(dir===false)
                        _.arr.insertAny(a,ms,i++);
                }
                profile.boxing().setUIValue(src.value=a.join(''));
                ns._setCaret(profile,src,i);
            }

        },
        _setCaret:function(profile, src, pos){
            if(profile.properties.mask){
                if(typeof pos !='number')
                    pos=src.value.indexOf(this._maskSpace);
                linb(src).caret(pos,pos);
            }
        },
        //check valid manually
        _checkValid:function(profile, value){
            var p=profile.properties,
                vf1 = (p.mask&&profile.$MaskFormat) ,
                vf2 = p.valueFormat || profile.$valueFormat;
            if( (profile.beforeFormatCheck && (profile.boxing().beforeFormatCheck(profile, value)===false)) ||
                (vf1 && typeof vf1=='string' && !(new RegExp(vf1)).test((value===0?'0':value)||'')) ||
                (vf2 && typeof vf2=='string' && !(new RegExp(vf2)).test((value===0?'0':value)||''))
            ){
                profile.inValid=2;
                return false;
            }{
                profile.inValid=3;
                return true;
            }
        },
        _asyCheck:function(profile){
            _.resetRun(profile.$linbid+":asycheck",function(){
                var src=profile.getSubNode("INPUT").get(0);
                if(!src)return;

                //for onchange event
                if(profile.onChange){
                    if(profile.$$$v!==src.value)
                        profile.boxing().onChange(profile,profile.$$$v=src.value);
                }

                //for mask
                if(profile.properties.mask){
                    if(src.value.length != profile.$Mask.length)
                        profile.box._changeMask(profile,src,'',true);
                }
            });
        },
        _onresize:function(profile,width,height){
                var $hborder=1, $vborder=1,
                    toff=linb.UI.$getCSSValue('linb-input-input','paddingTop'),
                    loff=linb.UI.$getCSSValue('linb-input-input','paddingTop');

                var t = profile.properties,
                    o = profile.getSubNode('BOX'),
                    v1=profile.getSubNode('INPUT'),
                    region,
                    ww=width,
                    hh=height,
                    left=Math.max(0, (t.$b_lw||0)-$hborder),
                    top=Math.max(0, (t.$b_tw||0)-$vborder);
                if(null!==ww){
                    ww -= Math.max($hborder*2, (t.$b_lw||0)+(t.$b_rw||0));
                    /*for ie6 bug*/
                    /*for example, if single number, 100% width will add 1*/
                    /*for example, if single number, attached shadow will overlap*/
                    if(linb.browser.ie6)ww=(parseInt(ww/2))*2;
                }
                if(null!==hh){
                    hh -=Math.max($vborder*2, (t.$b_lw||0) + (t.$b_rw||0));

                    if(linb.browser.ie6)hh=(parseInt(hh/2))*2;
                    /*for ie6 bug*/
                    if(linb.browser.ie6&&null===width)o.ieRemedy();
                }
                region={left:left,top:top,width:ww,height:hh};
                o.cssRegion(region);   
                if(ww||hh)
                    v1.cssSize({width:ww?(ww-loff):null,height:hh?(hh-toff):null});

                /*for ie6 bug*/
                if((profile.$border||profile.$shadow||profile.$resizer) && linb.browser.ie)o.ieRemedy();
        }
    }
});Class("linb.UI.RichEditor", ["linb.UI","linb.absValue"],{
    Initialize:function(){
        this.addTemplateKeys(['TOOLBARBTN']);
    },
    Instance:{
        _setCtrlValue:function(value){
            if(_.isNull(value) || !_.isDefined(value))value='';
            return this.each(function(profile){
                var doc=profile.$doc, body=doc && (doc.body||doc.documentElement);
                if(body)
                    body.innerHTML=value;
            });
        },
        _getCtrlValue:function(){
            var profile=this.get(0),
                doc=profile.$doc,
                body=doc && (doc.body||doc.documentElement);
             if(body)
                return body.innerHTML;
             return '';
        }
    },
    Static:{
        Templates:{
            tagName:'div',
            style:'{_style}',
            EDITOR:{
                tagName:'div'
            },
            POOL:{}
        },
        DataModel:{
            value:'',
            width:400,
            height:300,
            cmdList:{
                ini:'font1;font2;align;list;font4;font3;insert;clear;html',
                action:function(v){
                    var ns=this;
                    ns.box._iniToolBar(ns);
                }
            },
            disabled:{
                ini:false,
                action: function(v){
                    var ns=this;
                    if(ns.$toolbar)
                        ns.$toolbar.boxing().setDisabled(v);
                    if(ns.$doc)
                        ns.$doc.designMode=v?'off':'on';
                }
            }
        },
        Appearances:{
            POOL:{
                position:'absolute',
                display:'none'
            },
            TOOLBARBTN:{
                background:linb.UI.$bg('toolbar.gif', 'no-repeat')
            },
            EDITOR:{
                position:'absolute',
                display:'block',
                left:0,
                top:0,
                width:'100%',
                height:'100%',
                padding:0,
                margin:0,
                border:'1px solid #648CB4',
                'border-top':'none',
                'background-color':'#fff',
                'z-index':'0'
            }
        },
        Behaviors:{
            onSize:linb.UI.$onSize
        },
        $cmds:{
            //font style
            font1:[
                 {id:'bold',command:'Bold',statusButton:true,imagePos:"-36px 0"},
                 {id:'italic',command:'Italic',statusButton:true,imagePos:"-108px 0"},
                 {id:'underline',command:'Underline',statusButton:true,imagePos:"-324px 0"},
                 {id:'strikethrough',command:'strikeThrough',statusButton:true,imagePos:"-252px 0"}
            ],
            font2:[
                {id:'subscript',command : 'subscript',statusButton:true,imagePos:"-270px 0"},
                {id:'superscript',command : 'superscript',statusButton:true,imagePos:"-288px 0"}
            ],
            font3:[
                {id:'forecolor',command:'custom',imagePos:"0 0"},
                {id:'bgcolor',command:'custom',imagePos:"-18px 0"}
            ],
            font4:[
                {id:'fontsize',command:'custom',caption:'$editor.fontsize',dropButton:true},
                {id:'fontname',command:'custom',caption:'$editor.fontname',dropButton:true},
                {id:'formatblock',command:'custom',caption:'$editor.formatblock',dropButton:true}
            ],
            align:[
                {id:'left',command:'justifyleft',imagePos:"-144px 0"},
                {id:'center',command:'justifycenter',imagePos:"-54px 0"},
                {id:'right',command:'justifyright',imagePos:"-216px 0"},
                {id :'justify', command : 'justifyfull',imagePos:"-126px 0"}
            ],
            list:[
                {id:'indent', command:'indent',imagePos:"-90px 0"},
                {id:'outdent',command:'outdent',imagePos:"-180px 0"},
                {id:'ol',command:'insertorderedlist',imagePos:"-162px 0"},
                {id:'ul',command:'insertunorderedlist',imagePos:"-306px 0"}
            ],
            insert:[
                {id:'hr',command:'insertHorizontalRule',imagePos:"-72px 0"},
                {id:'insertimage',command:'custom',imagePos:"-342px 0"},
                {id:'createlink',command:'custom',imagePos:"-360px 0"},
                {id:'unlink',command:'unlink',imagePos:"-378px 0"}
            ],
            clear:[
                {id:'removeformat',command:'removeformat',imagePos:"-198px 0"}
            ],
            html:[    
                {id:'html',command:'custom', imagePos:"-234px 0"}
            ]
        },
        _updateToolbar:function(domId, clear){
            var profile=linb.$cache.profileMap[domId],toolbar;
            if(profile && (toolbar=profile.$toolbar)){
                var doc=profile.$doc,
                    bold=clear?false:doc.queryCommandState('bold'),
                    italic=clear?false:doc.queryCommandState('italic'),
                    underline=clear?false:doc.queryCommandState('underline'),
                    strikethrough=clear?false:doc.queryCommandState('strikethrough'),
                    subscript=clear?false:doc.queryCommandState('subscript'),
                    superscript=clear?false:doc.queryCommandState('superscript'),

                    tb=toolbar.boxing();

                tb.updateItem('bold',{value:bold})
                tb.updateItem('italic', {value:italic})
                tb.updateItem('underline', {value:underline})
                tb.updateItem('strikethrough', {value:strikethrough})
                tb.updateItem('subscript', {value:subscript})
                tb.updateItem('superscript', {value:superscript})

                doc=null;
            }
        },
        RenderTrigger:function(){
            var self=this;
            self.box._iniToolBar(self);

            if(!self.$inDesign){
                var div=self.getSubNode('EDITOR').get(0),
                    domId=self.$domId,
                    id=div.id,
                    iframe=document.createElement("iframe"),
                    //_updateToolbar event
                    event=self._event=function(e){

                        _.resetRun('RichEditor:'+domId, function(){
                            linb.UI.RichEditor._updateToolbar(domId)
                        },100);

                        //for BlurTrigger
                        if(e.type=='mousedown')
                            linb.doc.onMousedown(true);
                    },
                    doc,
                    checkF = function(){
                        if(frames[id].document!=doc || doc.readyState=='complete'){
                            self.$win=frames[id];
                            self.$doc=doc=frames[id].document;

                            doc.open();
                            doc.write('<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /><style type="text/css">body{border:0;margin:0;padding:0;margin:0;cursor:text;background:#fff;color:#000;padding:3px;}p{margin:0;padding:0;} div{margin:0;padding:0;}</style></head><body>'+self.properties.value+'</body></html>');
                            doc.close();

                            doc.designMode=self.properties.disabled?'off':"on";
                            try{doc.execCommand("styleWithCSS", 0, false)}catch(e){
                                try {doc.execCommand("useCSS", 0, true)}catch(e){}
                            }

                            if(linb.browser.ie){
                                doc.attachEvent("onmousedown",event);
                                doc.attachEvent("ondblclick",event);
                                doc.attachEvent("onclick",event);
                                doc.attachEvent("onkeyup",event);
                                doc.attachEvent("onkeydown",event);
                                self.$beforeDestroy=function(){
                                    var doc=this.$doc,
                                        event=this._event;

                                    doc.detachEvent("onmousedown",event);
                                    doc.detachEvent("ondblclick",event);
                                    doc.detachEvent("onclick",event);
                                    doc.detachEvent("onkeyup",event);
                                    doc.detachEvent("onkeydown",event);
                                    doc=null;
                                }
                            }else{
                                doc.addEventListener("mousedown",event,false);
                                doc.addEventListener("dblclick",event,false);
                                doc.addEventListener("click",event,false);
                                doc.addEventListener("keyup",event,false);

                                if(linb.browser.gek)
                                    doc.addEventListener("keypress",event,false);
                                else
                                    doc.addEventListener("keydown",event,false);

                                //don't ues $ondestory, opera will set doc to null
                                self.$beforeDestroy=function(){
                                    var doc=this.$doc,
                                        event=this._event;

                                    //for firefox
                                    if(linb.browser.gek)
                                        delete frames[this.$frameId];
                                    doc.removeEventListener("mousedown",event,false);
                                    doc.removeEventListener("dblclick",event,false);
                                    doc.removeEventListener("click",event,false);
                                    doc.removeEventListener("keyup",event,false);
                                    if(linb.browser.gek)
                                        doc.removeEventListener("keypress",event,false);
                                    else
                                        doc.removeEventListener("keydown",event,false);
                                    doc=null;
                                }
                            }

                            iframe.style.visibility='';

                            //for disabled
                            if(self.properties.disabled)
                                self.boxing().setDisabled(true,true);

                            event=self=checkF=doc=null;

                            return false;
                        }
                    };
                self.$frameId=id;
                iframe.id=iframe.name=id;
                iframe.className=div.className;
                iframe.src="javascript:false;";
                iframe.frameBorder=0;
                iframe.border=0;
                iframe.marginWidth=0;
                iframe.marginHeight=0;
                iframe.tabIndex=-1;
                iframe.allowTransparency="allowtransparency";
                iframe.style.visibility='hidden';


                //replace the original one
                linb.$cache.domPurgeData[iframe.$linbid=div.$linbid].element=iframe;
                div.parentNode.replaceChild(iframe,div);

                doc=frames[frames.length-1].document;

                linb.Thread.repeat(checkF,50);

                div=null;
            }
        },
        _clearPool:function(profile){
            profile.getSubNode('POOL').empty();
            profile.$colorPicker=profile.$fontsizeList=profile.$fontnameList=profile.$formatblockList=profile.$htmlEditor=null;
        },
        _iniToolBar:function(profile){
            var self=profile,
                pro=self.properties;
            if(self.$toolbar)
                self.$toolbar.boxing().destroy();

            var t,v,o,items=[],
                imageClass=self.getClass('TOOLBARBTN'),
                arr=pro.cmdList.split(';'),
                h={};
            _.arr.each(arr,function(i){
                //filter
                if((o=self.box.$cmds[i]) && !h[i]){
                    h[i]=1;
                    items.push({id:i,sub:o});
                    _.arr.each(o,function(v){
                        if(v.imagePos)
                            v.imageClass=imageClass;
                        v.tips=linb.wrapRes('editor.'+v.id);
                    });
                }
            });

            //compose
            self.getRoot().prepend(
                t=new linb.UI.ToolBar({handler:false,items:items,disabled:pro.disabled})
            );
            t.render(true);
            t = self._$tb = t.get(0);

            t.onClick=self.box._toolbarclick;
            v=self._$composed={};
            v[t.$linbid]=t;
            self.$toolbar=t;
            t.$hostage=self;
            
            linb.UI.$tryResize(profile, pro.width, pro.height,true);
        },
        _toolbarclick:function(profile,item,group,e,src){
            var editor=profile.$hostage;
            if(!editor.$doc)return;

            var pro=editor.properties;
            editor.$win.focus();

            if(item.command=='custom'){
                var cmd=item.id,
                    o,_clear,node,
                    items, items2;

                //get the pop control
                switch(cmd){
                    case 'forecolor':
                    case 'bgcolor':
                        if(!editor.$colorPicker)
                            editor.$colorPicker=(new linb.UI.ColorPicker({barDisplay:false})).render(true);
                        o=editor.$colorPicker;
                        break;
                    case 'fontsize':
                    case 'fontname':
                    case 'formatblock':
                        //if lang was changed, clear the pool first
                        if(editor.$lang!=linb.getLang())
                            editor.box._clearPool(editor);
                        editor.$lang=linb.getLang();

                        //font size
                        if(cmd=='fontsize'){
                            if(!editor.$fontsizeList){
                                items = linb.getRes('editor.fontsizeList');
                                items = items.split(';');
                                items2=[];
                                var t;
                                _.arr.each(items,function(o){
                                    o=o.split(',');
                                    t=o[0]=='...'?'1':o[0];
                                    items2.push({id:o[0], caption:'<font size="'+o[0]+'">'+o[1]+'</font>'})
                                });
                                editor.$fontsizeList=(new linb.UI.List({height:'auto',items:items2,width:150})).render(true);
                            }
                            o=editor.$fontsizeList;
                        //font family
                        }else if(cmd=='fontname'){
                            if(!editor.$fontnameList){
                                items = linb.getRes('editor.fontnameList');
                                items = items.split(';');
                                items2=[];
                                var t;
                                _.arr.each(items,function(o){
                                    t=o=='...'?'':o;
                                    items2.push({id:o, caption:'<span style="font-family:'+o+'">'+o+'</span>'})
                                });
                                editor.$fontnameList=(new linb.UI.List({height:'auto',items:items2})).render(true);
                            }
                            o=editor.$fontnameList;
                        //font format
                        }else if(cmd=='formatblock'){
                            if(!editor.$formatblockList){
                                items = linb.getRes('editor.formatblockList');
                                items = items.split(';');
                                items2=[];
                                var t;
                                _.arr.each(items,function(o){
                                    o=o.split(',');
                                    t=o[0]=='...'?'span':o[0];
                                    items2.push({id:o[0], caption:'<'+t+' style="display:inline;padding:0;margin:0">'+o[1]+'</'+t+'>'})
                                });

                                editor.$formatblockList=(new linb.UI.List({height:'auto',items:items2})).render(true);
                            }
                            o=editor.$formatblockList;
                        }
                        break;
                    case 'html':
                        if(!editor.$htmlEditor){
                            editor.$htmlEditor=new linb.UI.Input({multiLines:true,width:400,height:300,resizer:true});
                        }
                        o=editor.$htmlEditor;
                        break;
                }
                //pop the control and set clear funciton
                if(o){
                    _clear=function(){
                        o.beforeUIValueSet(null);
                        editor.getSubNode('POOL').append(o.getRoot());
                        node.setBlurTrigger(editor.$linbid);
                        linb.Event.keyboardHook('esc');
                        _.asyRun(function(){
                            editor.$win.focus()
                        });
                    };

                    o.setValue('',true);
                    node=o.reBoxing();
                    node.popToTop(src);
                    _.tryF(o.activate,[],o);

                    //for on blur disappear
                    node.setBlurTrigger(editor.$linbid, function(){
                        //force to trigger beforeUIValueSet event
                        if(o==editor.$htmlEditor)
                            o.setUIValue(o._getCtrlValue());

                         _clear();
                    });
                    //for esc
                    linb.Event.keyboardHook('esc',0,0,0,function(){
                        _clear();
                    });
                }
                //set beforeUIValueSet function
                switch(cmd){
                    case 'forecolor':
                    case 'bgcolor':
                        o.beforeUIValueSet(function(p,o,v){
                            _clear();
                            var doc=editor.$doc;
                            if(cmd=='bgcolor' && linb.browser.gek){
                                doc.execCommand('useCSS',0,false);
                                doc.execCommand('hilitecolor',false, '#'+v);
                                doc.execCommand('useCSS',0,true);
                            }else{
                                if(cmd=='bgcolor')
                                    cmd=linb.browser.opr?'hilitecolor':'backcolor';
                                doc.execCommand(cmd,false, linb.browser.kde?('#'+v):v)  ;
                            }
                            doc=null;
                            return false;
                        });
                        break;
                    case 'fontsize':
                    case 'fontname':
                    case 'formatblock':
                        o.beforeUIValueSet(function(p,o,v){
                            _clear();
                            //store range for IE
                            if(linb.browser.ie && (v=='...' ||cmd=='formatblock' )){
                                var selection=editor.$doc.selection,
                                    range=selection?selection.createRange():null;
                                if(range && range.parentElement().ownerDocument!=editor.$doc)
                                    range=selection=null;
                            }
                            var f=function(cmd,v){
                                    var doc=editor.$doc;

                                    //for formatblock in IE
                                    //reset range for IE
                                    if(range){
                                        editor.$win.focus();
                                        if(cmd=='formatblock' && v){
                                            var p=range.parentElement(),html;
                                            if(p.ownerDocument==doc){
                                                if(/^\s*</.test(range.htmlText)){
                                                    //affect the first block only
                                                    range.collapse(true);
                                                    p=range.parentElement();
                                                    if(p.tagName=='BODY'){
                                                        html=p.innerHTML;
                                                        p.innerHTML = "<"+v+">"+html+"</"+v+">"
                                                    }else{
                                                        html=p.outerHTML;
                                                        html=html.replace(/\<[\w]+/,'<'+v).replace(/[\w]+\>$/,v+'>');
                                                        p.outerHTML=html;
                                                    }
                                                }else{
                                                    range.pasteHTML("<"+v+">"+range.htmlText+"</"+v+">")
                                                }
                                            }
                                            p=null;
                                        }
                                        range.select();
                                        selection=range=null;
                                    }

                                    doc.execCommand(cmd,false,v);
                                    doc=null;
                                };
                            if(v=='...'){
                                var str=linb.getRes('editor.'+cmd);
                                linb.UI.Dialog.prompt(str,str,"",function(v){
                                    if(v){
                                        f(cmd,v);
                                    }
                                },function(){
                                    //reset range for IE
                                    if(linb.browser.ie){
                                        if(range){
                                            editor.$win.focus();
                                            range.select();
                                        }
                                        selection=range=null
                                    }
                                });
                            }else
                                f(cmd,v);
                        });
                        break;
                    case 'insertimage':
                    case 'createlink':
                        var str=linb.getRes('editor.'+cmd),
                            str2=linb.getRes('editor.'+cmd+'2');
                        //store range for IE
                        if(linb.browser.ie){
                            var selection=editor.$doc.selection,
                                range=selection?selection.createRange():null;
                                if(range && range.parentElement().ownerDocument!=editor.$doc)
                                    range=selection=null;
                        }
                        linb.UI.Dialog.prompt(str,str2,"http:/"+'/',function(v){
                            //reset range for IE
                            if(linb.browser.ie){
                                if(range){
                                    editor.$win.focus();
                                    range.select();
                                }
                                selection=range=null
                            }
                            if(v){
                                var doc=editor.$doc;
                                doc.execCommand(cmd,false,v);
                                doc=null;
                            }
                        },function(){
                            //reset range for IE
                            if(linb.browser.ie){
                                if(range){
                                    editor.$win.focus();
                                    range.select();
                                }
                                selection=range=null
                            }
                        });
                        break;
                     case 'html':
                         o.setValue(editor.boxing().getUIValue(),true);
                         o.beforeUIValueSet(function(p,o,v){
                            _clear();
                            editor.boxing().setUIValue(v);
                        });
                        break;
                }
            }else{
                editor.$doc.execCommand(item.command,false,item.commandArgs);

                if(item.id=='removeformat')
                    linb.UI.RichEditor._updateToolbar(editor.$domId,true)
            }
        },
        _onresize:function(profile,width,height){
            var size={};
            if(width)
                size.width=width-2;
            if(size.width<0)
                size.width=0;

            if(width || height){
                var itb=profile._$tb,
                    _top=(itb?itb.getRoot().offsetHeight():0);
                if(!height)
                    height=this.properties.height;
                size.height=height-_top-1;
                if(size.height<0)
                    size.height=0;
            }
            profile.getSubNode('EDITOR').top(_top).cssSize(size,true);
        }
    }
});

Class("linb.UI.ComboInput", "linb.UI.Input",{
    /*Instance*/
    Instance:{
        _getCtrlValue:function(){
            return this.get(0).properties.$UIvalue;
            //return this._fromEditValue(this.getSubNode('INPUT').attr('value'));
        },
        _setCtrlValue:function(value, flag){
            var me=arguments.callee, r1=me._r1||(me._r1=/\</),r2=me._r2||(me._r2=/\<\/?[^>]+\>/g);
            return this.each(function(profile){
                if(!profile.$typeOK)
                    profile.box._iniType(profile);

                var o=profile.getSubNode('INPUT'), type=profile.properties.type;
                value=flag?value:profile.boxing().getShowValue(value);
                if(type!=='none'&& !profile.properties.multiLines && typeof value=='string' && r1.test(value))value=value.replace(r2,'');
                o.attr('value',value||'');
                if(type=='colorpicker')
                    o.css({backgroundColor:value, color:linb.UI.ColorPicker.getTextColor(value)});
            })
        },
        _compareValue:function(v1,v2){
            var profile=this.get(0),t;
            if(t= profile.CF.compareValue||profile.$compareValue)
                return t(profile, v1, v2);

            return v1===v2;
        },
        getShowValue:function(value){
            var profile=this.get(0),
                pro=profile.properties,v,t;
            if(!_.isDefined(value))
                value=pro.$UIvalue;
            if(t= profile.CF.getShowValue||profile.$getShowValue)
                v = t(profile, value);
            else{
                //get from items
                if('listbox'==pro.type){
                    if( (v=_.arr.subIndexOf(pro.items,'id',value))!=-1){
                        v=pro.items[v].caption;
                        v=v.charAt(0)=='$'?linb.getRes(v.slice(1)):v;
                    }else
                        v='';
                }else
                    v = profile.$showValue;
            }
            v = v || ((value||value===0)?String(value):'');

            if(v!==value)profile.$caption=v;
            else delete profile.$caption;
            return v;
        },
        _getEditValue:function(value){
            var profile=this.get(0),
                pro=profile.properties,t;

                if(t= profile.CF.getEditValue||profile.$getEditValue)
                    return t(profile, value);
            return value;
        },
        _fromEditValue:function(value){
            var profile=this.get(0),
                pro=profile.properties,t;

                if(t= profile.CF.fromEditValue||profile.$fromEditValue)
                    return t(profile, value);
            return value;
        },
        _cache:function(){
            var profile=this.get(0),drop=profile.$drop;
            if(drop){
                if(linb.browser.opr)
                    drop.getRoot().css('display','none');
                _.asyRun(function(){
                    profile.getSubNode('POOL').append(drop.getRoot())
                });
            }
            delete profile.$poplink;
        },
        clearPopCache:function(){
            var profile=this.get(0);
            if(profile.renderId)
                profile.getSubNode('POOL').empty();
            delete profile.$drop;
            return this;
        },
        //for upload ,special must get the original node
        getUploadObj:function(){
            var profile=this.get(0);
            if(profile.renderId && profile.properties.type=='upload'){
                var o = profile.getSubNode('UPLOAD').get(0)
                if(!o.value)
                    return null;

                var c=o.cloneNode(false);
                //inner replace
                linb.setNodeData(c.$linbid=o.$linbid,'element',c);
                c.onclick=o.onclick;
                c.onchange=o.onchange;

                //remove those
                if(linb.browser.ie)
                    o.removeAttribute('$linbid');
                else
                    delete o.$linbid;
                o.id=o.onclick=o.onchange=null;

                //a special node, must delete if from cache here:
                delete profile.$_domid[profile.keys['UPLOAD']];
                linb([o]).addPrev(c).remove(false);
                c=null;

                this.setUIValue(this.getValue());

                return o;
            }
        },
        resetValue:function(value){
            this.each(function(p){
                if(p.properties.type=='upload')
                    p.getSubNode('UPLOAD').attr('value','');
            });
            return arguments.callee.upper.apply(this,arguments);
        },
        _drop:function(e,src){
            return this.each(function(profile){
                var pro = profile.properties, type=pro.type;
                if(pro.disabled)return;
                if(type=='upload'||type=='none'||type=='spin')return;
                //open already
                if(profile.$poplink)return;

                var o,v,
                box = profile.boxing(),
                main = profile.getRoot(),
                pos = main.offset(),
                size = main.cssSize()
                ;
                size.width += 2;
                pos.top += main.offsetHeight();


                //special cmd type: getter, 'cmdbox' and 'popbox'
                if((profile.beoforeComboPop && false===box.beoforeComboPop(profile, pos, e, src))||type=='getter'||type=='cmdbox'||type=='popbox')
                    return;

                //get cache key
                var cachekey;
                switch(type){
                    case 'timepicker':
                    case 'datepicker':
                    case 'colorpicker':
                        cachekey=type;
                        break;
                    default:
                        if(pro.listKey)
                            //function no cache
                            if(typeof _.get(linb.$cache,['UIDATA', pro.listKey])=='function')
                                profile.$drop = cachekey = null;
                            else
                                cachekey = pro.listKey;
                        else
                            cachekey = profile.$linbid;
                }
                //get from global cache
                if(cachekey){
                    //filter first
                    _.filter(profile.box.$drop,function(o){
                        return !!o.renderId;
                    });
                    profile.$drop = profile.box.$drop[cachekey];
                }

                //cache pop
                if(!profile.$drop){
                    switch(type){
                        case 'combobox':
                        case 'listbox':
                        case 'helpinput':
                            linb.SC('linb.UI.List');
                            o = linb.create('List').render();
                            o.host(profile).setItems(_.copy(pro.items)).setListKey(pro.listKey||'').adjustSize();
                            o.beforeUIValueSet(function(p, ovalue, value){
                                var b2=this.boxing();
                                if(type=='combobox'){
                                    var item=p.queryItems(p.properties.items,function(o){return o.id==value},false,true);
                                    if(item.length)
                                        value = item[0].caption;
                                }
                                //update value
                                b2.setUIValue(value)
                                //set activate
                                .activate()
                                //cache pop
                                ._cache();
                            });
                            break;
                        case 'timepicker':
                            linb.SC('linb.UI.TimePicker');
                            o = linb.create('TimePicker').render();
                            o.host(profile);
                            o.beforeClose(function(){this.boxing().activate()._cache();return false});
                            o.beforeUIValueSet(function(p, o, v){
                                //update value
                                this.boxing().setUIValue(v).activate()._cache();
                            });
                            break;
                        case 'datepicker':
                            linb.SC('linb.UI.DatePicker');
                            o = linb.create('DatePicker').render();
                            o.host(profile);
                            o.beforeClose(function(){this.boxing().activate()._cache();return false});
                            o.beforeUIValueSet(function(p, o, v){
                                //update value
                                this.boxing().setUIValue(String(v.getTime())).activate()._cache();
                            });

                            break;

                        case 'colorpicker':
                            linb.SC('linb.UI.ColorPicker');
                            o = linb.create('ColorPicker').render();
                            o.host(profile);
                            o.beforeClose(function(){this.boxing().activate()._cache();return false});
                            o.beforeUIValueSet(function(p, o, v){
                                //update value
                                this.boxing().setUIValue('#'+v).activate()._cache();
                            });
                            break;
                    }

                    profile.$drop = o.get(0);

                    //set to global cache
                    if(cachekey)
                        profile.box.$drop[cachekey]=profile.$drop;
                }

                o=profile.$drop.boxing();
                o.host(profile);

                //set pop
                switch(type){
                    case 'combobox':
                    case 'listbox':
                    case 'helpinput':
                        o.setWidth(profile.getRoot().width());
                    case 'timepicker':
                        o.setValue(profile.properties.$UIvalue, true);
                        break;
                    case 'datepicker':
                        var t = profile.$drop.properties;
                        t.WEEK_FIRST=pro.WEEK_FIRST;
                        if(t=profile.properties.$UIvalue)
                            o.setValue(new Date( parseInt(t) ), true);
                        break;
                    case 'colorpicker':
                        o.setValue(profile.properties.$UIvalue.replace('#',''), true);
                        break;
                }

                profile.$poplink = o.get(0);

                //pop
                var node=o.reBoxing();
                node.popToTop(profile.getRoot());

                _.tryF(o.activate,[],o);

                //for on blur disappear
                node.setBlurTrigger(profile.key+":"+profile.$linbid, function(){
                    box._cache();
                }, null, profile.$linbid);

                //for esc
                linb.Event.keyboardHook('esc',0,0,0,function(){
                    box._cache();
                    box.activate();
                    //unhook
                    linb.Event.keyboardHook('esc');
                });
            });
        }
    },
    /*Initialize*/
    Initialize:function(){
        this.addTemplateKeys(['UPLOAD','BTN','TOP','MID','RBTN','R1','R1T','R1B','R2','R2T','R2B']);
        //modify default template for shell
        var t = this.getTemplate();
        _.merge(t.FRAME.BORDER,{
            SBTN:{
                $order:5,
                style:"{_saveDisplay}",
                STOP:{},
                SMID:{}
            }
        },'all');
        t.FRAME.POOL={};
        t.className +=' {uploadClass}';

        this.setTemplate(t);
        
        this._adjustItems=linb.absList._adjustItems;
    },
    Static:{
        _iniType:function(profile){
            var pro=profile.properties, value=pro.type;
            if(value=='listbox'||value=='upload')
                profile.boxing().setReadonly(true);

            if(value!='listbox' && value!='combobox' && value!='helpinput')
                pro.items=[];

            if(value=='timepicker'){
                var  o=linb.SC('linb.UI.TimePicker');
                _.merge(profile,{
                    $compareValue : null,
                    $getShowValue : function(profile,value){
                        return value?o._ensureValue(profile,value):'';
                    },
                    $getEditValue : null,
                    $fromEditValue : function(profile,value){
                        return o._ensureValue(profile,value);
                    }
                },'all');
                if(pro.value)
                    pro.$UIvalue=pro.value=o._ensureValue(profile,pro.value);
            }else if(value=='datepicker'){
                var date=linb.Date;
                _.merge(profile,{
                    $compareValue : function(p,a,b){
                        return String(a)==String(b)
                    },
                    $getShowValue : function(profile,value){
                        return value?date.getText(new Date(parseInt(value)), 'ymd'):'';
                    },
                    $getEditValue : function(profile,value){
                        var v=new Date(parseInt(value));
                        return value?(date.get(v,'m')+1)+'/'+date.get(v,'d')+'/'+date.get(v,'y'):'';
                    },
                    $fromEditValue : function(profile,value){
                        //parse from local text mm/dd/yyyy
                        var v=linb.Date.parse(value);
                        if(v)v=linb.Date.getTimSpanStart(v,'d',1);
                        return v?String(v.getTime()):'0';
                    }
                },'all');

                var d=new Date(parseInt(pro.value)||0);
                pro.$UIvalue=pro.value=String(date.getTimSpanStart(d,'d',1).getTime());
            }else{
                delete profile.$compareValue;
                delete profile.$getShowValue;
                delete profile.$getEditValue;
                delete profile.$fromEditValue;
                if(_.isDate(pro.value))
                    pro.$UIvalue=pro.value=String(pro.value);
            }
            profile.$typeOK=true;
        },
        $drop:{},
        Appearances:{
            POOL:{
                position:'absolute',
                left:0,
                top:0,
                width:0,
                height:0,
                display:'none',
                visibility:'hidden'
            },
            UPLOAD:{
                opacity:0,
                '*filter':'alpha(opacity=0)',
                'z-index':'3',
                border:0,
                height:'100%',
                position:'absolute',
                top:0,
                right:0,
                cursor:'pointer',
                'font-size':'12px',
                overflow:'hidden'
            },
            'UPLOAD-show INPUT':{
                color:'#777'
            },
            'RBTN,SBTN,BTN':{
                display:'block',
                'z-index':'1',
                cursor:'pointer',
                width:'16px',
                height:'20px',
                'font-size':0,
                'line-height':0,
                position:'relative',
                'float':'right'
            },
            'SBTN,BTN,R1,R2':{
                'margin-top':'2px'
            },
            'R1, R2, BTN, SBTN, STOP, TOP, R1T, R2T, R1B, R2B, SMID,MID':{
                background: linb.UI.$bg('bg.gif')
            },
            'SBTN,BTN':{
                $order:1,
                'background-position':'left bottom'
            },
            'R1,R2':{
                $order:1,
                display:'block',
                'font-size':0,
                'line-height':0,
                cursor:'pointer',
                width:'16px',
                position:'absolute',
                height:'50%',
                'background-position':'left bottom',
                'margin-top':'2px'
            },
            R1:{
                top:0
            },
            R2:{
                bottom:'-2px'
            },

            'BTN-mouseover, SBTN-mouseover, R1-mouseover, R2-mouseover':{
                $order:2,
                'background-position': '-16px bottom'
            },
            'BTN-mousedown, SBTN-mousedown, R1-mousedown, R2-mousedown':{
                $order:3,
                'background-position': '-32px bottom'
            },
            'STOP, TOP, R1T, R2T':{
                $order:1,
                cursor:'pointer',
                width:'16px',
                'font-size':0,
                'line-height':0,
                position:'absolute',
                top:'-2px',
                left:0,
                height:'4px',
                'background-position':'left -104px'
            },
            'BTN-mouseover TOP,SBTN-mouseover STOP, R1-mouseover R1T, R2-mouseover R2T':{
                $order:2,
                'background-position': '-16px -104px'
            },
            'BTN-mousedown TOP,SBTN-mousedown STOP, R1-mousedown R1T, R2-mousedown R2T':{
                $order:3,
                'background-position': '-32px -104px'
            },
            'R1B,R2B':{
                cursor:'pointer',
                width:'16px',
                'font-size':0,
                'line-height':0,
                position:'absolute',
                left:0,
                top:'50%',
                'margin-top':'-4px',
                height:'6px',
                'z-index':2
            },
            R1B:{
                $order:1,
                'background-position':'-14px -36px'
            },
            R2B:{
                $order:1,
                'background-position':'left -5px'
            },
            'SMID,MID':{
                $order:2,
                cursor:'pointer',
                width:'16px',
                'font-size':0,
                'line-height':0,
                position:'absolute',
                bottom:'0',
                left:0,
                height:'16px',
                'background-position':'0 0'
            },
            SMID:{
                $order:3,
                'background-position': '-14px -16px'
            },
            '.setting-linb-comboinput':{
                'border-style':'solid',
                'border-top-width':'1px',
                'border-bottom-width':'1px',
                'border-left-width':'1px',
                'border-right-width':'1px'
            }
        },
        Behaviors:{
            HoverEffected:{BOX:'BOX',BTN:'BTN',SBTN:'SBTN',R1:'R1',R2:'R2'},
            ClickEffected:{BTN:'BTN',SBTN:'SBTN',R1:'R1',R2:'R2'},
            UPLOAD:{
                onClick : function(profile, e, src){
                    if(profile.onFileDlgOpen)profile.boxing().onFileDlgOpen(profile,src);
                },
                onChange:function(profile, e, src){
                    profile.boxing().setUIValue(linb.use(src).get(0).value+'');
                }
            },
            BTN:{
                onClick : function(profile, e, src){
                    profile.boxing()._drop(e,src);
                }
            },
            SBTN:{
                onClick : function(profile, e, src){
                    if(profile.onSave)profile.boxing().onSave(profile,src);
                }
            },
            INPUT:{
                onChange:function(profile, e, src){
                    if(profile.$_onedit||profile.$_inner)return;
                    var o=profile.inValid,
                        instance=profile.boxing(),
                        v = instance._fromEditValue(linb.use(src).get(0).value),
                        uiv=profile.properties.$UIvalue;
                    if(!instance._compareValue(uiv,v)){
                        profile.$_inner=1;
                        delete profile.$_inner;

                        //give a invalid value in edit mode
                        if(v===null)
                            instance._setCtrlValue(uiv);
                        else{
                            instance.setUIValue(v);
                            //input/textarea is special, ctrl value will be set before the $UIvalue
                            profile.properties.$UIvalue=v;
                            if(o!==profile.inValid) if(profile.renderId)instance._setDirtyMark();
                        }
                    }
                },
                onKeyup:function(profile, e, src){
                    var p=profile.properties;
                    if(p.dynCheck){
                        var value=linb.use(src).get(0).value;
                        if(p.$UIvalue!=value)
                            profile.box._checkValid(profile, value);
                        profile.boxing()._setDirtyMark();
                    }
                },
                onFocus:function(profile, e, src){
                    var p=profile.properties, uiv=p.$UIvalue;
                    if(p.disabled)return false;

                    var instance=profile.boxing(),
                        v = instance._getEditValue(uiv);
                    //string compare
                    if(v!==uiv){
                        //here, dont use $valueFormat, valueFormat or onValueFormat
                        //use $getShowValue, $getEditValue, $fromEditValue related functions
                        profile.$_onedit=true;
                        linb.use(src).get(0).value=v;
                        delete profile.$_onedit;
                    }

                    //set css class
                    if(profile.onFocus)profile.boxing().onFocus(profile);
                    profile.getSubNode('BORDER').tagClass('-focus');
                    //show tips color
                    profile.boxing()._setTB(3);
                },
                onBlur:function(profile, e, src){
                    var p=profile.properties,
                        instance=profile.boxing(),
                        uiv=p.$UIvalue,
                        v = instance._fromEditValue(linb.use(src).get(0).value)
                        ;
                    if(p.disabled)return false;
                    if(profile.onFocus)instance.onFocus(profile);
                    profile.getSubNode('BORDER').tagClass('-focus',false);

                    //onblur check it
                    if(instance._compareValue(p.$UIvalue,v)){
                        profile.box._checkValid(profile, v);
                        instance._setCtrlValue(uiv);
                    }
                    instance._setDirtyMark();
                },
                onKeydown : function(profile, e, src){
                    var prop=profile.properties,
                        m=prop.multiLines,
                        key=linb.Event.getKey(e);
                    //fire onchange first
                    if(key[0]=='enter'&& (!m||key[3]))
                        linb.use(src).onChange();
                    if(key[0]=='down'|| key[0]=='up'){
                        if(prop.type=='spin'){
                            profile.box._spin(profile, key[0]=='up');
                            return false;
                        }if(key[1] && prop.type){
                            profile.boxing()._drop(e,src);
                            return false;
                        }
                    }
                },
                onKeyup : function(profile, e, src){
                    var prop=profile.properties,
                        key=linb.Event.getKey(e);
                    if(key[0]=='down'|| key[0]=='up'){
                        if(prop.type=='spin'){
                            linb.Thread.abort(profile.$linbid+':spin');
                            return false;
                        }
                    }
                },
                onClick : function(profile, e, src){
                    if(src.readOnly)
                        profile.boxing()._drop(e, src);
                }
            },
            R1:{
                onMousedown:function(profile){
                    profile.box._spin(profile, true);
                },
                onMouseout:function(profile){
                    linb.Thread.abort(profile.$linbid+':spin');
                },
                onMouseup:function(profile){
                    linb.Thread.abort(profile.$linbid+':spin');
                }
            },
            R2:{
                onMousedown:function(profile){
                    profile.box._spin(profile, false);
                },
                onMouseout:function(profile){
                    linb.Thread.abort(profile.$linbid+':spin');
                },
                onMouseup:function(profile){
                    linb.Thread.abort(profile.$linbid+':spin');
                }
            }
        },
        EventHandlers:{
            onFileDlgOpen:function(profile, node){},
            onSave:function(profile, node){},
            beoforeComboPop:function(profile, pos, e, src){}
        },
        _posMap:{
            none:'',
            combobox:'left top',
            listbox:'left top',
            upload:'-16px top',
            getter:'left -31px',
            helpinput:'-16px -46px',
            cmdbox:'left -16px',
            popbox:'left -46px',
            timepicker:'left -60px',
            datepicker:'left -75px',
            colorpicker:'-16px -60px'
        },
        DataModel:{
            listKey:{
                set:function(value){
                    var t = linb.UI.getCachedData(value),
                        o=this;
                    o.boxing().setItems(t?t:o.properties.items);
                    o.properties.listKey = value;
                }
            },
            items:{
                ini:[],
                set:function(value){
                    var o=this;
                    o.properties.items = _.copy(value);
                    if(o.renderId){
                        o.boxing().setValue(null,true);
                        o.SubSerialIdMapItem={};
                        o.ItemIdMapSubSerialId={};
                        //for memory map
                        value=o.box._adjustItems(value);
                        o.box._prepareItems(o, value);
                        o.boxing().clearPopCache();                            
                    }
                }
            },
            image:{
                action: function(value){
                    this.getSubNode('MID')
                        .css('backgroundImage','url('+(value||'')+')');
                }
            },
            imagePos:{
                action: function(value){
                    this.getSubNode('MID')
                        .css('backgroundPosition', value);
                }
            },
            readonly:{
                ini:false,
                action:function(v){
                    if(!v && this.properties.type=='listbox')return;
                    this.getSubNode('INPUT').css('cursor',v?'pointer':'default').attr('readonly',v);
                }
            },
            type:{
                ini:'combobox',
                listbox:_.toArr('none,combobox,listbox,upload,getter,helpinput,cmdbox,popbox,timepicker,datepicker,colorpicker,spin'),
                set:function(value){
                    var pro=this;
                    pro.properties.type=value;
                    pro.box._iniType(pro);
                    if(pro.renderId)
                        pro.boxing().refresh();
                }
            },
            scale:2,
            increment:0.01,
            min:0,
            max:1,
            saveBtn:{
                ini:false,
                action:function(v){
                    this.boxing().refresh();
                }
            }
        },
        RenderTrigger:function(){
            var self=this,
                instance=self.boxing(),
                p=self.properties;
            self.box._iniType(self);
            if(p.readonly)
                instance.setReadonly(true,true);
        },
        _spin:function(profile, flag){
            var id=profile.$linbid+':spin';
            if(linb.Thread.isAlive(id))return;
            var prop=profile.properties,
                off=prop.increment*(flag?1:-1),
                task={delay:300},
                fun=function(){
                    profile.boxing().setUIValue(String((+prop.$UIvalue||0)+off));
                    task.delay *=0.9;
                };
            task.task=fun;
            linb.Thread(id,[task],500,null,fun,null,true).start();
        },
        _dynamicTemplate:function(profile){
            var properties = profile.properties,
                hash = profile._exhash = "$" +
                    'multiLines:'+properties.multiLines+';'+
                    'type:'+properties.type+';',
                template = profile.box.getTemplate(hash);

            properties.$UIvalue = properties.value;

            // set template dynamic
            if(!template){
                template = _.clone(profile.box.getTemplate());
                var t=template.FRAME.BORDER;

                if(properties.multiLines){
                    t.BOX.WRAP.INPUT.tagName='textarea';
                    delete t.BOX.WRAP.INPUT.type;
                }

                switch(properties.type){
                case 'spin':
                    t.RBTN={
                        $order:5,
                        style:"{rDisplay}",
                        R1:{
                            R1T:{},
                            R1B:{}
                        },
                        R2:{
                            R2T:{},
                            R2B:{}
                        }
                    };
                break;
                case 'none':
                break;
                case 'upload':
                    t.UPLOAD={
                        $order:2,
                        tagName:'input',
                        type:'file',
                        size:'1'
                    };
                default:
                    t.BTN={
                        $order:4,
                        style:"{_popbtnDisplay}",
                        TOP:{},
                        MID:{
                            style:'{_btnStyle}'
                        }
                    };
                }

                // set template
                profile.box.setTemplate(template, hash);
            }
            profile.template = template;
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile),
                map=profile.box._posMap;
            if(map[data.type])
                data._btnStyle = data.image? ('background: url('+data.image+')' + (data.imagePos||'')) :('background-position:'+map[data.type]);

            if(data.type=='upload')
                data.uploadClass=profile.getClass('UPLOAD','-show');
                
            data._type="text";

            data._saveDisplay = data.saveBtn?'':'display:none';
            data._popbtnDisplay = data.type!='none'?'':'display:none';
            return data;
        },
        _ensureValue:function(profile, value){
            var me=arguments.callee, reg=me._reg||(me._reg=/^#[\w]{6}$/),prop=profile.properties;
            switch(profile.properties.type){
                case 'datepicker':
                    return (value.constructor==Date?value.getTime():value) + "";
                case 'colorpicker':
                    return '#'+linb.UI.ColorPicker._ensureValue(null,value);
                case 'timepicker':
                    return linb.UI.TimePicker._ensureValue(null,value);
                case 'spin':
                    var n=Math.pow(10,prop.scale);
                    value=+value||0;
                    value=Math.ceil((value-0.0000000000003)*n)/n;
                    return String(value>prop.max?prop.max:value<prop.min?prop.min:value);
                default:
                    return typeof value=='string'?value:(value||value===0)?String(value):'';
            }
        },
        _onresize:function(profile,width,height){
            var $hborder=1, $vborder=1,
                toff=linb.UI.$getCSSValue('linb-comboinput-input','paddingTop'),
                loff=linb.UI.$getCSSValue('linb-comboinput-input','paddingLeft');

            var t = profile.properties,
                o = profile.getSubNode('BOX'),
                px='px',
                f=function(k){return k?profile.getSubNode(k).get(0):null},
                v1=f('INPUT'),
                save=f(t.saveBtn?'SBTN':null),
                btn=f(t.type=='spin'?'RBTN':t.type=='none'?null:'BTN'),
                ww=width,
                hh=height,
                left=Math.max(0, (t.$b_lw||0)-$hborder),
                top=Math.max(0, (t.$b_tw||0)-$vborder);
            if(null!==ww){
                ww -= Math.max($hborder*2, (t.$b_lw||0)+(t.$b_rw||0));
                ww -= ((save?save.offsetWidth:0)+(btn?btn.offsetWidth:0));
                /*for ie6 bug*/
                /*for example, if single number, 100% width will add 1*/
                /*for example, if single number, attached shadow will overlap*/
                if(linb.browser.ie6)ww=(parseInt(ww/2))*2;
            }
            if(null!==hh){
                hh -=Math.max($vborder*2, (t.$b_lw||0) + (t.$b_rw||0));

                if(linb.browser.ie6)hh=(parseInt(hh/2))*2;
                /*for ie6 bug*/
                if(linb.browser.ie6&&null===width)o.ieRemedy();
            }   

            if(null!==ww)
                v1.style.width=(ww-loff)+px;

            if(null!==hh)
                v1.style.height=(hh-toff)+px;
            if(height-2>0){
                if(save)save.style.height=(height-2)+px;
                if(btn)btn.style.height=(height-2)+px;
            }
            if(t.type=='spin'){
                if(height/2-2>0){
                    height=(height/2-2)+px;
                    f('R1').style.height=height;
                    f('R2').style.height=height;
                }
            }

            o.cssRegion({left:left,top:top,width:ww,height:hh});

            /*for ie6 bug*/
            if((profile.$border||profile.$shadow||profile.$resizer) && linb.browser.ie){
                o.ieRemedy();
            }

        }
    }
});
Class("linb.UI.Group", "linb.UI.Div",{
    Instance:{
        activate:function(){
            var profile = this.get(0);
            profile.getSubNode('HANDLE').focus();
            return this;
        }
    },
    Static:{
        Behaviors:{
            NavKeys:{CAPTION:1},
            HoverEffected:{TOGGLE:'TOGGLE'},
            ClickEffected:{TOGGLE:'TOGGLE'},
            DropableKeys:['PANEL'],
            DragableKeys:['HANDLE'],
            onSize:linb.UI.$onSize,
            HANDLE:{
                onClick:function(profile, e, src){
                    if(profile.properties.toggleBtn){
                        profile.box._toggle(profile, !profile.properties.toggle);
                        return false;
                    }
                }
            }
        },
        Templates:{
            tagName : 'div',
            style:'{_style}',
            FIELDSET:{
                tagName : 'fieldset',
                className: ' {toggleCls}',
                LEGEND:{
                    tagName : 'legend',
                    HANDLE:{
                        tagName: 'a',
                        href :linb.$href,
                        tabindex: '{tabindex}',
                        TOGGLE:{
                            className: 'uicmd-toggle2 {toggleCls}',
                            style:"{toggleDispplay}"
                        },
                        ICON:{
                            $order:1,
                            className:'ui-icon {imageClass}',
                            style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                        },
                        CAPTION : {
                            text:   '{caption}',
                            $order:2
                        }
                    }
                },
                PANEL:{
                    $order:1,
                    tagName:'div',
                    style:'{panelDisplay}',
                    text:'{html}'+linb.UI.$childTag
                }
            }
        },
        Appearances:{
            KEY:{
                zoom:linb.browser.ie6?"1":null
            },
            FIELDSET:{
                border:'1px solid #7ba3cb',
                position:'relative',
                overflow:'hidden',
                zoom:linb.browser.ie6?"1":null
            },
            'FIELDSET-checked':{
                $order:2,
                'padding-left':'2px',
                'border-left':'0',
                'border-right':'0',
                'border-bottom':'0'
            },
            LEGEND:{
                'margin-left':'3px'
            },
            HANDLE:{
                cursor:'default',
                padding:'0 3px 0 6px',
                display:linb.$inlineBlock
            },
            PANEL:{
                position:'relative',
                overflow:'auto',
                 background:linb.browser.ie?'url('+linb.ini.file_bg+') no-repeat left top':null
            },
            'FIELDSET-checked PANEL':{
                $order:4,
                display:'none'
            },
            CAPTION:{
                'vertical-align':'middle',
                'font-family': '"Verdana", "Helvetica", "sans-serif"',
                'font-size':'12px',
                'line-height':'18px'
            }
        },

        DataModel:{
            caption:{
                ini:undefined,
                // ui update function when setCaption
                action: function(value){
                    this.getSubNode('CAPTION').get(0).innerHTML = value;
                }
            },
            html:{
                action:function(v){
                    this.getSubNode('PANEL').html(v);
                }
            },
            toggleBtn:{
                ini:true,
                action:function(v){
                    this.getSubNode('TOGGLE').css('display',v?'':'none');
                }
            },
            toggle:{
                ini:true,
                action:function(v){
                    this.box._toggle(this, v);
                }
            },
            image:{
                action: function(value){
                    this.getSubNode('ICON')
                        .css('display',value?'':'none')
                        .css('backgroundImage','url('+(value||'')+')');
                }
            },
            imagePos:{
                action: function(value){
                    this.getSubNode('ICON')
                        .css('backgroundPosition', value);
                }
            }
        },
        LayoutTrigger:function(){
            var self=this, t=self.properties, b=self.box;
            if(t.toggle)
                b._toggle(self,t.toggle);
        },        
        EventHandlers:{
            onIniPanelView:function(profile){},
            onFold:function(profile){},
            onExpend:function(profile){}
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile),
                nodisplay='display:none';

            data.toggleDispplay=data.toggleBtn?'':nodisplay;

            data.panelDisplay = data.toggleBtn&&!data.toggle?nodisplay:'';
            data.toggleCls = data.toggleBtn&&!data.toggle?profile.getClass('FIELDSET','-checked'):'';
            data.toggleCls2 = data.toggleBtn&&!data.toggle?profile.getClass('TOGGLE','-checked'):'';
            return data;
        },
        _onresize:function(profile,width,height){
            if(height && height!='auto'){
                profile.getSubNode('FIELDSET').height(height);
                profile.getSubNode('PANEL').height(height-(profile.getSubNode('LEGEND').height()||18));
            }
            if(width && width!='auto')
                profile.getSubNode('PANEL').width(width-2);
        },
        _toggle:function(profile, value){
            var p=profile.properties, b=profile.boxing();
            //set toggle mark
            p.toggle = value;

            //event
            if(value &&!profile.$ini)
                if(b.onIniPanelView)
                    if(b.onIniPanelView(profile)!==false)
                        profile.$ini=true;

            if(value){
                if(false===b.onExpend(profile))return;
            }else{
                if(false===b.onFold(profile))return;
            }

            //show/hide/panel
            profile.getSubNode('PANEL').css('display',value?'':'none');
            //chang toggle button

            profile.getSubNodes(['TOGGLE','FIELDSET']).tagClass('-checked', !value);
        }
    }
});Class('linb.UI.ColorPicker', ['linb.UI',"linb.absValue"], {
    Instance:{
        activate:function(){
            this.getSubNode('TOGGLEA').focus();
            return this;
        },
        _setCtrlValue:function(value,inner){
            return this.each(function(profile){
                if(!profile.renderId)return;
                var cls = profile.box,
                    p = profile.properties,
                    hex = profile.$hex = cls._to3(value),
                    hexs=profile.$hex.join(''),
                    rgb = profile.$rgb = cls.hex2rgb(value),
                    hsv = profile.$hsv = cls.rgb2hsv(rgb),
                    f=function(s,v){profile.getSubNode(s).get(0).firstChild.nodeValue=String(v)},
                    ff=function(v){return parseInt(v*100)};

                f('R',rgb[0]);
                f('G',rgb[1]);
                f('B',rgb[2]);
                f('H',hex[0]);
                f('E',hex[1]);
                f('X',hex[2]);

                //dont update hsv UI again, if hsv value is the newest
                if(profile.$hexinhsv != hexs){
                    f('HH',hsv[0]);
                    f('S',ff(hsv[1]));
                    f('V',ff(hsv[2]));
                    delete profile.$hexinhsv;
                }
                cls._setClrName(profile,hexs);
                cls._updateDftTip(profile);
                //dont update adv UI again, if adv value is the newest
                if(p.advance && profile.$hexinadv != hexs){
                    cls._updateMarks(profile, value, true, hsv[0]);
                    delete profile.$hexinadv;
                }
                //from setUIValue/setValue
                if(inner!=false)
                    profile.getSubNode('CAPTION').html('#'+value,false);
           });
        },
        getColorName:function(){
            return this.get(0).$clrN||'';
        }
    },
    Initialize:function(){
        var ns=this,
            id=linb.UI.$ID,
            cls=linb.UI.$CLS,
            key=ns.KEY,
            list=ns._slist,
            l=list.length,
            i,data,
            arr=[],
            evs=' unselectable="on" ';

        ns.addTemplateKeys(['TXT', 'DD1', 'DD2', 'DD3','R','G','B','HH','S','V','H','E','X']);

        //simple list
        for(i=0;i<l;i++)
            arr.push('<a  '+'id="'+key+'-SC:'+id+':'+list[i]+'" href='+linb.$href+'  style="background-color:#'+list[i]+'">'+list[i]+'</a>');

        //data
        data = '<div><span class="'+cls+'-txt">R: </span><span '+'id="'+key+'-R:'+id+':" class="'+cls+'-dd2 ui-dragable #DD2_CC#" '+evs+'>R</span><span style="width:8px;height:8px"  unselectable="on" ></span><span class="'+cls+'-txt">H: </span><span '+'id="'+key+'-HH:'+id+':" class="'+cls+'-dd2 ui-dragable #DD2_CC#" '+evs+'>H</span><span>\xB0</span></div>' +
               '<div><span class="'+cls+'-txt">G: </span><span '+'id="'+key+'-G:'+id+':" class="'+cls+'-dd2 ui-dragable #DD2_CC#" '+evs+'>G</span><span style="width:8px;height:8px"  unselectable="on" ></span><span class="'+cls+'-txt">S: </span><span '+'id="'+key+'-S:'+id+':" class="'+cls+'-dd2 ui-dragable #DD2_CC#"  '+evs+'>S</span><span>%</span></div>' +
               '<div><span class="'+cls+'-txt">B: </span><span '+'id="'+key+'-B:'+id+':" class="'+cls+'-dd2 ui-dragable #DD2_CC#" '+evs+'>B</span><span style="width:8px;height:8px"  unselectable="on" ></span><span class="'+cls+'-txt">V: </span><span '+'id="'+key+'-V:'+id+':" class="'+cls+'-dd2 ui-dragable #DD2_CC#" '+evs+'>V</span><span>%</span></div>' +
               '<div><span style="width:38px">HEX: #</span><span '+'id="'+key+'-H:'+id+':" class="'+cls+'-dd3 ui-dragable #DD3_CC#" '+evs+'>H</span><span '+'id="'+key+'-E:'+id+':" class="'+cls+'-dd3 ui-dragable #DD3_CC#" '+evs+'>E</span><span '+'id="'+key+'-X:'+id+':" class="'+cls+'-dd1 ui-dragable #DD1_CC#" '+evs+'>X</span></div>'
        ns.setTemplate({
            style:'{_style};height:auto;width:{_width}px;',
            tagName : 'div',
            onselectstart:'return false',
            BORDER:{
                tagName : 'div',
                BAR:{
                    tagName:'div',
                    className:'{classBar}',
                    BART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        className:'uibar-t',
                        tagName:'table',
                        BARTR:{
                            tagName:'tr',
                            BARTDL:{
                                tagName:'td',
                                className:'uibar-tdl'
                            },
                            BARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'uibar-tdm'
                            },
                            BARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'uibar-tdr'
                            }
                        }
                    },
                    BARCMDL:{
                        tagName: 'div',
                        className:'uibar-cmdl'
                    },
                    BARCMDR:{
                        tagName: 'div',
                        className:'uibar-cmdr',
                        onselectstart:'return false',
                        unselectable:'on',
                        CLOSE:{
                            className:'uicmd-close ',
                            style:'{closeDisplay}'
                        }
                    }
                },
                MAIN:{
                    $order:2,
                    tagName:'div',
                    className:'uicon-main',
                    MAINI:{
                        tagName:'div',
                        className:'uicon-maini',
                        CON:{
                            $order:1,
                            tagName:'div',
                            SIMPLE:{
                                tagName:'div',
                                TOP:{
                                    $order:1,
                                    tagName:'div',
                                    DATA:{
                                        $order:0,
                                        tagName:'div',
                                        onselectstart:'return false',
                                        text:data
                                    },
                                    EXAM:{
                                        $order:1,
                                        tagName:'div',
                                        EXAMI:{
                                            tagName:'div'
                                        }
                                    }
                                },
                                LIST:{
                                   $order:2,
                                   tagName:'div',
                                   text: arr.join('')
                                }
                            },
                            ADV:{
                                $order:2,
                                style:'{advDispay}',
                                tagName:'div',
                                ADVWHEEL:{
                                    $order:0,
                                    tagName:'div'
                                },
                                ADVCLR:{
                                    $order:1,
                                    tagName:'div'
                                },
                                ADVMARK1:{
                                    $order:3,
                                    tagName:'div'
                                },
                                ADVMARK2:{
                                    $order:4,
                                    tagName:'div'
                                }
                            }
                        }
                    }
                },
                TAIL:{
                    $order:3,
                    tagName:'div',
                    className:'uicon-main',
                    TAILI:{
                        tagName:'div',
                        className:'uicon-maini',
                        CAPTION:{
                            text : '{caption}'
                        },
                        SET:{
                            className:'ui-btn',
                            SETI:{
                                className:'ui-btni',
                                SETC:{
                                    className:'ui-btnc',
                                    SETA:{
                                        tagName:'a',
                                        href:linb.$href,
                                        text:linb.wrapRes('inline.set')
                                    }
                                }
                            }
                        },
                        TOGGLE:{
                            className:'ui-btn',
                            TOGGLEI:{
                                className:'ui-btni',
                                TOGGLEC:{
                                    className:'ui-btnc',
                                    TOGGLEA:{
                                        tagName:'a',
                                        href:linb.$href,
                                        tabindex: '{tabindex}',
                                        text:'>>'
                                    }
                                }
                            }
                        }
                    }
                },
                BBAR:{
                    $order:4,
                    tagName:'div',
                    className:'uibar-bottom-s',
                    BBART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        tagName:'table',
                        className:'uibar-t',
                        BBARTR:{
                            tagName:'tr',
                            BBARTDL:{
                                tagName:'td',
                                className:'uibar-tdl'
                            },
                            BBARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'uibar-tdm'
                            },
                            BBARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'uibar-tdr'
                            }
                        }
                    }
                }
            }
        });
    },
    Static:{
        _radius:84,
        _square:100,
        _bigRadius:97,
        DataModel:{
            height:{
                ini:'auto',
                readonly:true
            },
            width:{
                ini:'auto',
                readonly:true
            },
            value:"FFFFFF",
            barDisplay : {
                ini:true,
                action:function(v){
                    if(v)
                        this.getSubNode('BAR').replaceClass('uibar-top-s','uibar-top');
                    else
                        this.getSubNode('BAR').replaceClass('uibar-top','uibar-top-s');
                }
            },
            closeBtn:{
                ini:true,
                action:function(v){
                    this.getSubNode('CLOSE').css('display',v?'':'none');
                }
            },
            advance:{
                ini:false,
                action:function(v){
                    var ns=this;
                    ns.getSubNode('ADV').css('display',v?'':'none');
                    ns.getSubNode('TOGGLEA').text(v?"<<":">>");
                    ns.getRoot().width(v?410:210);
                    if(v)
                        ns.box._updateMarks(ns,ns.properties.$UIvalue,true, ns.$hsv[0])
                }
            }
        },
        Appearances:{
            KEY:{
                '-moz-user-select': 'none'
            },
            MAINI:{
                padding:'4px 5px 4px 0'
            },
            CON:{
                height:'196px',
                padding:'3px',
                position:'relative',
                border:'solid 1px #648CB4'
            },
            DATA:{
                'float':'left',
                width:'112px',
                height:'86px'
            },
            'DATA span':{
                'float':'left'
            },
            'DATA div':{
                'padding-top':'3px',
                'clear':'both'
            },
            TXT:{
                width:'16px'
            },
            CAPTION:{
                'font-size':'12px',
                'vertical-align':'middle'
            },
            EXAM:{
                'float':'left',
                'margin-top':'2px',
                padding:'3px',
                border:'solid 1px #648CB4',
                'background-color':'#E5EBFB'
            },
            EXAMI:{
                height:'70px',
                width:'70px',
                'white-space':'normal',
                'text-align':'center',
                border:'solid 1px #648CB4'
            },
            'DD1, DD2, DD3':{
                display:'block',
                height:'16px',
                border:'1px solid #779EBF',
                'padding-right':'2px',
                cursor:'e-resize',
                'text-align':'right',
                background:'#F8FBFF'
            },
            DD1:{
                width:'16px'
            },
            DD2:{
                width:'24px'
            },
            DD3:{
                $order:2,
                width:'16px',
                'border-right':'none'
            },
            TOP:{
                height:'90px',
                position:'relative'
            },
            LIST :{
                height:'106px',
                position:'relative',
                overflow:'hidden',
                margin:'0 2px',
                'line-height':linb.browser.ie6?'0':null,
                'clear':'both'
            },
            TAILI:{
                position:'relative',
                'padding-top':'4px',
                height:'22px',
                'text-align':'center'
            },
            SIMPLE:{
                'float':'left',
                width:'192px',
                position:'relative'
            },
            ADV:{
                'float':'right',
                width:'195px',
                height:'195px',
                position:'relative'
            },
            'ADV div':{
                cursor:'crosshair',
                position:'absolute'
            },
            ADVCLR:{
                background: linb.browser.ie6?null:linb.UI.$bg('bg.png', 'no-repeat left top'),
                _filter: linb.UI.$ieBg('bg.png'),
                height:'101px',
                left:'47px',
                top:'47px',
                width:'101px'
            },
            ADVWHEEL:{
                background: linb.browser.ie6?null:linb.UI.$bg('clr.png', 'no-repeat left top'),
                _filter: linb.UI.$ieBg('clr.png'),
                height:'195px',
                width:'195px'
            },
            'ADVMARK1, ADVMARK2':{
                background:linb.browser.ie6?null:linb.UI.$bg('picker.png', 'no-repeat left top'),
                _filter: linb.UI.$ieBg('picker.png'),
                height:'17px',
                margin:'-8px 0pt 0pt -8px',
                overflow:'hidden',
                width:'17px'
            },
            'LIST a':{
                height: '12px',
                width: '10px',
                'font-size':linb.browser.ie6?'0':null,
                'float': 'left',
                display: 'block',
                overflow: 'hidden',
                'text-indent': '100px',
                margin: '0',
                cursor: 'pointer',
                border: '1px solid #000',
                margin:'0 -1px -1px 0'
            },
            'LIST a:hover':{
                border: '1px solid black'
            },
            SET:{
                position:'absolute',
                display:'none',
                top:'0',
                right:'38px'
            },
            TOGGLE:{
                position:'absolute',
                right:'5px',
                top:'0'
            }
        },
        Behaviors:{
            HoverEffected:{CLOSE:'CLOSE',SET:'SET',TOGGLE:'TOGGLE'},
            ClickEffected:{CLOSE:'CLOSE',SET:'SET',TOGGLE:'TOGGLE'},
            KEY:{onClick:function(){return false}},
            SC:{
                onMouseover:function(p,e,s){
                    p.box._setTempUI(p,p.getSubId(s));
                },
                onClick:function(p,e,s){
                    var sid=p.getSubId(s);
                    p.boxing()._setCtrlValue(p.$tempValue=sid,false);
                    if(!p.properties.advance)
                        p.boxing().setUIValue(sid);
                    p.box._vC(p);
                    return false;
                }
            },
            LIST:{
                onMouseout:function(p,e,s){
                    p.box._updateDftTip(p);
                }
            },
            SET:{
                onClick:function(p,e,src){
                    p.boxing().setUIValue(p.$tempValue,true);
                    p.box._vC(p);
                }
            },
            CANCEL:{
                onClick:function(p,e,src){
                    p.getSubNode('CLOSE').onClick(true);
                }
            },
            TOGGLE:{
                onClick:function(p,e,src){
                    p.boxing().setAdvance(!p.properties.advance)
                }
            },
            R:{
                onMousedown:function(p, e, src){
                    p.box._dd1(p,e,src);
                },
                onDrag:function(p, e, src){
                    p.box._dd2(p,e,src,0);
                },
                onDragstop:function(p, e, src){
                    p.box._dd3(p,e,src,0);
                }
            },
            G:{
                onMousedown:function(p, e, src){
                    p.box._dd1(p,e,src);
                },
                onDrag:function(p, e, src){
                    p.box._dd2(p,e,src,1);
                },
                onDragstop:function(p, e, src){
                    p.box._dd3(p,e,src,1);
                }
            },
            B:{
                onMousedown:function(p, e, src){
                    p.box._dd1(p,e,src);
                },
                onDrag:function(p, e, src){
                    p.box._dd2(p,e,src,2);
                },
                onDragstop:function(p, e, src){
                    p.box._dd3(p,e,src,2);
                }
            },
            HH:{
                onMousedown:function(p, e, src){
                    p.box._dd1(p,e,src,true);
                },
                onDrag:function(p, e, src){
                    p.box._dd2(p,e,src,0,'hsv1');
                },
                onDragstop:function(p, e, src){
                    p.box._dd3(p,e,src,0,true,'hsv1');
                }
            },
            S:{
                onMousedown:function(p, e, src){
                    p.box._dd1(p,e,src,true);
                },
                onDrag:function(p, e, src){
                    p.box._dd2(p,e,src,1,'hsv2');
                },
                onDragstop:function(p, e, src){
                    p.box._dd3(p,e,src,1,true,'hsv2');
                }
            },
            V:{
                onMousedown:function(p, e, src){
                    p.box._dd1(p,e,src,true);
                },
                onDrag:function(p, e, src){
                    p.box._dd2(p,e,src,2,'hsv2');
                },
                onDragstop:function(p, e, src){
                    p.box._dd3(p,e,src,2,true,'hsv2');
                }
            },
            H:{
                onMousedown:function(p, e, src){
                    p.box._dd1(p,e,src);
                },
                onDrag:function(p, e, src){
                    p.box._dd2(p,e,src,0,'hex');
                },
                onDragstop:function(p, e, src){
                    p.box._dd3(p,e,src,0);
                }
            },
            'E':{
                onMousedown:function(p, e, src){
                    p.box._dd1(p,e,src);
                },
                onDrag:function(p, e, src){
                    p.box._dd2(p,e,src,1,'hex');
                },
                onDragstop:function(p, e, src){
                    p.box._dd3(p,e,src,1);
                }
            },
            X:{
                onMousedown:function(p, e, src){
                    p.box._dd1(p,e,src);
                },
                onDrag:function(p, e, src){
                    p.box._dd2(p,e,src,2,'hex');
                },
                onDragstop:function(p, e, src){
                    p.box._dd3(p,e,src,2);
                }
            },
            CLOSE:{
                onClick:function(profile, e, src){
                    var properties = profile.properties,
                        instance = profile.boxing();
                    if(properties.disabled)return;
                    if(false===instance.beforeClose(profile)) return;
                    instance.destroy();
                    //for design mode in firefox
                    return false;
                }
            },
            ADVWHEEL:{
                onMousedown:function(p, e, src){
                    var cls=p.box;
                    cls._prepareAdv(p,e);
                    cls._updateClrByPos(p,e,true);
                    p.getSubNode('ADVMARK1').startDrag(e, {
                        dragType:'none'
                    });
                }
            },
            ADVMARK1:{
                onMousedown:function(p, e, src){
                    var cls=p.box;
                    cls._prepareAdv(p,e);
                    cls._updateClrByPos(p,e,true);
                    p.getSubNode('ADVMARK1').startDrag(e, {
                        dragType:'none'
                    });
                },
                onDrag:function(p, e, src){
                    var cls=p.box;
                    cls._updateClrByPos(p,e,true);
                },
                onDragstop:function(p, e, src){
                    p.box._updateValueByPos(p, e);
                }
            },
            ADVCLR:{
                onMousedown:function(p, e, src){
                    var cls=p.box;
                    cls._prepareAdv(p,e);
                    cls._updateClrByPos(p,e);
                    p.getSubNode('ADVMARK2').startDrag(e, {
                        dragType:'none'
                    });
                    return false;
                }
            },
            ADVMARK2:{
                onMousedown:function(p, e, src){
                    var cls=p.box;
                    cls._prepareAdv(p,e);
                    cls._updateClrByPos(p,e);
                    p.getSubNode('ADVMARK2').startDrag(e, {
                        dragType:'none'
                    });
                    return false;
                },
                onDrag:function(p, e, src){
                    var cls=p.box;
                    cls._updateClrByPos(p, e);
                },
                onDragstop:function(p, e, src){
                    p.box._updateValueByPos(p, e);
                }
            }
        },
        _vC:function(profile){
            var pro=profile.properties,
                v=pro.$UIvalue,
                d=v==profile.$tempValue;
            profile.getSubNode('SET').css('display',d?'none':'block');
            profile.getSubNode('CAPTION').css('color',d?'#000':'#ff0000');
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile);
            var nodisplay='display:none';
            data.classBar= data.barDisplay?'uibar-top':'uibar-top-s';
            data.closeDisplay = data.closeBtn?'':nodisplay;
            data._width = data.advance?'410':'210';
            data.advDispay = data.advance?'':'display:none;';
            return data;
        },
        EventHandlers:{
            beforeClose:function(profile, src){}
        },
        RenderTrigger:function(){
            this.$onValueSet=this.$onValueUpdated=function(v){
                this.box._setClrName(this,v);
            };
        },
        _setClrName:function(profile,v){
            var p=profile,
                k='color.LIST.',
                vv=linb.getRes(k+v);
            if(vv==v)
                p.$clrN2 = p.$clrN = '#'+v;
            else{
                p.$clrN = vv;
                p.$clrN2 = linb.wrapRes(k+v);
            }
        },
        _slist:"FFFFFF,FFFFF0,FFFFE0,FFFF00,FFFAFA,FFFAF0,FFFACD,FFF8DC,FFF5EE,FFF0F5,FFEFD5,FFEBCD,FFE4E1,FFE4C4,FFE4B5,FFDEAD,FFDAB9,FFD700,FFC0CB,FFB6C1,FFA500,FFA07A,FF8C00,FF7F50,FF69B4,FF6347,FF4500,FF1493,FF00FF,FF00FF,FF0000,FDF5E6,FAFAD2,FAF0E6,FAEBD7,FA8072,F8F8FF,F5FFFA,F5F5F5,F5DEB3,F4A460,F0FFFF,F0FFF0,F0F8FF,F0E68C,F08080,EEE8AA,EE82EE,E9967A,E6E6FA,E1FFFF,DEB887,DDA0DD,DCDCDC,DC143C,DB7093,DAA520,DA70D6,D8BFD8,D3D3D3,D2B48C,D2691E,CD853F,CD5C5C,C71585,C0C0C0,BDB76B,BC8F8F,BA55D3,B22222,B0E0E6,B0C4DE,AFEEEE,ADFF2F,ADD8E6,A9A9A9,A52A2A,A0522D,9932CC,98FB98,9400D3,9370DB,90EE90,8FBC8F,8B4513,8B008B,8B0000,8A2BE2,87CEFA,87CEEB,808080,808000,800080,800000,7FFFAA,7FFF00,7CFC00,7B68EE,778899,708090,6B8E23,6A5ACD,696969,6495ED,5F9EA0,556B2F,4B0082,48D1CC,483D8B,4682B4,4169E1,40E0D0,3CB371,32CD32,2F4F4F,2E8B57,228B22,20B2AA,1E90FF,191970,00FFFF,00FFFF,00FF7F,00FF00,00FA9A,00CED1,00BFFF,008B8B,008080,008000,006400,0000FF,0000CD,00008B,000080,000000".split(','),
        _C16:"0123456789ABCDEF",
        //for drag rgb span
        _dd1:function(profile, e, src, hsv){
            var p=profile.properties,
                cls=profile.box,
                f=function(){var rgb = cls.hex2rgb(profile.$tempValue||p.$UIvalue); return hsv?cls.rgb2hsv(rgb):rgb;};

            linb.use(src).css('backgroundColor','red').startDrag(e, {
                dragType:'blank',
                targetReposition:false,
                widthIncrement:2,
                dragCursor:true
            });
            profile.$temp=0;
            profile.$start = f();
            profile.$temp2 = f();
        },
        _dd2:function(profile, e, src, i, type){
            var count,
                off = linb.DragDrop.getProfile().offset,
                p=profile.properties,
                old=profile.$temp2,
                cls=profile.box,
                rate = type=='hsv1'?361:type=='hsv2'?101:256,
                v;

            count = (type=='hsv2'?parseInt(profile.$start[i]*100):parseInt(profile.$start[i]))+parseInt(off.x/2);

            count=(count%rate+rate)%rate;
            if(profile.$temp!=count){
                old[i]=profile.$temp = type=='hsv2'?count/100:count;
                v = (type=='hsv1'||type=='hsv2')?cls.hsv2rgb(old):old;
                v=cls.rgb2hex(v);
                cls._setTempUI(profile,v);
                linb.use(src).text(type=='hex'?cls._toFF(count):count);
            }
        },
        _dd3:function(profile, e, src, i, hsv){
            if(profile.$start[i] !== profile.$temp){
                var p=profile.properties,
                    cls=profile.box,
                    old=profile.$start,
                    v;
                old[i]=profile.$temp;
                v=hsv?cls.hsv2rgb(old):old;
                v=cls.rgb2hex(v);

                //set the cur hex value of hsv for preventing update adv UI again
                if(hsv)profile.$hexinhsv=v;
                profile.boxing()._setCtrlValue(profile.$tempValue=v,false);
                delete profile.$hexinhsv;
                profile.box._vC(profile);
            }
            linb.use(src).css('backgroundColor','');
            profile.$temp=profile.$start=0;
        },
        //set temp UI
        _setTempUI:function(p,v){
            var cls=this,
                rgb=cls.hex2rgb(v),
                b=p.boxing(),
                ex=b.getSubNode('EXAMI'),
                hsv=cls.rgb2hsv(rgb),
                vv=linb.getRes('color.LIST.'+v);
            ex.css({backgroundColor:'#'+v, color:hsv[2]>0.6?'#000':'#FFF'});
            ex.text(p.show_color=vv==v?'#'+v:vv);
        },
        //reset example block
        _updateDftTip:function(p){
            var cls=p.box,
                ex=p.boxing().getSubNode('EXAMI');
            ex.css({backgroundColor:'#'+p.$hex.join(''), color:p.$hsv[2]>0.6?'#000':'#FFF'});
            ex.html(p.$clrN2||'',false);
        },
        _to3:function(s){
            if(!s)s="FFFFFF";
            return [s.substr(0, 2), s.substr(2, 2), s.substr(4, 2)];
        },
        //0...255 to 00...FF
        _toFF: function(n) {
            var C16=this._C16;
            n = parseInt(n)||0;
            n = (n>255||n<0)?0:n;
            return C16.charAt((n-n%16)/16) + C16.charAt(n%16);
        },
        // 00...FF to 0...255
        _to255: function(str) {
            var C16=this._C16, s=str.split('');
            return C16.indexOf(s[0].toUpperCase())*16 + C16.indexOf(s[1].toUpperCase());
        },
        _webSafe:function(r, g, b){
            //safe divisor is 51, smart divisor is 17
            var me=arguments.callee,f=me.f||(me.f=function(n){
                return parseInt(n/51)*51;
            });
            if(typeof r=='object'){
                g=r[1];b=r[2];r=r[0];
            }
            return [f(r),f(g),f(b)];
        },
        _updateMarks:function(profile, hex, forcePos, hsv0){
            var cls=this,
                rgb=cls.hex2rgb(hex),
                hsv=cls.rgb2hsv(rgb),
                angle=(hsv[0]/360)*6.28,
                clr=profile.getSubNode('ADVCLR');
            if(forcePos){
                var m1=profile.getSubNode('ADVMARK1'),
                    m2=profile.getSubNode('ADVMARK2');
                m1.cssPos({
                  left: Math.round(Math.sin(angle)*cls._radius+cls._bigRadius),
                  top: Math.round(-Math.cos(angle)*cls._radius+cls._bigRadius)
                });
                m2.cssPos({
                  left: Math.round(cls._square*(hsv[1]-0.5)+cls._bigRadius),
                  top: Math.round(cls._square*(0.5-hsv[2])+cls._bigRadius)
                });
            }

            if(hsv0 !== undefined)
                clr.css('backgroundColor', '#'+cls.rgb2hex(cls.hsv2rgb([hsv0, 1, 1])));
            cls._setTempUI(profile, hex);
        },
        //flag:change h
        _updateClrByPos:function(profile, e, flag){
            var cls=this,
                mPos=linb.Event.getPos(e),
                pos=profile.$tpos,
                left=mPos.left-pos.left,
                top=mPos.top-pos.top,
                angle,m1,m2,
                h,s,v,hsv,rgb,hex;
            ;
            if(flag){
                m1=profile.getSubNode('ADVMARK1');
                angle=Math.atan2(left, -top);
                m1.cssPos({
                  left: Math.round(Math.sin(angle)*cls._radius+cls._bigRadius),
                  top: Math.round(-Math.cos(angle)*cls._radius+cls._bigRadius)
                });
                h=Math.floor((angle/6.28)*360);
                if(h<0)h +=360;
                hsv=[h, profile.$hsv[1], profile.$hsv[2]];
                rgb = cls.hsv2rgb(hsv);
                hex = cls.rgb2hex(rgb);
                cls._updateMarks(profile, profile.$t_hex=hex, false, h);
            }else{
                m2=profile.getSubNode('ADVMARK2');
                s=Math.max(0, Math.min(1, (left/cls._square) + 0.5));
                v=Math.max(0, Math.min(1, 0.5 - (top/cls._square)));
                m2.cssPos({
                  left: Math.round(cls._square*(s-0.5)+cls._bigRadius),
                  top: Math.round(cls._square*(0.5-v)+cls._bigRadius)
                });
                hsv=[profile.$hsv[0], s, v];
                rgb = cls.hsv2rgb(hsv);
                hex = cls.rgb2hex(rgb);
                cls._updateMarks(profile, profile.$t_hex=hex);
            }

        },
        _updateValueByPos:function(profile, e){
            //set the cur hex value of adv for preventing update adv UI again
            profile.$hexinadv=profile.$t_hex;
            profile.boxing()._setCtrlValue(profile.$tempValue=profile.$t_hex,false);
            delete profile.$hexinadv;
            profile.box._vC(profile);
        },
        _prepareAdv:function(profile,e){
            var cls=this,
                pos=profile.getSubNode('ADVWHEEL').offset();
            profile.$tpos= { left:pos.left+cls._bigRadius, top:pos.top+cls._bigRadius };
        },
        _ensureValue:function(profile,v){
            var ns=this,me=arguments.callee,map=me.map||(me.map=(function(){
                var h={};
                _.arr.each(ns._C16.split(''),function(o,i){
                    h[o]=1;
                });
                return h;
            }())),
            reg=me._r||(me._r=/rgb\(([^)]*)\)/);
            if(!v || typeof v !='string')return 'FFFFFF';
            if(reg.test(v)){
                v=v.replace(reg,'$1');
                v=v.split(',');
                v[0]=parseInt(v[0])||0;
                v[1]=parseInt(v[1])||0;
                v[2]=parseInt(v[2])||0;
                v=ns.rgb2hex(v);
            }
            if(v.charAt(0)=='#')v=v.substr(1,v.length);
            var a='',k;
            for(var i=0;i<6;i++){
                k=v.charAt(i).toUpperCase();
                a += (map[k]?k:'F');
            }
           return a;
        },
        //HSV (h[0-360], s[0-1]), v[0-1] to RGB [255,255,255]
        hsv2rgb: function(h, s, v) {
            if(h instanceof Array) {
                s=h[1]; v=h[2]; h=h[0];
            }
            var me=arguments.callee, f = me.f ||
                (me.f=function(n) {
                    return Math.min(255, Math.round(n*256));
                }),
                r, g, b, i, k, p, q, t;
            if(s==0)
                return [v=f(v),v,v];
            else{
                i = Math.floor((h/60)%6);
                k = (h/60)-i;
                p = v*(1-s);
                q = v*(1-k*s);
                t = v*(1-(1-k)*s);
                switch(i) {
                    case 0: r=v; g=t; b=p; break;
                    case 1: r=q; g=v; b=p; break;
                    case 2: r=p; g=v; b=t; break;
                    case 3: r=p; g=q; b=v; break;
                    case 4: r=t; g=p; b=v; break;
                    case 5: r=v; g=p; b=q; break;
                }
                return s==0?[v=f(v),v,v]:[f(r), f(g), f(b)];
            }
        },
        // RGB [255,255,255] to HSV (h[0-360], s[0-1]), v[0-1]
        rgb2hsv: function(r, g, b) {
            if(r instanceof Array) {
                g=r[1];b=r[2];r=r[0];
            }
            r=r/255;g=g/255;b=b/255;
            var min=Math.min(r,g,b),
                max=Math.max(r,g,b),
                delta = max-min,
                s = (max===0)?0:1-(min/max),
                v = max,
                h;
            switch (max) {
                case min:
                    h=0;
                    break;
                case r:
                    h=60*(g-b)/delta;
                    if(g<b)h+=360;
                    break;
                case g:
                    h=(60*(b-r)/delta)+120;
                    break;
                case b:
                    h=(60*(r-g)/delta)+240;
                    break;
            }
            return [Math.round(h), s, v];
        },
        //rgb values into a hex string; 255,255,255 -> FFFFFF
        rgb2hex: function(r, g, b) {
            var ns=this;
            if(r instanceof Array) {
                g=r[1];b=r[2];r=r[0];
            }
            return ns._toFF(r) + ns._toFF(g) + ns._toFF(b);
        },
        // Converts a hex string to rgb
        hex2rgb: function(hex) {
            var ns=this;
            if(!hex)hex="FFFFFF";
            if(hex.charAt(0)=='#')hex=hex.slice(1);
            return [ns._to255(hex.substr(0, 2)), ns._to255(hex.substr(2, 2)), ns._to255(hex.substr(4, 2))];
        },
        getTextColor:function(value){
            var ns=this;
            value=ns._ensureValue(0,value);
            value=ns.hex2rgb(value);
            value=ns.rgb2hsv(value);
            return (value&&value[2])>0.6?'#000000':'#FFFFFF';
        },
        _onresize:function(){}
    }
});Class('linb.UI.DatePicker', ['linb.UI',"linb.absValue"], {
    Dependency:['linb.Date'],
    Instance:{
        activate:function(){
            this.getSubNode('PRE').focus();
            return this;
        },
        _setCtrlValue:function(value){
            return this.each(function(profile){
                if(!profile.renderId)return;
                var cls = profile.box,
                    p = profile.properties,
                    date=linb.Date,
                    mfirst=date.getTimSpanStart(value,'m');
                cls._to(profile,mfirst,value);
                if(profile.keys.CAPTION)
                    profile.getSubNode('CAPTION').html(date.getText(value,'ymd',p.WEEK_FIRST),false);
            });
        },
        getDateFrom:function(){
            return this.get(0)._realstart;
        }
    },
    Initialize:function(){
        var self=this,
            id=linb.UI.$ID,
            cls=linb.UI.$CLS,
            cls2=cls+'-td-free',
            key=self.KEY;
            
        self.addTemplateKeys(['H', 'W','TBODY', 'TD']);
        var colgroup = '<colgroup><col width="2%"/><col width="14%"/><col width="14%"/><col width="14%"/><col width="14%"/><col width="14%"/><col width="14%"/><col width="14%"/></colgroup>',
            thead1='<thead><tr height="1%"><th id="'+key+'-H:'+id+':7" class="'+cls+'-h #H_CC#"></th>',
            thead2='</tr></thead>',
            th='<th id="'+key+'-H:'+id+':@" class="'+cls+'-h #H_CC#">@</th>',
            tbody1 = '<tbody id="'+key+'-TBODY:'+id +':" >',
            tbody2 = '</tbody>',
            tr1='<tr>',
            tr2='</tr>',
            td1='<th id="'+key+'-W:'+id+':@"  class="'+cls+'-w #W_CC#">@</th>',
            td2='<td id="'+key+'-TD:'+id+':@" class="'+cls+'-td ! #TD_CC#"  unselectable="on" >'+
                '</td>',
            body,i,j,k,l,a=[],b=[];
        for(i=0;i<7;i++)
            b[b.length]= th.replace(/@/g,i);

        k=l=0;
        for(i=0;i<48;i++){
            j=i%8;
            a[a.length]= (j==0?tr1:'') + (j==0?td1:td2).replace(/@/g,j==0?l:k).replace('!',(j==1||j==7)?cls2:'') + (j==7?tr2:'');
            if(j!==0)k++;
            else l++;
        }

        body=colgroup+thead1+b.join('')+thead2+tbody1+a.join('')+tbody2;

        self.setTemplate({
            tagName : 'div',
            style:'{_style};height:auto;',
            onselectstart:'return false',
            BORDER:{
                tagName : 'div',
                BAR:{
                    tagName:'div',
                    className:'uibar-top',
                    style:'{barDisplay};',
                    BART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        className:'uibar-t',
                        tagName:'table',
                        BARTR:{
                            tagName:'tr',
                            BARTDL:{
                                tagName:'td',
                                className:'uibar-tdl'
                            },
                            BARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'uibar-tdm'
                            },
                            BARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'uibar-tdr'
                            }
                        }
                    },
                    BARCMDL:{
                        tagName:'div',
                        className:'uibar-cmdl',
                        PRE2:{
                            $order:0,
                            tagName:'a',
                            href:linb.$href,
                            tabindex: '{tabindex}'
                        },
                        PRE:{
                            $order:1,
                            tagName:'a',
                            href:linb.$href,
                            tabindex: '{tabindex}'
                        },
                        YEAR:{$order:2,unselectable:'on',
                            className:'ui-dragable'},
//                        YTXT:{$order:3,style:'display:inline'},
                        MONTH:{$order:4,unselectable:'on',
                            className:'ui-dragable'},
                        MTXT:{$order:5,style:'display:inline'},
                        NEXT:{
                            $order:6,
                            tagName:'a',
                            href:linb.$href,
                            tabindex: '{tabindex}'
                        },
                        NEXT2:{
                            $order:7,
                            tagName:'a',
                            href:linb.$href,
                            tabindex: '{tabindex}'
                        }
                    },
                    BARCMDR:{
                        tagName: 'div',
                        className:'uibar-cmdr',
                        onselectstart:'return false',
                        unselectable:'on',
                        CLOSE:{
                            className:'uicmd-close ',
                            style:'{closeDisplay}'
                        }
                    }
                },
                MAIN:{
                    $order:2,
                    tagName:'div',
                    className:'uicon-main',
                    MAINI:{
                        tagName:'div',
                        className:'uicon-maini',
                        CON:{
                            tagName:'div',
                            BODY:{
                                tagName:'table',
                                cellpadding:"0",
                                cellspacing:"0",
                                width:'100%',
                                text:body
                            }
                        }
                    }
                },
                TAIL:{
                    $order:3,
                    tagName:'div',
                    className:'uicon-main',
                    TAILI:{
                        tagName:'div',
                        className:'uicon-maini',
                        CAPTION:{
                            text : '{caption}',
                            $order:1
                        },
                        TODAY:{
                            className:'ui-btn',
                            TODAYI:{
                                className:'ui-btni',
                                TODAYC:{
                                    className:'ui-btnc',
                                    TODAYA:{
                                        tagName:'a',
                                        href:linb.$href,
                                        tabindex: '{tabindex}',
                                        text:linb.wrapRes('inline.today')
                                    }
                                }
                            }
                        }
                    }
                },
                BBAR:{
                    $order:4,
                    tagName:'div',
                    className:'uibar-bottom-s',
                    BBART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        tagName:'table',
                        className:'uibar-t',
                        BBARTR:{
                            tagName:'tr',
                            BBARTDL:{
                                tagName:'td',
                                className:'uibar-tdl'
                            },
                            BBARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'uibar-tdm'
                            },
                            BBARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'uibar-tdr'
                            }
                        }
                    }
                }
            }
        });
    },
    Static:{
        Appearances:{
            KEY:{
                overflow:'visible',
                '-moz-user-select': 'none'
            },
            BORDER:{
                overflow: 'visible',
                position: 'relative'
            },
            BODY:{
                position:'relative'
            },
            BARCMDL:{
                top:'3px'
            },
            TAILI:{
                position:'relative',
                'padding-top':'4px',
                height:'22px',
                'text-align':'center'
            },
            TODAY:{
                position:'absolute',
                top:'0',
                right:'5px'
            },
            'PRE,PRE2,NEXT,NEXT2':{
                $order:0,
                display:linb.$inlineBlock,
                position:'relative',
                margin:'0 2px',
                width:'15px',
                height:'15px',
                'vertical-align': 'middle',
                cursor:'default',
                background: linb.UI.$bg('icons.gif', 'no-repeat', true),
                _zoom:1
            },
            PRE:{
                $order:1,
                'background-position': '-260px -70px'
            },
            'PRE-mouseover':{
                $order:2,
                'background-position': '-260px -90px'
            },
            'PRE-mousedown':{
                $order:3,
                'background-position': '-260px -110px'
            },
            PRE2:{
                $order:1,
                'background-position': '-240px -70px'
            },
            'PRE2-mouseover':{
                $order:2,
                'background-position': '-240px -90px'
            },
            'PRE2-mousedown':{
                $order:3,
                'background-position': '-240px -110px'
            },
            NEXT:{
                $order:1,
                'background-position': '-280px -70px'
            },
            'NEXT-mouseover':{
                $order:2,
                'background-position': '-280px -90px'
            },
            'NEXT-mousedown':{
                $order:3,
                'background-position': '-280px -110px'
            },
            NEXT2:{
                $order:1,
                'background-position': '-300px -70px'
            },
            'NEXT2-mouseover':{
                $order:2,
                'background-position': '-300px -90px'
            },
            'NEXT2-mousedown':{
                $order:3,
                'background-position': '-300px -110px'
            },
            'YEAR,MONTH':{
                $order:4,
                margin:'0 2px',
                height:'15px',
                'font-weight':'bold',
                'vertical-align': 'middle',
                border:'1px solid #779EBF',
                'background-color':'#F8FBFF',
                'padding-left':'2px',
                cursor:'e-resize'
            },
            YEAR:{
                width:'32px'
            },
            MONTH:{
                width:'16px'
            },
            CAPTION:{
                'font-size':'12px',
                'vertical-align':'middle'
            },
            MAINI:{
                'padding-top':'4px',
                'padding-bottom':'4px'
            },
            CON:{
                'border-left':'solid 1px #648CB4',
                'border-top':'solid 1px #648CB4'
            },
            BODY:{
                overflow: 'visible'
            },
            'BODY td,BODY th':{
                $order:1,
                border:0,
                'border-right':'solid 1px #648CB4',
                'border-bottom':'solid 1px #648CB4'
            },
            'TD .exday':{
                color:'#C1C1C1'
            },
            TD:{
                'text-align':'center',
                'background-color': '#EFF8FF'
            },
            'TD-free':{
                $order:1,
                'text-align':'center',
                'background-color': '#F9F7D1'
            },
            'TD-mouseover':{
                $order:3,
                'background-color': '#d9e8fb'
            },
            'TD-checked':{
                $order:4,
                'background-color':'#316AC5',
                'font-weight':'bold',
                color:'#fff'
            },
            'W,H':{
                $order:3,
                'color':'#333333',
                'background-color':'#E8EEF7',
                'vertical-align':'middle',
                'text-align':'center'
            }
        },
        Behaviors:{
            HoverEffected:{CLOSE:'CLOSE',TD:'TD',PRE:'PRE',PRE2:'PRE2',NEXT:'NEXT',NEXT2:'NEXT2',TODAY:'TODAY'},
            ClickEffected:{CLOSE:'CLOSE',TD:'TD',PRE:'PRE',PRE2:'PRE2',NEXT:'NEXT',NEXT2:'NEXT2',TODAY:'TODAY'},
            KEY:{onClick:function(){return false}},
            TD:{
                onClick:function(profile, e, src){
                    var p=profile.properties,
                        id=profile.getSubId(src),
                        map=profile.$daymap,
                        v=map[id];
                    if(p.disabled)return false;

                    linb.use(src).onMouseout(true,{$force:true});
                    //onClick event
                    profile.boxing().setUIValue(v);
                }
            },
            TODAY:{
                onClick:function(profile){
                    profile.boxing().setUIValue(new Date,true);
                }
            },
            CLOSE:{
                onClick:function(profile, e, src){
                    var properties = profile.properties,
                        instance = profile.boxing();
                    if(properties.disabled)return;
                    if(false===instance.beforeClose(profile, src)) return;
                    instance.destroy();
                    //for design mode in firefox
                    return false;
                }
            },
            PRE:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled)return;
                    profile.box._to(profile, linb.Date.add(profile.$mfirst,'m',-1,p.WEEK_FIRST));
                }
            },
            NEXT:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled)return;
                    profile.box._to(profile, linb.Date.add(profile.$mfirst,'m',1,p.WEEK_FIRST));
                }
            },
            PRE2:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled)return;
                    profile.box._to(profile, linb.Date.add(profile.$mfirst,'y',-1,p.WEEK_FIRST));
                }
            },
            NEXT2:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled)return;
                    profile.box._to(profile, linb.Date.add(profile.$mfirst,'y',1,p.WEEK_FIRST));
                }
            },
            YEAR:{
                onMousedown:function(profile, e, src){
                    linb.use(src).startDrag(e, {
                        dragType:'blank',
                        targetReposition:false,
                        widthIncrement:20,
                        dragCursor:true
                    });
                    profile.$temp=profile.$temp2=0;
                },
                onDrag:function(profile, e, src){
                    var count,off = linb.DragDrop.getProfile().offset;
                    count=parseInt(profile.$year)+(profile.$temp2=parseInt(off.x/20));
                    if(profile.$temp!=count){
                        profile.$temp=count;
                        profile.getSubNode('YEAR').html(count,false);
                    }
                },
                onDragstop:function(profile, e, src){
                    if(profile.$temp2){
                        var p=profile.properties,
                            v = linb.Date.add(profile.$mfirst,'y',profile.$temp2,p.WEEK_FIRST);
                        profile.box._to(profile,linb.Date.getTimSpanStart(v,'m'));
                    }
                    profile.$temp=profile.$temp2=0;
                }
            },
            MONTH:{
                onMousedown:function(profile, e, src){
                    linb.use(src).startDrag(e, {
                        dragType:'blank',
                        targetReposition:false,
                        widthIncrement:20,
                        dragCursor:true
                    });
                    profile.$temp=profile.$temp2=0;
                },
                onDrag:function(profile, e, src){
                    var count,off = linb.DragDrop.getProfile().offset;
                    count=parseInt(profile.$month)+(parseInt(off.x/20)%12);
                    count=(count%12+12)%12;
                    if(profile.$temp!=count){
                        profile.$temp=count;
                        profile.$temp2=count-profile.$month+1;
                        profile.getSubNode('MONTH').html(count+1,false);
                    }
                },
                onDragstop:function(profile, e, src){
                    if(profile.$temp2){
                        var p=profile.properties,
                            v = linb.Date.add(profile.$mfirst,'m',profile.$temp2,p.WEEK_FIRST);
                        profile.box._to(profile,linb.Date.getTimSpanStart(v,'m'));
                    }
                    profile.$temp=profile.$temp2=0;
                }
            }
        },
        DataModel:{
            height:{
                ini:'auto',
                readonly:true
            },
            width:{
                ini:210,
                readonly:true
            },
            value:new Date,
            closeBtn:{
                ini:true,
                action:function(v){
                    this.getSubNode('CLOSE').css('display',v?'':'none');
                }
            }
        },
        EventHandlers:{
            beforeClose:function(profile, src){}
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile);
            var nodisplay='display:none';
            data.closeDisplay = data.closeBtn?'':nodisplay;
            return data;
        },
        RenderTrigger:function(){
            var self=this, p=self.properties, o=self.boxing(), b=self.box;
            b._setWeekLabel(self);
//            self.getSubNode('YTXT').html(linb.wrapRes('date.Y'),false);
//            self.getSubNode('MTXT').html(linb.wrapRes('date.M'),false);
        },
        _getWeekNodes:function(profile){
            return profile.$week || (profile.$week=profile.getSubNode('W',true));
        },
        _getTDNodes:function(profile){
            return profile.$tds || (profile.$tds=profile.getSubNode('TD',true));
        },
        _getLabelNodes:function(profile){
            return profile.$day || (profile.$day=profile.getSubNode('TD',true));
        },
        _getHeaderNodes:function(profile){
            return profile.$header || (profile.$header=profile.getSubNode('H',true));
        },
        _setWeekLabel:function(profile){
            var o=linb.Date,f=profile.getSubId;
            profile.box._getHeaderNodes(profile).each(function(node,i){
                node.innerHTML=linb.wrapRes('date.WEEKS.'+f(node.id))
            });
        },
        _setBGV:function(profile, v, m){
            var date=linb.Date,
                p=profile.properties,
                daymap=profile.$daymap||(profile.$daymap=[]),
                t,n,
                fd=p.WEEK_FIRST;
            profile.box._getLabelNodes(profile).each(function(node,i){
                n=date.add(v,'d',i,fd);
                daymap[i]=n;
                t=date.get(n,'m',fd)==m?'#':'<p class="exday">#</p>';
                n=date.get(n,'d',fd);
                node.innerHTML = t.replace('#',n);
            });
            profile.box._getWeekNodes(profile).each(function(node,i){
                node.innerHTML=date.get(date.add(v,'ww',i,fd),'ww',fd);
            });
        },
        _to:function(profile, mfirst, value){
            var p = profile.properties,
                fd=p.WEEK_FIRST,
                date=linb.Date,
                keys=profile.keys,
                uiv=value||p.$UIvalue,
                md=date.get(uiv,'m',fd)+'-'+date.get(uiv,'d',fd),
                ym1=date.get(uiv,'y',fd)+'-'+date.get(uiv,'m',fd),
                ym2=date.get(mfirst,'y',fd)+'-'+date.get(mfirst,'m',fd),
                index=-1,
                node,
                temp,
                _realstart = date.getTimSpanStart(date.getTimSpanStart(mfirst,'m'),'ww',1,fd),
                m=date.get(mfirst,'m',fd);

            profile.$mfirst=mfirst;
            this._setBGV(profile, profile._realstart=_realstart, m);


            //remove checked css class
            if(profile.$selnode)
                profile.$selnode.tagClass('-checked',false);
            if(ym1==ym2){
                _.arr.each(profile.$daymap,function(o,i){
                    if(date.get(o,'m',fd)+'-'+date.get(o,'d',fd)==md){
                        index=i;
                        return false;
                    }
                });
                node=this._getTDNodes(profile).get()[index];
                (profile.$selnode=linb([node]).tagClass('-checked'));
            }

            if(keys.YEAR){
                temp=date.get(mfirst,'y',fd);
                if(profile.$year!=temp){
                    profile.$year=temp;
                    profile.getSubNode('YEAR').html(temp,false);
                }
            }
            if(keys.MONTH){
                temp=date.get(mfirst,'m',fd)+1;
                if(profile.$month!=temp){
                    profile.$month=temp;
                    profile.getSubNode('MONTH').html(temp,false);
                }
            }
        },
        _onresize:function(){}
    }
});Class('linb.UI.TimePicker', ['linb.UI',"linb.absValue"], {
    Dependency:['linb.Date'],
    Instance:{
        activate:function(){
            this.getSubNode('PRE').focus();
            return this;
        },
        _setCtrlValue:function(value){
            return this.each(function(profile){
                if(!profile.renderId)return;

                var instance = profile.boxing(),
                    cls = profile.box,
                    p = profile.properties,
                    uiv = p.$UIvalue,
                    arr1=cls._v2a(uiv),
                    arr2=cls._v2a(value);
                profile.$hour=arr2[0];
                if(arr1[1])
                    cls._uncheck(profile.getSubNode('MI',arr1[1]).get(0));
                cls._check(profile.getSubNode('MI',arr2[1]).get(0));

                profile.getSubNode('HOUR').html(arr2[0],false);
                profile.getSubNode('CAPTION').html(profile.box._showV(profile,profile.box._v2a(arr2)),false);
            });
        }
    },
    Initialize:function(){
        this.addTemplateKeys(['MI']);

        var a=[],
            cls=this._excls,
            cls2=this._excls2,
            id=linb.UI.$ID,
            t='<span id="'+this.KEY+'-MI:'+id+':@" class="'+cls+' !" unselectable="on" >@</span>',
            i,m;

        for(i=0;i<60;i++)
            a[a.length]=t.replace(/@/g,i<10?'0'+i:i).replace('!',(i%5===0)?cls2:'');
        m=a.join('');
        a.length=0;

        this.setTemplate({
            tagName : 'div',
            onselectstart:'return false',
            style:'{_style};height:auto;',
            BORDER:{
                tagName : 'div',
                BAR:{
                    tagName:'div',
                    className:'uibar-top',
                    style:'{barDisplay};',
                    BART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        tagName:'table',
                        className:'uibar-t',
                        BARTR:{
                            tagName:'tr',
                            BARTDL:{
                                tagName:'td',
                                className:'uibar-tdl'
                            },
                            BARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'uibar-tdm'
                            },
                            BARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'uibar-tdr'
                            }
                        }
                    },
                    BARCMDL:{
                        tagName: 'div',
                        className:'uibar-cmdl',
                        PRE:{
                            $order:0,
                            tagName:'a',
                            href:linb.$href,
                            tabindex: '{tabindex}'
                        },
                        HOUR:{
                            $order:1,
                            unselectable:'on',
                            className:'ui-dragable'
                        },
//                        HOURTXT:{$order:2,style:'display:inline'},
                        NEXT:{
                            $order:3,
                            tagName:'a',
                            href:linb.$href,
                            tabindex: '{tabindex}'
                        }
                    },
                    BARCMDR:{
                        tagName: 'div',
                        className:'uibar-cmdr',
                        onselectstart:'return false',
                        unselectable:'on',
                        CLOSE:{
                            className:'uicmd-close ',
                            style:'{closeDisplay}'
                        }
                    }
                },
                MAIN:{
                    $order:2,
                    tagName:'div',
                    className:'uicon-main',
                    MAINI:{
                        tagName:'div',
                        className:'uicon-maini',
                        CON:{
                            tagName:'div',
                            text:m
                        }
                    }
                },
                TAIL:{
                    $order:3,
                    tagName:'div',
                    className:'uicon-main',
                    TAILI:{
                        tagName:'div',
                        className:'uicon-maini',
                        CAPTION:{
                            text : '{caption}'
                        },
                        SET:{
                            className:'ui-btn',
                            SETI:{
                                className:'ui-btni',
                                SETC:{
                                    className:'ui-btnc',
                                    SETA:{
                                        tagName:'a',
                                        href:linb.$href,
                                        tabindex: '{tabindex}',
                                        text:linb.wrapRes('inline.set')
                                    }
                                }
                            }
                        }
                    }
                },
                BBAR:{
                    $order:4,
                    tagName:'div',
                    className:'uibar-bottom-s',
                    BBART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        tagName:'table',
                        className:'uibar-t',
                        BBARTR:{
                            tagName:'tr',
                            BBARTDL:{
                                tagName:'td',
                                className:'uibar-tdl'
                            },
                            BBARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'uibar-tdm'
                            },
                            BBARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'uibar-tdr'
                            }
                        }
                    }
                }
            }
        });
    },
    Static:{
        _excls:'linbex-timepicker',
        _excls2:'linbex-timepicker2',
        _excls_mo:'linbex-timepicker-mouseover',
        _excls_c:'linbex-timepicker-checked',
        _mover:function(src){
            var b=this,cn=src.className;
            if(cn.indexOf(b._excls_mo)==-1)
                src.className=cn + ' ' + b._excls_mo;
            src=null;
        },
        _mout:function(src){
            var b=this,cn=src.className;
            if(cn.indexOf(b._excls_mo)!=-1)
                src.className=cn.replace(b._excls_mo,'');
            src=null;
        },
        _check:function(src){
            var b=this,cn=src.className;
            if(cn.indexOf(b._excls_c)==-1)
                src.className=cn + ' ' + b._excls_c;
            b._mout(src);
            src=null;
        },
        _uncheck:function(src){
            var b=this,cn=src.className;
            if(cn.indexOf(b._excls_c)!=-1)
                src.className=cn.replace(b._excls_c,'');
            src=null;
        },
        Appearances:{
            KEY:{
                '-moz-user-select': 'none'
            },
            MAINI:{
                'padding-top':'4px'
            },
            CON:{
                width:'220px',
                'border-left':'solid 1px #648CB4',
                'border-top':'solid 1px #648CB4'
            },
            BARCMDL:{
                top:'3px'
            },
            'PRE,NEXT':{
                position:'relative',
                margin:'0 2px',
                width:'15px',
                height:'15px',
                'vertical-align': 'middle',
                cursor:'default',
                background: linb.UI.$bg('icons.gif', 'no-repeat', true),
                _zoom:1
            },
            PRE:{
                $order:1,
                display:linb.$inlineBlock,
                'background-position': '-260px -70px'
            },
            'PRE-mouseover':{
                $order:2,
                'background-position': '-260px -90px'
            },
            'PRE-mousedown':{
                $order:3,
                'background-position': '-260px -110px'
            },
            NEXT:{
                $order:1,
                display:linb.$inlineBlock,
                'background-position': '-280px -70px'
            },
            'NEXT-mouseover':{
                $order:2,
                'background-position': '-280px -90px'
            },
            'NEXT-mousedown':{
                $order:3,
                'background-position': '-280px -110px'
            },
            HOUR:{
                $order:3,
                margin:'0 2px',
                height:'15px',
                width:'16px',
                'font-weight':'bold',
                'vertical-align': 'middle',
                border:'1px solid #779EBF',
                'background-color':'#F8FBFF',
                cursor:'e-resize',
                'padding-left':'2px'
            },
            SET:{
                position:'absolute',
                display:'none',
                color:'#ff0000',
                top:'1px',
                right:'5px'
            },
            TAILI:{
                position:'relative',
                'padding-top':'4px',
                height:'20px',
                'text-align':'center'
            },
            CAPTION:{
                'font-size':'12px',
                'vertical-align':'middle'
            },
            '.linbex-timepicker2':{
                $order:1,
                'background-color':'#FDF8D2'
            },
            '.linbex-timepicker':{
                'font-size':"12px",
                'padding-left':'3px',
                width:'18px',
                height:'16px',
                'border-right':'1px solid #648CB4',
                'border-bottom':'1px solid #648CB4',
                'background-color': '#F9F9FB'
            },
            '.linbex-timepicker-mouseover':{
                $order:2,
                'background-color': '#d9e8fb'
            },
            '.linbex-timepicker-checked':{
                $order:2,
                'background-color':'#316AC5',
                color:'#fff'
            }
        },
        Behaviors:{
            HoverEffected:{CLOSE:'CLOSE',PRE:'PRE',NEXT:'NEXT',SET:'SET'},
            ClickEffected:{CLOSE:'CLOSE',PRE:'PRE',NEXT:'NEXT',SET:'SET'},
            KEY:{onClick:function(){return false}},
            HOUR:{
                onMousedown:function(profile, e, src){
                    linb(src).startDrag(e, {
                        dragType:'blank',
                        targetReposition:false,
                        widthIncrement:5,
                        dragCursor:true
                    });
                    profile.$temp2=0;
                },
                onDrag:function(profile, e, src){
                    var count,off = linb.DragDrop.getProfile().offset,v=profile.properties.$UIvalue,a=v.split(':');
                    a[0]=(parseFloat(a[0])||0)+parseInt(off.x/10);
                    a[0]=(a[0]%24+24)%24;
                    profile.$temp2=(a[0]<=9?'0':'')+a[0];

                    if(v[0]!=profile.$temp2)
                        profile.getSubNode('HOUR').html(profile.$temp2,false);
                },
                onDragstop:function(profile, e, src){
                    if(profile.$temp2)
                        profile.$hour=profile.$temp2;
                    profile.$temp2=0;
                    profile.box._hourC(profile);
                }
            },
            SET:{
                onClick:function(profile){
                    var pro=profile.properties,
                        v=pro.$UIvalue,
                        a=v.split(':');
                    a[0]=profile.$hour;
                    profile.boxing().setUIValue(a.join(':'),true);
                    profile.box._hourC(profile);
                }
            },
            MI:{
                onMouseover:function(profile, e, src){
                    profile.box._mover(linb.use(src).get(0));
                },
                onMouseout:function(profile, e, src){
                    profile.box._mout(linb.use(src).get(0));
                },
                onClick:function(profile, e, src){
                    var a=[];
                    a[0]=profile.$hour;
                    a[1]=profile.getSubId(src);
                    profile.boxing().setUIValue(a.join(':'),true);
                    profile.box._hourC(profile);
                }
            },
            PRE:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled)return;
                    var v=profile.$hour;
                    v=(parseFloat(v)||0)-1;
                    v=(v%24+24)%24;
                    profile.$hour=v=(v<=9?'0':'')+v;
                    profile.getSubNode('HOUR').html(v,false);
                    profile.box._hourC(profile);
                }
            },
            NEXT:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled)return;
                    var v=profile.$hour;
                    v=(parseFloat(v)||0)+1;
                    v=(v%24+24)%24;
                    profile.$hour=v=(v<=9?'0':'')+v;
                    profile.getSubNode('HOUR').html(v,false);
                    profile.box._hourC(profile);
                }
            },
            CLOSE:{
                onClick:function(profile, e, src){
                    var properties = profile.properties,
                        instance = profile.boxing();
                    if(properties.disabled)return;
                    if(false===instance.beforeClose(profile, src)) return;
                    instance.destroy();
                    //for design mode in firefox
                    return false;
                }
            }
        },
        DataModel:{
            height:{
                ini:'auto',
                readonly:true
            },
            width:{
                ini:231,
                readonly:true
            },
            value:'00:00',
            closeBtn:{
                ini:true,
                action:function(v){
                    this.getSubNode('CLOSE').css('display',v?'':'none');
                }
            }
        },
        EventHandlers:{
            beforeClose:function(profile, src){}
        },
        _hourC:function(profile){
            var pro=profile.properties,
                v=pro.$UIvalue,
                a=v.split(':'),
                d=a[0]==profile.$hour;
            profile.getSubNode('SET').css('display',d?'none':'block');
            profile.getSubNode('CAPTION').css('color',d?'':'#ff0000');
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile);
            var nodisplay='display:none';
            data.closeDisplay = data.closeBtn?'':nodisplay;
            return data;
        },
//        RenderTrigger:function(){
//            this.getSubNode('HOURTXT').html(linb.wrapRes('date.H'),false);
//        },
        _ensureValue:function(profile, value){
            var a,b=[];
            if(value&& typeof value == 'string')
                a=value.split(':')
            else if(value && typeof value=='object' && _.isArr(value))
                a=value;
            else a=[];

            b[0]= parseFloat(a[0])||0;
            b[1]=parseFloat(a[1])||0;
            if(b[0]<0)b[0]=0;
            if(b[0]>23)b[0]=23;
            if(b[1]<0)b[1]=0;
            if(b[1]>59)b[1]=59;

            b[0]=(b[0]<=9?'0':'')+b[0];
            b[1]=(b[1]<=9?'0':'')+b[1];

            return b.join(':');
        },
        formatValue:function(value){
            return value.join(':');
        },        
        _v2a:function(v){
            return typeof v == 'string'? v.split(':') : v;
        },
        _showV:function(profile, a){
            var f=profile.CF;
            if(typeof f.formatCaption == 'function')
                return f.formatCaption(a);
            else
                return a.join(':');
        },
        _onresize:function(){}
    }
});Class("linb.UI.List", ["linb.UI", "linb.absList","linb.absValue" ],{
    Instance:{
        _setCtrlValue:function(value){
            return this.each(function(profile){
                if(!profile.renderId)return;

                var box=profile.box,
                    uiv=profile.boxing().getUIValue(),
                    p=profile.properties,
                    item=box._ITEMKEY || 'ITEM',
                    k=box._DIRTYKEY || 'ITEM',
                    getN=function(k,i){return profile.getSubNode(k,i)},
                    getI=function(i){return profile.getSubIdByItemId(i)};
                if(p.selMode=='single'){
                    var itemId = getI(uiv);
                    if(uiv!==null && itemId)
                        getN(k,itemId).tagClass('-mouseover',false).tagClass('-checked',false);

                    itemId = getI(value);
                    if(itemId)
                        getN(k,itemId).tagClass('-mouseover',false).tagClass('-checked');

                    //scroll
                    if(itemId){
                        var o = getN(item,itemId);
                        if(o){
                            var top = o.offsetTop(),
                            items = getN('ITEMS'),
                            sh=items.scrollHeight(),
                            st=items.scrollTop(),
                            hh=items.height()
                            ;
                            if(sh > hh)
                                if(top<st || top>st+hh)
                                    items.scrollTop(top);

                        }
                    }
                }else if(p.selMode=='multi'){
                    uiv = uiv?uiv.split(';'):[];
                    value = value?value.split(';'):[];
                    //check all
                    _.arr.each(uiv,function(o){
                        if(_.arr.indexOf(value,o)==-1)
                            getN(k, getI(o)).tagClass('-mouseover',false).tagClass('-checked',false)
                    });
                    _.arr.each(value,function(o){
                        if(_.arr.indexOf(uiv,o)==-1)
                            getN(k, getI(o)).tagClass('-mouseover',false).tagClass('-checked')
                    });
                }
            });
        },
        adjustSize:function(){
            return this.each(function(profile){
                var items = profile.getSubNode('ITEMS'),pp=profile.properties;
                items.height('auto');
                var h = Math.min(pp.maxHeight, items.offsetHeight());
                pp.height=h;
                items.height(h);
                profile.getRoot().height(h);
            });
        },
        activate:function(){
            return linb.absList.prototype.activate.call(this);
        },
        getShowValue:function(value){
            var profile=this.get(0),
                pro=profile.properties,v,t;
            if(!_.isDefined(value))
                value=pro.$UIvalue;
            if( (v=_.arr.subIndexOf(pro.items,'id',value))!=-1){
                v=pro.items[v].caption;
                v=v.charAt(0)=='$'?linb.getRes(v.slice(1)):v;
            }else
                v='';
            return v;
        },
        _setDirtyMark:function(){
            return this.each(function(profile){
                if(!profile.properties.dirtyMark)return;
                var id=profile.domId,
                    p=profile.properties,
                    flag=p.value !== p.$UIvalue,
                    d=linb.UI.$css_tag_dirty;

                //dirty mark
                if(profile.beforeDirtyMark && false===profile.boxing().beforeDirtyMark(profile,flag)){}
                else{
                    var o = profile.getSubNode('ITEMS');
                    if(flag)
                        o.addClass(d);
                    else
                        o.removeClass(d);
                }
            });
        }
    },
    Static:{
        _DIRTYKEY:'ITEM',
        Templates:{
            tagName : 'div',
            style:'{_style}',
            className:'uibg-base',
            ITEMS:{
               $order:10,
               tagName:'div',
               className:'uiborder-inset',
               text:"{items}"
            },
            $submap:{
                items:{
                    ITEM:{
                        className:'{itemClass} {disabled}',
                        style:'{itemStyle}',
                        tagName : 'a',
                        href :linb.$href,
                        tabindex:'{_tabindex}',
                        ICON:{
                            $order:10,
                            className:'ui-icon {imageClass}',
                            style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                        },
                        CAPTION:{
                            tagName : 'text',
                            text : '{caption}&nbsp;',
                            $order:20
                        }
                    }
                }
            }
        },
        Appearances:{
            KEY:{
                'font-size':'12px'
            },
            ITEMS:{
                position:'relative',
                overflow:'auto',
                'overflow-x': (linb.browser.ie || linb.browser.gek)?'hidden':''
            },
            ITEM:{
                display:'block',
                zoom:linb.browser.ie?1:null,
                'font-family': '"Verdana", "Helvetica", "sans-serif"',
                border:0,
                cursor:'pointer',
                'font-size':'12px',
                padding:'4px 2px',
                position:'relative'
            },
            'ITEM-mouseover, ITEM-mousedown, ITEM-checked':{
                background: linb.UI.$bg('item.gif', 'repeat-x')
            },
            'ITEM-mouseover':{
                $order:1,
                'background-color':'#FAD200',
                'background-position': 'left -51px'
            },
            'ITEM-mousedown':{
                $order:2,
                'background-color':'#F5D22D',
                'background-position': 'left -101px'
            },
            'ITEM-checked':{
                $order:2,
                'background-color':'#AAD2FA',
                'background-position': 'left top'
            }
        },
        Behaviors:{
            HoverEffected:{ITEM:'ITEM'},
            ClickEffected:{ITEM:'ITEM'},
            DragableKeys:["ITEM"],
            DropableKeys:["ITEM","ITEMS"],
            onSize:linb.UI.$onSize,
            ITEM:{
                onDblclick:function(profile, e, src){
                    var properties = profile.properties,
                        item = profile.getItemByDom(src);
                    profile.boxing().onDblclick(profile, item, src);
                },
                onClick:function(profile, e, src){
                    var properties = profile.properties,
                        item = profile.getItemByDom(src),
                        itemId =profile.getSubId(src),
                        box = profile.boxing(),
                        ks=linb.Event.getKey(e),
                        rt,rt2;

                    if(properties.disabled|| item.disabled)return false;

                    linb.use(src).focus();
                    
                    switch(properties.selMode){
                    case 'none':
                        rt=box.onItemSelected(profile, item, src);
                        break;
                    case 'multi':
                        var value = box.getUIValue(),
                            arr = value?value.split(';'):[];

                        if(arr.length&&(ks[1]||ks[2]||properties.noCtrlKey||properties.$checkbox)){
                            //for select
                            rt2=false;
                            if(ks[2]){
                                var items=properties.items,
                                    i1=_.arr.subIndexOf(items,'id',profile.$firstV.id),
                                    i2=_.arr.subIndexOf(items,'id',item.id),
                                    i;
                                arr.length=0;
                                for(i=Math.min(i1,i2);i<=Math.max(i1,i2);i++)
                                    arr.push(items[i].id);
                            }else{
                                if(_.arr.indexOf(arr,item.id)!=-1)
                                    _.arr.removeValue(arr,item.id);
                                else
                                    arr.push(item.id);
                            }

                            arr.sort();
                            value = arr.join(';');

                            //update string value only for setCtrlValue
                            if(box.getUIValue() == value)
                                rt=false;
                            else{
                                box.setUIValue(value);
                                if(box.getUIValue() == value)
                                    rt=box.onItemSelected(profile, item, src)||rt2;
                            }
                            break;
                        }
                    case 'single':
                        if(box.getUIValue() == item.id)
                            rt=false;
                        else{
                            profile.$firstV=item;
                            box.setUIValue(item.id);
                            if(box.getUIValue() == item.id)
                                rt=box.onItemSelected(profile, item, src);
                        }
                        break;
                    }
                    return rt;
                },
                onKeydown:function(profile, e, src){
                    var keys=linb.Event.getKey(e), key = keys[0], shift=keys[2],
                    cur = linb(src),
                    first = profile.getRoot().nextFocus(true, true, false),
                    last = profile.getRoot().nextFocus(false, true, false);

                    switch(linb.Event.getKey(e)[0]){
                        case 'tab':
                            if(shift){
                                if(cur.get(0)!=first.get(0)){
                                    first.focus();
                                    return false;
                                }
                            }else{
                                if(cur.get(0)!=last.get(0)){
                                    last.focus();
                                    return false;
                                }
                            }
                            break;
                        case 'left':
                        case 'up':
                            var next = cur.nextFocus(false, true, false);
                            if(cur.get(0)==first.get(0))
                                last.focus();
                            else
                                cur.nextFocus(false);
                            return false;
                            break;
                        case 'right':
                        case 'down':
                            var next = cur.nextFocus(true, false, false);
                            if(cur.get(0)==last.get(0))
                                first.focus();
                            else
                                cur.nextFocus();
                            return false;
                            break;
                        case 'enter':
                            cur.onClick();
                            return false;
                            break;
                    }
                }
            }
        },
        DataModel:({
            selMode:{
                ini:'single',
                listbox:['single','none','multi']
            },
            noCtrlKey:true,
            width:120,
            height:150,
            maxHeight:300
        }),
        EventHandlers:{
            onDblclick:function(profile, item, src){},
            onItemSelected:function(profile, item, src){}
        },
        _ensureValue:function(profile,value){
            if(profile.properties.selMode=='multi'){
                var arr = (value||"").split(';');
                arr.sort();
                return arr.join(';');
            }else
                return value;
        },
        _onStartDrag:function(profile, e, src, pos){
            var pos=linb.Event.getPos(e);
            linb.use(src).startDrag(e, {
                dragType:'icon',
                shadowFrom:src,
                targetLeft:pos.left+12,
                targetTop:pos.top+12,
                dragCursor:'pointer',
                dragDefer:1,
                dragKey: profile.box.getDragKey(profile, src),
                dragData: profile.box.getDragData(profile, e, src)
            });
            return false;
        },
        _onDropTest:function(profile, e, src, key, data, item){
            var fid=data&&data.domId, tid=linb.use(src).id();
            if(fid){
                if(fid==tid)return false;
                if(_.get(linb.use(src).get(0),['previousSibling','id'])==fid)return false;
            }
        },
        _onDrop:function(profile, e, src, key, data, item){
            linb.DragDrop.setDragIcon('none');

            var k=profile.getKey(linb.use(src).id()),
                po=data.profile,
                ps=data.domId,
                oitem,
                t=linb.absObj.$specialChars;
            //remove
            oitem=_.clone(po.getItemByDom(ps),function(o,i){return !t[(i+'').charAt(0)]});
            po.boxing().removeItems([oitem.id]);

            if(k==profile.keys.ITEM)
                profile.boxing().insertItems([oitem], item.id, true);
            else
                profile.boxing().insertItems([oitem]);

            return false;
        },
        _onresize:function(profile,width,height){
            if(height)
                profile.getSubNode('ITEMS').height(height=='auto'?height:(height-2));
        }
    }
});
Class("linb.UI.Gallery", "linb.UI.List",{
    Instance:{
        getStatus:function(id){
            var item=this.get(0).getItemByItemId(id);
            return (item && item._status)||'ini';
        }
    },
    Initialize:function(){
        //modify default template fro shell
        var t = this.getTemplate();
        t.$submap={
            items:{
                ITEM:{
                    tagName : 'a',
                    href :linb.$href,
                    tabindex:'{_tabindex}',
                    className:'{itemClass} {disabled}',
                    style:'padding:{itemPadding}px;margin:{itemMargin}px;{itemStyle}',
                    ITEMFRAME:{
                        style:'width:{itemWidth}px;height:{itemHeight}px;',
                        CAPTION:{
                            tagName : 'div',
                            text: '{caption}',
                            $order:0
                        },
                        CONTENT:{
                                tagName : 'div',
                                $order:1,
                                //for firefox2 image in -moz-inline-box cant change height bug
                                IBWRAP:{
                                    tagName : 'div',
                                    IMAGE:{
                                        tagName : 'img',
                                        src:'{image}',
                                        width:'{imgWidth}',
                                        height:'{imgHeight}',
                                        style:'{imgStyle}'
                                    }
                                }
                        },
                        COMMENT:{
                            tagName : 'div',
                            text: '{comment}',
                            $order:2
                        }
                    }
                }
            }
        };
        this.setTemplate(t);
    },
    Static:{
        Appearances:{
            KEY:{
                overflow:'auto',
                'overflow-x': (linb.browser.ie || linb.browser.gek)?'hidden':''
            },
            ITEMS:{
                position:'relative',
                overflow:'visible',
                zoom:linb.browser.ie6?1:null
            },
            ITEM:{
                display:linb.$inlineBlock,
                zoom:linb.browser.ie6?1:null,
                position:'relative',
                cursor:'pointer',
                'vertical-align':'top',
                /*opera must be 0 not 'none'*/
                border:'solid 1px #C2E4FC',
                margin:0
            },
            ITEMFRAME:{
                display:linb.browser.ie?'inline-block':'block',
                position:'relative',
                overflow:'hidden',
                border:0,
                padding:0,
                margin:0,
                width:'100%',
                height:'100%',
                '-moz-box-flex':'1',
                '-moz-user-select':'none'
            },
            IBWRAP:{
                'font-size':0,
                'line-height':0
            },
            'ITEM-mouseover':{
                $order:1,
                padding:0,
                border:'solid 1px #a0c8f0',
                'background-color':'#e1f0ff'
            },
            'ITEM-mousedown':{
                $order:2,
                padding:0,
                border:'solid 1px #dcdcdc',
                'background-color':'#bbcef1'
             },
            'ITEM-checked':{
                $order:2,
                padding:0,
                border:'solid 1px #bbcef1',
                'background-color':'#bbcef1'
            },
            IMAGE:{
                display:linb.$inlineBlock,
                zoom:linb.browser.ie6?1:null,
            	'vertical-align': 'middle'
            },

            'CONTENT, CAPTION':{
            	'text-align': 'center',
                overflow:'hidden',
                'white-space':'nowrap'
            },
            CAPTION:{
                'font-weight':'bold'
            },
            COMMENT:{
                display:'block',
                'font-size':'12px',
                margin:'0 2px 0 2px',
                'text-align':'center'
            }
        },
        Behaviors:{
            IMAGE:{
                onLoad:function(profile,e,src){
                    var item=profile.getItemByDom(src);
                    item._status='loaded';
                },
                onError:function(profile,e,src){
                    var item=profile.getItemByDom(src);
                    item._status='error';
                }
            }
        },
        DataModel:({
            itemMargin:{
                ini:6,
                action:function(v){
                    if(typeof v!='object')
                        this.getSubNode('ITEM',true).css('margin', (''+parseFloat(v))==(''+v)?v+'px':v);
                    else
                        this.getSubNode('ITEM',true).css(v);
                }
            },
            itemPadding:{
                ini:2,
                action:function(v){
                    if(typeof v!='object')
                        this.getSubNode('ITEM',true).css('padding',(''+parseFloat(v))==(''+v)?v+'px':v);
                    else
                        this.getSubNode('ITEM',true).css(v);
                }
            },
            itemWidth:{
                ini:32,
                action:function(v){
                    this.getSubNode('ITEMFRAME',true).width(v);
                }
            },
            itemHeight:{
                ini:32,
                action:function(v){
                    this.getSubNode('ITEMFRAME',true).height(v);
                }
            },
            imgWidth:{
                ini:16,
                action:function(v){
                    this.getSubNode('IMAGE',true).width(v);
                }
            },
            imgHeight:{
                ini:16,
                action:function(v){
                    this.getSubNode('IMAGE',true).height(v);
                }
            },
            width:200,
            height:200
        }),
        _prepareItem:function(profile, item){
            var p = profile.properties;

            _.arr.each(_.toArr('itemWidth,itemHeight,imgWidth,imgHeight,itemPadding,itemMargin'),function(i){
                item[i] = item[i] || p[i];
            });
            item.href = item.href||linb.$href;
            item.capition = item.capition || '';
            item.comment = item.comment || '';
            item._tabindex = p.tabindex;
        }
    }
});
Class("linb.UI.IconList", "linb.UI.List",{
    Instance:{
        getStatus:function(id){
            var item=this.get(0).getItemByItemId(id);
            return (item && item._status)||'ini';
        }
    },
    Initialize:function(){
        //modify default template fro shell
        var t = this.getTemplate();
        t.$submap={
            items:{
                ITEM:{
                    tagName : 'a',
                    href :linb.$href,
                    tabindex:'{_tabindex}',
                    className:'{itemClass} {disabled}',
                    style:'padding:{itemPadding}px;margin:{itemMargin}px;{itemStyle}',
                    //for firefox2 image in -moz-inline-box cant change height bug
                    IBWRAP:{
                        tagName:'div',
                        IMAGE:{
                            tagName:'img',
                            src:'{image}',
                            width:'{itemWidth}',
                            height:'{itemHeight}',
                            style:'{imgStyle}'
                        }
                    }
                }
            }
        };
        this.setTemplate(t);
    },
    Static:{
        Appearances:{
            KEY:{
                overflow:'auto',
                'overflow-x': (linb.browser.ie || linb.browser.gek)?'hidden':''
            },
            ITEMS:{
                overflow:'auto',
                'overflow-x': (linb.browser.ie || linb.browser.gek)?'hidden':'',
                position:'relative',
                'line-height':'14px',
                zoom:linb.browser.ie6?1:null
            },
            ITEM:{
                display:linb.$inlineBlock,
                zoom:linb.browser.ie6?1:null,
                position:'relative',
                cursor:'pointer',
                border:'solid 1px #C2E4FC',
                'vertical-align':'top'
            },
            IBWRAP:{
                'font-size':0,
                'line-height':0
            },
             'ITEM-mouseover':{
                $order:1,
                padding:0,
                border:'solid 1px #a0c8f0',
                'background-color':'#e1f0ff'
            },
            'ITEM-mousedown':{
                $order:2,
                padding:0,
                border:'solid 1px #dcdcdc',
                'background-color':'#bbcef1'
             },
            'ITEM-checked':{
                $order:2,
                padding:0,
                border:'solid 1px #bbcef1',
                'background-color':'#bbcef1'
            }
        },
        Behaviors:{
            IMAGE:{
                onLoad:function(profile,e,src){
                    var item=profile.getItemByDom(src);
                    item._status='loaded';
                },
                onError:function(profile,e,src){
                    var item=profile.getItemByDom(src);
                    item._status='error';
                }
            }
        },
        DataModel:({
            itemMargin:{
                ini:6,
                action:function(v){
                    if(typeof v!='object')
                        this.getSubNode('ITEM',true).css('margin',(''+parseFloat(v))==(''+v)?v+'px':v);
                    else
                        this.getSubNode('ITEM',true).css(v);
                }
            },
            itemPadding:{
                ini:2,
                action:function(v){
                    if(typeof v!='object')
                        this.getSubNode('ITEM',true).css('padding',(''+parseFloat(v))==(''+v)?v+'px':v);
                    else
                        this.getSubNode('ITEM',true).css(v);
                }
            },
            itemWidth:{
                ini:16,
                action:function(v){
                    this.getSubNode('IMAGE',true).width(v);
                }
            },
            itemHeight:{
                ini:16,
                action:function(v){
                    this.getSubNode('IMAGE',true).height(v);
                }
            },
            width:200,
            height:200
        }),
        _prepareItem:function(profile, item){
            var p = profile.properties;
            _.arr.each(_.toArr('itemWidth,itemHeight,itemPadding,itemMargin'),function(i){
                item[i] = item[i] || p[i];
            });
            item._tabindex = p.tabindex;
        }
    }
});
Class("linb.UI.Panel", "linb.UI.Div",{
    Instance:{
        activate:function(flag){
            var profile, cls=this.constructor;
            if(profile=linb.UI._cache['$'+cls.activeWndId])
                profile.getSubNode('TBAR').tagClass('-focus',false);
            delete cls.activeWndId;

            if(flag!==false){
                profile=this.get(0);
                profile.getSubNode('TBAR').tagClass('-focus');
                profile.getSubNode('CAPTION').focus();
                cls.activeWndId=profile.$linbid;
            }
        }
    },
    Static:{
        Templates:{
            tagName : 'div',
            style:'{_style}',
            BORDER:{
                tagName:'div',
                TBAR:{
                    tagName:'div',
                    className:'uibar-top',
                    BART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        height:'100%',
                        border:'0',
                        tagName:'table',
                        className:'uibar-t',
                        BARTR:{
                            tagName:'tr',
                            BARTDL:{
                                tagName:'td',
                                className:'uibar-tdl'
                            },
                            BARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'uibar-tdm'
                            },
                            BARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'uibar-tdr'
                            }
                        }
                    },
                    BARCMDL:{
                        tagName: 'div',
                        className:'uibar-cmdl',
                        TOGGLE:{
                            className: 'uicmd-toggle {toggleCls}',
                            style:'{toggleDisplay}',
                            $order:0
                        },
                        ICON:{
                            $order:0,
                            className:'ui-icon {imageClass}',
                            style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                        },
                        CAPTION:{
                            tagName: 'a',
                            href :"{href}",
                            tabindex: '{tabindex}',
                            text : '{caption}',
                            $order:1
                        }
                    },
                    BARCMDR:{
                        tagName: 'div',
                        className:'uibar-cmdr',
                        onselectstart:'return false',
                        unselectable:'on',
                        OPT:{
                            className:'uicmd-opt',
                            style:'{optDisplay}',
                            $order:1
                        },
                        LAND:{
                            className:'uicmd-land',
                            style:'{landDisplay}',
                            $order:1
                        },
                        CLOSE:{
                            className:'uicmd-close ',
                            style:'{closeDisplay}',
                            $order:2
                        }
                    }
                },
                MAIN:{
                    $order:2,
                    tagName:'div',
                    className:'uicon-main',
                    MAINI:{
                        tagName:'div',
                        className:'uicon-maini',
                        PANEL:{
                            tagName:'div',
                            style:'{panelDisplay}',
                            text:'{html}'+linb.UI.$childTag
                        }
                    }
                },
                BBAR:{
                    $order:3,
                    tagName:'div',
                    className:'uibar-bottom-s',
                    BBART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        tagName:'table',
                        className:'uibar-t',
                        BBARTR:{
                            tagName:'tr',
                            BBARTDL:{
                                tagName:'td',
                                className:'uibar-tdl'
                            },
                            BBARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'uibar-tdm'
                            },
                            BBARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'uibar-tdr'
                            }
                        }
                    }
                }                
            }
        },
        Appearances:{
            KEY:{
                overflow:'hidden',
                background:'transparent'
            },
            'KEY BORDER':{
                zoom:linb.browser.ie6?1:null
            },
            PANEL:{
                position:'relative',
                left:0,
                top:0,
                overflow:'hidden',
                zoom:linb.browser.ie6?1:null
            },

            CAPTION:{
                'font-size':'12px',
                display:'inline',
                'vertical-align':'middle'
            }
        },
        Behaviors:{
            DropableKeys:['PANEL'],
            DragableKeys:['TBAR'],
            HoverEffected:{OPT:'OPT', CLOSE:'CLOSE',LAND:'LAND', TOGGLE:'TOGGLE'},
            ClickEffected:{CLOSE:'CLOSE', OPT:'OPT', LAND:'LAND', TOGGLE:'TOGGLE'},
            onSize:linb.UI.$onSize,
            OPT:{
                onClick:function(profile, e, src){
                    profile.boxing().onShowOptions(profile, e, src);
                }
            },
            TOGGLE:{
                onClick:function(profile, e, src){
                    profile.box._toggle(profile, !profile.properties.toggle);
                    return false;
                }
            },
            CAPTION:{
                onClick:function(profile, e, src){
                    if(!profile.onClickBar || false===profile.boxing().onClickBar(profile,src))
                        return !!linb.Event.getKey(e)[2];
                }
            },
            CLOSE:{
                onClick:function(profile, e, src){
                    var properties = profile.properties;
                    if(properties.disabled)return;
                    var instance = profile.boxing();

                    if(false===instance.beforeClose(profile)) return;

                    instance.destroy();

                    //for design mode in firefox
                    return false;
                }
            },
            LAND:{
                onClick:function(profile, e, src){
                    var properties=profile.properties;
                    if(properties.disabled)return;
                    var pos = profile.getRoot().offset(), size=profile.getRoot().cssSize();

                    var pro = _.copy(linb.UI.Dialog.$DataStruct);
                    _.merge(pro, properties, 'with');
                    _.merge(pro,{
                        dock:'none',
                        width:Math.max(size.width,200),
                        height:Math.max(size.height,100),
                        left:pos.left,
                        top:pos.top
                    },'all');
                    var dialog = new linb.UI.Dialog(pro),arr=[];
                    linb('body').append(dialog);

                    _.arr.each(profile.children,function(o){
                        arr.push(o[0]);
                    });
                    dialog.append(linb.UI.pack(arr,false));

                    profile.boxing().destroy();

                    //for design mode in firefox
                    return false;
                }
            }
        },
        DataModel:{
            position:'absolute',
            zIndex:0,
            dock:'fill',
            // setCaption and getCaption
            caption:{
                ini:undefined,
                // ui update function when setCaption
                action: function(value){
                    this.getSubNode('CAPTION').get(0).innerHTML = value;
                }
            },
            image:{
                action: function(value){
                    this.getSubNode('ICON')
                        .css('display',value?'':'none')
                        .css('backgroundImage','url('+(value||'')+')');
                }
            },
            imagePos:{
                action: function(value){
                    this.getSubNode('ICON')
                        .css('backgroundPosition', value);
                }
            },
            href:{
                ini:linb.$href,
                action:function(v){
                    this.getSubNode('CAPTION').attr('href',v);
                }
            },
            html:{
                action:function(v){
                    this.getSubNode('PANEL').html(v);
                }
            },
            toggle:{
                ini:true,
                action:function(v){
                    this.box._toggle(this, v);
                }
            },
            optBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('OPT').css('display',v?'':'none');
                }
            },
            toggleBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('TOGGLE').css('display',v?'':'none');
                }
            },
            closeBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('CLOSE').css('display',v?'':'none');
                }
            },
            landBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('LAND').css('display',v?'':'none');
                }
            }
        },
        EventHandlers:{
            beforeClose:function(profile, src){},
            onIniPanelView:function(profile){},
            onFold:function(profile){},
            onExpend:function(profile){},
            onShowOptions:function(profile, e, src){},
            onClickBar:function(profile, src){}
        },
        LayoutTrigger:function(){
            var self=this, t=self.properties, b=self.box;
            if(t.toggle)
                b._toggle(self,t.toggle);
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile);
            var nodisplay='display:none';

            data.panelDisplay = data.toggle?'':nodisplay;
            data.toggleCls = data.toggle?'':profile.getClass('TOGGLE','-checked');

            data.toggleDisplay = data.toggleBtn?'':nodisplay;
            data.optDisplay = data.optBtn?'':nodisplay;
            data.closeDisplay = data.closeBtn?'':nodisplay;
            data.landDisplay = data.landBtn?'':nodisplay;
            return data;
        },
        _onresize:function(profile,width,height){
            var isize={},
                v1=profile.getSubNode('TBAR'),
                v2=profile.getSubNode('PANEL'),
                v4=profile.getSubNode('BBAR'),
                v5=profile.getSubNode('MAIN'),
                v6=profile.getSubNode('MAINI'),
                h1,h4,t;
            if(height){
                if(height=='auto')
                    isize.height=height;
                else{
                    h1=v1.height(), h4=v4.height();
                    if((t=height-h1-h4)>0)
                        isize.height=t;
                }
            }
            if(width)
                isize.width=width-(parseInt(v6.css('paddingRight'))||0)-(parseInt(v5.css('paddingLeft'))||0);
            v2.cssSize(isize, true);
        },

        _toggle:function(profile, value){
            var p=profile.properties, b=profile.boxing();
            //set toggle mark
            p.toggle = value;

            //event
            if(value &&!profile.$ini)
                if(b.onIniPanelView)
                    if(b.onIniPanelView(profile)!==false)
                        profile.$ini=true;

            if(value){
                if(false===b.onExpend(profile))return;
            }else{
                if(false===b.onFold(profile))return;
            }

            //show/hide/panel
            profile.getSubNode('PANEL').css('display',value?'':'none');
            //chang toggle button
            if(p.toggleBtn)
                profile.getSubNode('TOGGLE').tagClass('-checked', !value);
        }
    }
});
Class("linb.UI.PageBar",["linb.UI","linb.absValue"] ,{
    Instance:{
        _setCtrlValue:function(value){
            return this.each(function(profile){
                if(!profile.renderId)return;
                var t,
                    prop = profile.properties,
                    arr = profile.box._v2a(value),
                    min=arr[0],
                    cur=arr[1],
                    max=arr[2],
                    keys = profile.keys,
                    fun = function(p,k){return p.getSubNode(k)},

                    first = fun(profile, 'FIRST'),
                    prev = fun(profile, 'PREV'),
                    prehide = fun(profile, 'PREM'),
                    current = fun(profile, 'CUR'),
                    next = fun(profile, 'NEXT'),
                    nexthide = fun(profile, 'NEXTM'),
                    last = fun(profile, 'LAST'),

                    change = function(n,i,j){if(i)n.first(3).attr('href',prop.uriTpl.replace('*',i));if(j)n.first(3).text(prop.textTpl.replace('*',j))},
                    display = function(n,f){n.css('display',f?'':'none')}
                    ;
                //change href and text
                change(first, min, min);
                change(prehide, '','..' + _.str.repeat('.',String(cur-1-min).length) );
                change(prev, cur-1);
                change(current, cur, cur);
                change(next, cur+1);
                change(nexthide, '','..' + _.str.repeat('.',String(max-cur-1).length) );
                change(last, max, max);

                //show or hide
                if((t=cur-min)<=0){
                    display(first,0);display(prehide,0);display(prev,0);
                }else if(t==1){
                    display(first,1);display(prehide,0);display(prev,0);
                }else if(t==2){
                    display(first,1);display(prehide,0);display(prev,1);
                }else{
                    display(first,1);display(prehide,1);display(prev,1);
                }
                if((t=max-cur)<=0){
                    display(last,0);display(nexthide,0);display(next,0);
                }else if(t==1){
                    display(last,1);display(nexthide,0);display(next,0);
                }else if(t==2){
                    display(last,1);display(nexthide,0);display(next,1);
                }else{
                    display(last,1);display(nexthide,1);display(next,1);
                }
            });
        },
        setPage:function(value){
            return this.each(function(o){
                var v=o.properties.value,
                    a=v.split(':');
                a[1]=parseInt(value)||a[0];
                o.boxing().setValue(a.join(':'));
            });
        }
    },
    Static:{
        Templates:{
            style:'{_style}',
            POOL:{
                style:'position:absolute;display:none;',
                POP:{
                    tagName:'div',
                    className:'uibg-base'
                }
            },
            LABEL:{
                text:'{caption}'
            },
            FIRST:{
                $order:1,
                className:'ui-btn',
                FIRSTI:{
                    className:'ui-btni',
                    FIRSTC:{
                        className:'ui-btnc',
                        FIRSTA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}'
                        }
                    }
                }
            },
            PREM:{
                $order:2,
                className:'ui-btn',
                PREMI:{
                    className:'ui-btni',
                    PREMC:{
                        className:'ui-btnc',
                        PREMA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}'
                        }
                    }
                }
            },
            PREV:{
                $order:3,
                className:'ui-btn',
                PREVI:{
                    className:'ui-btni',
                    PREVC:{
                        className:'ui-btnc',
                        PREVA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}',
                            text:'{prevMark}'
                        }
                    }
                }
            },
            CUR:{
                $order:4,
                className:'ui-btn ui-btn-focus',
                CURI:{
                    className:'ui-btni',
                    CURC:{
                        className:'ui-btnc',
                        CURA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}'
                        }
                    }
                }
            },
            NEXT:{
                $order:5,
                className:'ui-btn',
                NEXTI:{
                    className:'ui-btni',
                    NEXTC:{
                        className:'ui-btnc',
                        NEXTA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}',
                            text:'{nextMark}'
                        }
                    }
                }
            },
            NEXTM:{
                $order:6,
                className:'ui-btn',
                NEXTMI:{
                    className:'ui-btni',
                    NEXTMC:{
                        className:'ui-btnc',
                        NEXTMA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}'
                        }
                    }
                }
            },
            LAST:{
                $order:6,
                className:'ui-btn',
                LASTI:{
                    className:'ui-btni',
                    LASTC:{
                        className:'ui-btnc',
                        LASTA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}'
                        }
                    }
                }
            }
        },
        Appearances:{
            LABEL:{
                'font-size':'12px',
                padding:'3px 6px 0 6px',
                'vertical-align':'top',                
                'white-space':'nowrap'
            },
            KEY:{
                display:'inline',
                overflow:'visible'
            },
            'KEY a:focus, POP a:focus':{
                '-moz-outline-offset': ''
            },
            'KEY .ui-btn, POP .ui-btn':{
                'margin-right':'3px'
            },
            'KEY .ui-btn a, POP .ui-btn a':{
                padding:'0 3px 0 3px'
            },
            'PREV,CUR,NEXT':{
                'font-weight' : 'bold'
            },
            POP:{
                border:'dotted 1px gray',
                background:'#fff',
                position:'absolute',
                padding:'3px',
                'line-height':'26px'
            }
        },
        Behaviors:{
            HoverEffected:{FIRST:'FIRST',PREM:'PREM',PREV:'PREV',NEXT:'NEXT',NEXTM:'NEXTM',LAST:'LAST',POPI:'POPI',CUR:'CUR'},
            ClickEffected:{FIRST:'FIRST',PREM:'PREM',PREV:'PREV',NEXT:'NEXT',NEXTM:'NEXTM',LAST:'LAST',POPI:'POPI',CUR:'CUR'},
            POP:{
                onClick:function(profile, e, src){
                    var o=linb(src),
                        r = linb.Event.getSrc(e)
                        ;
                    o.setBlurTrigger(profile.key+":"+profile.$linbid, null);
                    profile.getSubNode('POOL').append(o);
                    if(r.tagName.toLowerCase()=='a' || ((r=r.firstChild)&&(r.tagName.toLowerCase()=='a')) || ((r=r.firstChild)&&(r.tagName.toLowerCase()=='a')) || ((r=r.firstChild)&&(r.tagName.toLowerCase()=='a')))
                        return profile.box._click(profile,r.parentNode.parentNode.parentNode);
                }
            },
            FIRST:{
                onClick:function(profile, e, src){
                    return profile.box._click(profile,src);
                }
            },
            PREM:{
                onClick:function(profile, e){return !!linb.Event.getKey(e)[2]},
                onMousedown:function(profile, e, src){
                    profile.box._show(profile,e,src,0);
                    return false;
                }
            },
            PREV:{
                onClick:function(profile, e, src){
                    return profile.box._click(profile,src);
                }
            },
            CUR:{
                onClick:function(profile, e, src){
                    return profile.box._click(profile,src);
                }
            },
            NEXT:{
                onClick:function(profile, e, src){
                    return profile.box._click(profile,src);
                }
            },
            NEXTM:{
                onClick:function(profile, e){return !!linb.Event.getKey(e)[2]},
                onMousedown:function(profile, e, src){
                    profile.box._show(profile,e,src,1);
                    return false;
                }
            },
            LAST:{
                onClick:function(profile, e, src){
                    return profile.box._click(profile,src);
                }
            }
        },
        DataModel:{
            dataField:null,
            dataBinder:null,

            caption:' Page: ',
            value:"1:1:1",
            uriTpl:"#*",
            textTpl:"*",
            prevMark:'&lt;',
            nextMark:'&gt;',
            _moreStep:100
        },
        EventHandlers:{
            onClick:function(profile, page){}
        },
        _ensureValue:function(profile,value){
            var a = value.split(':'),
                b=[],
                fun=function(a){return parseInt(a)||1};
            b[0]=fun(a[0]);
            b[1]=fun(a[1]);
            b[2]=fun(a[2]);

            b[0] = Math.max(b[0],1);
            b[0] = Math.min(b[0],b[1]);
            b[2] = Math.max(b[1],b[2]);

            return b.join(':');
        },
        _v2a:function(v){
            v = typeof v == 'string'? v.split(':') : v;
            v[0]=parseInt(v[0]);v[1]=parseInt(v[1]);v[2]=parseInt(v[2]);
            return v;
        },
        _click:function(profile, src){
            var b=profile.boxing(),
                v=b.getValue(),
                a=v.split(':');

            var r = b.onClick(profile, parseInt(linb(src).first(3).attr('href').split('#')[1])||a[0]);
            return typeof r=="boolean"?r:false;
        },
        _show:function(profile, e, src, flag){
            var prop = profile.properties,
                arr = profile.box._v2a(prop.value),
                min=arr[0],
                cur=arr[1],
                max=arr[2],

                keys = profile.keys,
                fun = function(p,k){return p.getSubNode(k)},
                pool = fun(profile, 'POOL'),
                pop = fun(profile, 'POP'),
                ceil = function(n){return Math.ceil((n+1)/10)*10},
                a=[],
                t,m,n,i,l
                ;

            if(flag){
                if((t=max-1-cur)<=0)return;
                n=cur + 1;
                l=max;
            }else{
                if((t=cur-1-min)<=0)return;
                n=1;
                l=cur-1;
            }
            m=Math.ceil(t/prop._moreStep);
            if(m>10){
                n=ceil(n);
                l=ceil(l)-1;
                m=ceil(m);
            }else
                n=n+m;
            //
            var _id=profile.keys.POPI+':'+profile.serialId+':';
            while(n<l){
                //margin-top for ie6
                a.push('<span style="margin-top:3px;" id="'+_id+n+'" class="ui-btn"><span class="ui-btni"><span class="ui-btnc"><a href="'+prop.uriTpl.replace('*',n)+'">'+prop.textTpl.replace('*',n)+'</a></span></span></span>')
                n=n+m;
            }
            pop.width('auto');
            pop.html(a.join(' '));
            linb('body').append(pop);
            if(pop.width()>300)pop.width(300);
            pop.popToTop(src);
            pop.setBlurTrigger(profile.key+":"+profile.$linbid, function(){
                pool.append(pop);
            });
        }
    },
    Initialize:function(){
        this.addTemplateKeys(['POPI']);
    }
});
Class("linb.UI.Tabs", ["linb.UI", "linb.absList","linb.absValue"],{
    Instance:{
        _setCtrlValue:function(value){
            this.each(function(profile){
                var id=profile.domId,
                    box = profile.boxing(),
                    uiv = box.getUIValue(),
                    properties = profile.properties,
                    itemId = profile.getSubIdByItemId(uiv),
                    item,
                    temp,t
                    ;
                    if(uiv && profile.getSubIdByItemId(uiv)){
                        profile.getSubNodes(['ITEM','BOX'],itemId).tagClass('-checked',false);

                        if(!properties.noPanel)
                            // hide pane
                            //box.getPanel(uiv).hide();
                            box.getPanel(uiv).css('display','none');
                    }
                    itemId = profile.getSubIdByItemId(value);
                    item=profile.getItemByItemId(value);
                    if(itemId){
                        profile.getSubNodes(['ITEM','BOX'],itemId).tagClass('-checked');
                        if(!properties.noPanel){
                            // show pane
                            //box.getPanel(value).css('position','relative').show('auto','auto');
                            box.getPanel(value).css('display','block');

                            t=profile.getRootNode().style;
                            //reset width and height
                            linb.UI.$tryResize(profile, t.width, t.height, true, value);
                            t=null;

                            //dynamic render
                            var arr=profile.children,a=[];
                            _.arr.each(arr,function(o){
                                if(o[1]==value && !o[0]['parent:'+profile.$linbid]){
                                    a.push(o[0]);
                                    o[0]['parent:'+profile.$linbid]=1;
                                }
                            });
                            if(a.length)
                                box.append(linb.UI.pack(a),value);

                            if(!item._$ini)
                                if(box.onIniPanelView)
                                    if(box.onIniPanelView(profile,item)!==false)
                                        item._$ini=true;
                        }
                    }
            });
        },
        append:function(target,subId){
            var p=this.get(0).properties;
            if(subId=subId||p.$UIvalue||p.value)
                arguments.callee.upper.call(this, target, subId);
            return this;
        },
        getCurPanel:function(){
            var profile = this.get(0);
            return this.getPanel(profile.properties.$UIvalue);
        },
        // get pane in page views
        getPanel:function(subId){
            var profile = this.get(0);
            return profile.getSubNodeByItemId('PANEL', subId);
        },
        ////
        addPanel:function(para, children, item){
            var i={}, 
                id = item&&item.id,
                items = this.getItems(),
                id2=para.id||para.tag;
            if(items.length){
                if(-1!=_.arr.subIndexOf(items,'id',id2))
                    return false;

                if(!id)    
                    id = items[items.length-1].id;
            }

            _.merge(i, {
                caption:para.caption,
                image:para.image,
                closeBtn:para.closeBtn || false,
                landBtn:para.landBtn || false,
                optBtn:para.optBtn || false,
                imagePos:para.imagePos,
                dragKey:para.dragKey,
                dropKeys:para.dropKeys,
                id : para.id || para.tag || _.id()
            });

            this.insertItems([i], id);
            var arr=[];
            _.arr.each(children,function(o){
                arr.push(o[0]);
            });
            this.append(linb.UI.pack(arr,false), i.id);

            return this;
        },
        removePanel:function(domId){
            var self=this,
                item = self.getItemByDom(domId);
            return self.removeItems([item.id]);
        },
        getPanelPara:function(domId){
            var profile=this.get(0),
                pp=profile.properties,
                item = profile.getItemByDom(domId),
                para = _.clone(item);
            if(!para.dragKey)para.dragKey=pp.dragKey;
            if(!para.dropKeys)para.dropKeys=pp.dropKeys;
            return para;
        },
        getPanelChildren:function(domId){
            var profile=this.get(0),
                id = profile.getItemIdByDom(domId),
                arr=[];
            if(id)
                _.arr.each(profile.children,function(o){
                    if(o[1]==id)arr.push(o);
                });
            return arr;
        },

        ////
        fireItemClickEvent:function(subId){
            this.getSubNodeByItemId('ITEM', subId).onMousedown();
            return this;
        },
        /* insert some views to pageView widgets
            arr: hash(view properties) or array of hash
            before: views will insert before it, string
        */
        _afterInsertItems:function(profile, data){
            if(!profile.renderId)return;
            var box=profile.box,obj,v,pp=profile.properties;
            if(obj=profile.getSubNode(profile.keys.BOX||profile.keys.KEY)){
                obj.append(profile._buildItems('panels', data));
                if(!pp.noPanel){
                    if(!(v=this.getUIValue()))
                        this.fireItemClickEvent((v=pp.items[0]) && (v=v.id));
    
                    var t=profile.getRootNode().style;
                    linb.UI.$tryResize(profile, t.width, t.height, true,v);
                    t=null;
                }
            }
        },
        /*  remove some views from pageView
            arr: array for id
        */
        removeItems:function(arr){
            var self=this,
                obj,serialId;
            if(!_.isArr(arr))arr=[arr];

            self.each(function(profile){
                if(!profile.properties.noPanel)
                    _.arr.each(arr,function(o){
                        // get ui serial id
                        serialId=profile.getSubIdByItemId(o);
                        if(serialId && !(obj = profile.getSubNode('PANEL', serialId) ).isEmpty() ){
                            // remove ui
                            obj.remove();
                        }
                    });
            });
            arguments.callee.upper.apply(self,arguments);

            self.each(function(profile){                
                if(!profile.boxing().getUIValue()){
                    var i;
                    profile.boxing().fireItemClickEvent((i=profile.properties.items[0]) && i.id);
                }
                if(!profile.properties.noPanel){
                    var t=profile.getRootNode().style;
                    linb.UI.$tryResize(profile, t.width, t.height, true, profile.boxing().getUIValue());
                    t=null;
                }
            });

            return self;
        },
        clearItems:function(){
            var self=this;
            self.each(function(profile){
                if(!profile.properties.noPanel)
                    profile.getSubNode('PANEL',true).remove();
            });
            self.setValue(null,true);
            arguments.callee.upper.apply(self,arguments);
            return self;
        },
        markItemCaption:function(subId, mark, force){
            var profile = this.get(0);
            subId=profile.getItemByItemId(subId);

            if((subId._dirty !=mark) || force){
                var id = subId.id,
                    caption = profile.getItemByItemId(id).caption;
                profile.getSubNodeByItemId('CAPTION', id).html(
                    profile.getItemByItemId(id).caption=mark?('*'+caption):caption.replace(/^\*/,'')
                ).css('fontStyle',mark?'italic':'normal');
                subId._dirty=mark;
            }
            return this;
        }
    },
    Static:{
        _dynamicRender:true,
        Templates:{
            tagName : 'div',
            style:'{_style};',
            LIST:{
                $order:0,
                tagName : 'div',
                ITEMS:{
                    tagName : 'div',
                    text:"{items}",
                    style:'{HAlign}'
                }
            },
            PNAELS:{
                $order:1,
                tagName:'text',
                text:'{panels}'
            },
            $submap:{
                items:{
                    ITEM:{
                        className:'{itemClass} {disabled}',
                        style:'{itemStyle}',
                        ITEMI:{
                            ITEMC:{
                                HANDLE:{
                                    tagName: 'a',
                                    href :"{href}",
                                    tabindex: '{_tabindex}',
                                    IBWRAP:{
                                        tagName:'div',
                                        style:"white-space:nowrap;",
                                        RULER:{},
                                        ICON:{
                                            $order:0,
                                            className:'ui-icon {imageClass}',
                                            style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                                        },
                                        CAPTION:{
                                            text: '{caption}',
                                            $order:1
                                        },
                                        CMDS:{
                                            $order:2,
                                            OPT:{
                                                $order:1,
                                                className:'uicmd-opt',
                                                style:'{_opt}'
                                            },
                                            LAND:{
                                                className:'uicmd-land',
                                                style:'{landDisplay}',
                                                $order:1
                                            },
                                            CLOSE:{
                                                className:'uicmd-close ',
                                                style:'{closeDisplay}',
                                                $order:2
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                panels:{
                    PANEL:{
                        tagName : 'div',
                        className:'uibg-base',
                        text:linb.UI.$childTag
                    }
                }
            }
        },
        Appearances:{
            KEY:{
                position:'absolute',
                overflow:'hidden'
            },
            LIST:{
                position:'relative'
            },
            ITEMS:{
                padding:'0 4px 2px 0',
                position:'relative',
                background: linb.UI.$bg('line.gif', 'repeat-x center bottom')
            },
            ITEM:{
                $order:0,
                'font-family': '"Verdana", "Helvetica", "sans-serif"',
                cursor:'pointer',
                'padding-right':'6px',
                'vertical-align':'top',
                background: linb.UI.$bg('button.gif', 'no-repeat right -540px', true)
            },
            'ITEM-mouseover':{
                $order:1,
                'background-position' : 'right -690px'
            },
            'ITEM-mousedown, ITEM-checked':{
                $order:2,
                'background-position' : 'right -840px',
                'border-bottom':'solid 1px #FAD600;'
            },
            ITEMI:{
                $order:0,
                'padding-left':'6px',
                //keep this same with ITEM
                'vertical-align':'top',
                background: linb.UI.$bg('button.gif', 'no-repeat left -640px',true)
            },
            'ITEM-mouseover ITEMI':{
                $order:1,
                'background-position' : 'left -790px'
            },
            'ITEM-mousedown ITEMI, ITEM-checked ITEMI':{
                $order:2,
                'background-position' : 'left -940px'
            },
            ITEMC:{
                $order:0,
                padding:'5px 0 3px 0',
                //keep this same with ITEM
                'vertical-align':'top',
                'text-align': 'center',
                background: linb.UI.$bg('button.gif', 'repeat-x left -590px',true)
            },
            'ITEM-mouseover ITEMC':{
                $order:1,
                'background-position' : 'left -740px'
            },
            'ITEM-mousedown ITEMC, ITEM-checked ITEMC':{
                $order:2,
                'background-position' : 'left -890px'
            },
            HANDLE:{
                display:linb.$inlineBlock,
                zoom:linb.browser.ie6?1:null,
                cursor:'pointer',
                'vertical-align':'middle',
                'font-size':'12px'
            },
            RULER:{
                height:'18px',
                width:'1px',
                'vertical-align':'middle'
            },
            PANEL:{
                position:'relative',
                //visibility:'hidden',
                //top:'-10000px',
                //left:'-10000px',
                display:'none',
                width:'100%',
                overflow:'auto'
            },
            CAPTION:{
                'vertical-align':'middle'
            },
            CMDS:{
                'vertical-align':'middle',
                'margin-left':'4px'
            }
        },
        Behaviors:{
            DropableKeys:['PANEL','KEY', 'ITEM'],
            DragableKeys:['ITEM'],
            HoverEffected:{ITEM:'ITEM',OPT:'OPT',CLOSE:'CLOSE',LAND:'LAND'},
            ClickEffected:{ITEM:'ITEM',OPT:'OPT',CLOSE:'CLOSE',LAND:'LAND'},
            onSize:linb.UI.$onSize,
            OPT:{
                onMousedown:function(){
                    return false;
                },
                onClick:function(profile, e, src){
                    profile.boxing().onShowOptions(profile, profile.getItemByDom(src), e, src);
                    return false;
                }
            },
            CAPTION:{
                onMousedown:function(profile, e, src){
                    if(linb.Event.getBtn(e)!='left')return;
                    var properties = profile.properties,
                        item = profile.getItemByDom(src),
                        box = profile.boxing();

                    if(properties.disabled || item.disabled)return false;
                    if(box.getUIValue() == item.id){
                         if(profile.onCaptionActive)
                            profile.boxing().onCaptionActive(profile, profile.getItemByDom(src), src);
                    }
                }
            },
            ITEM:{
                onClick:function(profile, e, src){
                    return false;
                },
                onMousedown:function(profile, e, src){
                    if(linb.Event.getBtn(e)!='left')return false;
                    if(profile.getKey(linb.Event.getSrc(e).parentNode.id)==profile.keys.CMDS)return false;

                    var properties = profile.properties,
                        itemId = profile.getSubId(src),
                        item = profile.getItemByDom(src),
                        box = profile.boxing();

                    if(properties.disabled || item.disabled)return false;
                    if(box.getUIValue() == item.id)return;

                    //for some input onblur event
                    profile.getSubNode('HANDLE', itemId).focus();

                    box.setUIValue(item.id);

                    //if success
                    if(box.getUIValue() == item.id){
                        box.onItemSelected(profile, item, src);
                        return false;
                    }
                }
            },
            HANDLE:{
                onClick:function(profile, e, src){
                    return !!linb.Event.getKey(e)[2];
                },
                onKeydown:function(profile, e, src){
                    var keys=linb.Event.getKey(e), key = keys[0], shift=keys[2];
                    if(key==' '||key=='enter'){
                        profile.getSubNode('ITEM',profile.getSubId(src)).onMousedown();
                        return false;
                    }

                    var cur = linb(src),
                    target = profile.getSubNode('ITEMS'),
                    first = target.nextFocus(true, true, false),
                    last = target.nextFocus(false, true, false);

                    switch(key){
                        case 'tab':
                            if(shift){
                                if(cur.get(0)!=first.get(0)){
                                    first.focus();
                                    return false;
                                }
                            }else{
                                if(cur.get(0)!=last.get(0)){
                                    last.focus();
                                    return false;
                                }
                            }
                            break;
                        case 'left':
                        case 'up':
                            var next = cur.nextFocus(false, true, false);
                            if(cur.get(0)==first.get(0))
                                last.focus();
                            else
                                cur.nextFocus(false);
                            return false;
                            break;
                        case 'right':
                        case 'down':
                            var next = cur.nextFocus(true, false, false);
                            if(cur.get(0)==last.get(0))
                                first.focus();
                            else
                                cur.nextFocus();
                            return false;
                            break;
                    }
                }
            },
            CLOSE:{
                onMousedown:function(){
                    return false;
                },
                onClick:function(profile, e, src){
                    var properties = profile.properties,
                        item = profile.getItemByDom(src),bak;

                    if(properties.disabled || item.disabled)return;
                    var instance = profile.boxing();

                    if(false===instance.beforePageClose(profile, item, src)) return;

                    bak=_.copy(item);

                    instance.removeItems(item.id);

                    instance.afterPageClose(profile, bak);

                    var t=profile.getRootNode().style;
                    linb.UI.$tryResize(profile, t.width, t.height,true);
                    t=null;
                    //for design mode in firefox
                    return false;
                }
            },
            LAND:{
                onMousedown:function(){
                    return false;
                },
                onClick:function(profile, e, src){
                    var properties = profile.properties,
                        item = profile.getItemByDom(src),
                        id=item.id;

                    if(properties.disabled || item.disabled)return;

                    var panel = profile.boxing().getPanel(id),
                        pos = profile.getRoot().offset(),
                        size=profile.getRoot().cssSize(),
                        pro = _.copy(linb.UI.Dialog.$DataStruct);
                    _.merge(pro, item, 'with');
                    _.merge(pro,{
                        dragKey: item.dragkey || properties.dragKey ,
                        dock:'none',
                        tag:item.tag||item.id,
                        width:Math.max(size.width,200),
                        height:Math.max(size.height,100),
                        left:pos.left,
                        top:pos.top
                    },'all');
                    var dialog = new linb.UI.Dialog(pro);
                    linb('body').append(dialog);

                    var arr=[];
                    _.arr.each(profile.children,function(o){
                        if(o[1]==id)
                            arr.push(o[0]);
                    },null,true);

                    if(arr.length)
                        dialog.append(linb.UI.pack(arr,false));

                    profile.boxing().removeItems(id);

                    //for design mode in firefox
                    return false;
                }
            }
        },
        DataModel:{
            dataBinder:null,
            dataField:null,

            dock:'fill',
            noPanel:false,
            width:200,
            height:200,
            position:'absolute',
            HAlign:{
                ini:'left',
                listbox:['left','center','right'],
                action:function(value){
                    this.getSubNode('ITEMS').css('textAlign',value);
                }
            },
            dropKeysPanel:'',
            value:{
                ini:''
            },
            //use ilist defualt items
            items:{
                set:function(value){
                    var o=this;
                    if(o.renderId){
                        var box = o.boxing(),
                            p,
                            temp = linb.$getGhostDiv(),
                            children = _.copy(o.children);
                        o.children.length=0;
                        _.arr.each(children,function(o){
                            //for flush dock
                            delete o[0].$dockParent;
                            //keep it in dom
                            temp.appendChild(o[0].getRootNode());
                        });

                        //bak value
                        var bv = o.properties.value;

                        //clear all
                        box.clearItems();

                        //inset items
                        box.insertItems(value);

                        //restore children
                        _.arr.each(children,function(v){
                            box.append.apply(box,v);
                        });

                        //clear
                        temp.innerHTML='';

                        //set value
                        box.setValue(bv,true);

                        //resize
                        var t=o.getRootNode().style;
                        linb.UI.$tryResize(o, t.width, t.height,true);
                        t=null;
                    }else
                        o.properties.items = _.copy(value);
                }
            }
        },
        EventHandlers:{
            onIniPanelView:function(profile, item){},
            beforePageClose:function(profile, item, src){},
            afterPageClose:function(profile, item){},
            onShowOptions:function(profile,item,e,src){},
            onItemSelected:function(profile, item, src){},
            onCaptionActive:function(profile, item, src){}
        },
        RenderTrigger:function(){
            var self=this,v,i,ins;
            // set default value
            if(v=self.properties.value){
                (ins=self.boxing()).setUIValue(v);
                if(i=self.getItemByItemId(v))
                    ins.onItemSelected(self, i);
            }
        },
        _prepareData:function(profile){
            var data = arguments.callee.upper.call(this, profile);
            data.panels = data.items;
            data.HAlign = 'text-align:'+data.HAlign+';';
            return data;
        },
        _prepareItem:function(profile, item){
            var dpn = 'display:none';
            item.closeDisplay = item.closeBtn?'':dpn;
            item.landDisplay = item.landBtn?'':dpn;
            item._opt = item.optBtn?'':dpn;
            item.href = item.href || linb.$href;
        },
        getDropKeys:function(profile,node){
            return profile.properties[profile.getKey(linb.use(node).id())==profile.keys.PANEL?'dropKeys':'dropKeysPanel'];
        },
        _showTips:function(profile, node, pos){
            var id=node.id,
                p=profile.properties,
                keys=profile.keys,
                key=profile.getKey(id);
            if(!id)return false;

            if(profile.onShowTips)
                return profile.boxing().onShowTips(profile, node, pos);
            else
                return arguments.callee.upper.apply(this,arguments);
        },
        //for tabs only
        _onresize:function(profile,width,height,force,key){
            var t=profile.properties,
                item = profile.getItemByItemId(key);
            if(!item)
                key=t.$UIvalue;
            item = profile.getItemByItemId(key);
            var o = profile.boxing().getPanel(key),
                l=profile.getSubNode('LIST'),
                forceH=0,
                listH;
            ;
            if(!o || o.isEmpty())return;

            var wc=null,hc=null;
            if(force)item._w=item._h=null;
            if(width && item._w!=width){
                if(height!='auto')
                    height=profile.getRootNode().offsetHeight || profile.getRoot().offsetHeight();
                forceH=1;
            }
            if((height && item._h!=height) || forceH){
                item._h=height;
                if(height && height!='auto'){
                    listH = l.get(0).offsetHeight ||
                        //for opear 9.0 get height bug, get offsetheight in firefox is slow
                        l.offsetHeight();
    
                    height = height-listH+(linb.browser.ie6?2:1);
                    if(height>0)hc=height;
                }else hc=height;
            }
            //if(listH)o.top(listH);
            //force to trigger onSze event, whatever width or height was changed.
            if(hc)o.height(hc).onSize();
        }
    }
});Class("linb.UI.Stacks", "linb.UI.Tabs",{
    Initialize:function(){
        var t=this.getTemplate();
        t.BOX={tagName:'div',LIST:t.LIST, PNAELS:t.PNAELS};
        delete t.LIST;
        delete t.PNAELS;
        this.setTemplate(t);
    },
    Static:{
        Appearances:{
            BOX:{
                border:'solid 1px #648CB4',
                position:'absolute',
                left:0,
                top:0
            },
            LIST:{
                position:'static'
            },
            ITEMS:{
                position:'static'
            },
            ITEM:{
                $order:0,
                display:'block',
                position:'absolute',
                cursor:'pointer',
                background: linb.UI.$bg('bar_vertical.gif', 'repeat-x left -380px', true),
                width:'100%',
                left:0
            },
            ITEMC:{
                display:'block'
            },
            ITEMI:{
                display:'block'
            },
            'ITEM-mouseover':{
                $order:1,
                'background-position' : 'right -410px'
            },
            'ITEM-mousedown, ITEM-checked':{
                $order:2,
                'background-position' : 'right -440px'
            },
            HANDLE:{
                cursor:'pointer',
                display:'block',
                'font-size':'12px',
                height:'100%',
                height:'18px',
                'padding':'5px 0 5px 8px',
                'white-space':'nowrap'
            },
            PANEL:{
                position:'absolute',
//                visibility:'hidden',
//                top:'-10000px',
//                left:'-10000px',
                display:'none',
                overflow:'auto'
            },
            CMDS:{
                position:'absolute',
                top:'6px',
                right:'8px',
                'text-align':'right',
                'vertical-align': 'middle'
            }
        },
        DataModel:{
            $border:1,
            NoPanel:null
        },
        _onresize:function(profile,width,height,force,key){
            var t=profile.properties,
                item = profile.getItemByItemId(key),
                bw=t.$border*2;
            if(!item)
                key=t.$UIvalue;

            var temp,t1,t2,obj,top,
                wc=null,hc=null,
                bx=profile.getSubNode('BOX'),
                o = profile.boxing().getPanel(key);
            if(!o || o.isEmpty())return;

            // change value
            if(height){
                height-=bw;
                t2=t1=0;
                _.arr.each(t.items,function(o){
                    obj = profile.getSubNodeByItemId('ITEM', o.id);
                    obj.cssRegion({bottom:'auto',top:t1});

                    // offsetHeight maybe not set here
                    t1 += obj.height();
                    if(o.id == key)return false;
                });
                _.arr.each(t.items,function(o){
                    if(o.id == key)return false;
                    obj = profile.getSubNodeByItemId('ITEM', o.id);
                    obj.cssRegion({top:'auto',bottom:t2});
                    t2+= obj.height();
                },null,true);

                temp = height - t1 - t2;
                if(temp>0){
                    top=t1;
                    hc=temp;
                }

                bx.height(height);
            }
            if(width){
                width-=bw;
                wc=width;
                bx.width(width);
            }

            o.cssRegion({width:wc?wc:null,height:hc?hc:null,top:top,left:0},true);
            if(wc)profile.getSubNode('LIST').width(wc);
        }
    }
});
Class("linb.UI.ButtonViews", "linb.UI.Tabs",{
    Initialize:function(){
        var t = this.getTemplate();
        t.LIST.className='uibg-bar uiborder-outset';
        this.setTemplate(t);
    },
    Static:{
        Appearances:{
            LIST:{
                'z-index':'2',
                position:'absolute'
            },
            ITEMS:{
                'z-index':'2',
                position:'absolute',
                left:0,
                top:0
            },
            ITEM:{
                $order:0,
                margin:'2px',
                position:'relative',
                'font-family': '"Verdana", "Helvetica", "sans-serif"',
                cursor:'pointer',
                'padding-right':'4px',
                'vertical-align':'top',
                background: linb.UI.$bg('button.gif', 'no-repeat right -270px',true)
            },
            'ITEM-mouseover':{
                $order:1,
                'background-position' : 'right -360px'
            },
            'ITEM-mousedown, ITEM-checked':{
                $order:2,
                'background-position' : 'right -450px'
            },
            ITEMI:{
                $order:0,
                'padding-left':'4px',
                //keep this same with ITEM
                'vertical-align':'top',
                'text-align': 'center',
                background: linb.UI.$bg('button.gif', 'no-repeat left -330px', true)
            },
            'ITEM-mouseover ITEMI':{
                $order:1,
                'background-position' : 'left -420px'
            },
            'ITEM-mousedown ITEMI, ITEM-checked ITEMI':{
                $order:2,
                'background-position' : 'left -510px'
            },
            ITEMC:{
                $order:0,
                //keep this same with ITEM
                'vertical-align':'top',
                'text-align': 'center',
                height:'20px',
                padding:'2px 0',
                background: linb.UI.$bg('button.gif', 'repeat-x left -300px', true)
            },
            'ITEM-mouseover ITEMC':{
                $order:1,
                'background-position' : 'left -390px'
            },
            'ITEM-mousedown ITEMC, ITEM-checked ITEMC':{
                $order:2,
                'background-position' : 'left -480px'
            },
            LEFT:{
                'border-right': '1px solid #A7A6AA'
            },
            RIGHT:{
                'border-left': '1px solid #A7A6AA'
            },
            TOP:{
                'border-bottom': '1px solid #A7A6AA'
            },
            BOTTOM:{
                'border-top': '1px solid #A7A6AA'
            },
            HANDLE:{
                display:linb.$inlineBlock,
                zoom:linb.browser.ie6?1:null,
                cursor:'pointer',
                'vertical-align':'middle',
                'font-size':'12px',
                margin:'1px'
            }
        },
        DataModel:{
            barLocation:{
                ini:'top',
                listbox:['top','bottom','left','right'],
                action:function(v){
                    var self=this,
                        hs = self.getSubNode('LIST'),
                        h = self.getSubNodes(['ITEM','ITEMI','ITEMC'],true);
                    switch(v){
                        case 'left':
                            hs.cssRegion({left:0,top:0,right:'auto',bottom:0});
                        break;
                        case 'top':
                            hs.cssRegion({left:0,top:0,right:0,bottom:'auto'});
                        break;
                        case 'right':
                            hs.cssRegion({left:'auto',top:0,right:0,bottom:0});
                        break;
                        case 'bottom':
                            hs.cssRegion({left:0,top:'auto',right:0,bottom:0});
                       break;
                    }
                    switch(v){
                        case 'left':
                        case 'right':
                            h.css('display','block');
                            break;
                        case 'top':
                        case 'bottom':
                            h.setInlineBlock();
                            hs.height('auto');
                            break;
                    }
                    self.boxing().setBarSize(self.properties.barSize,true);
                }
            },
            barHAlign:{
                ini:'left',
                listbox:['left','center', 'right'],
                action:function(v){
                    var hl = this.getSubNode('ITEMS');
                    hl.css('textAlign',v);
                }
            },
            barVAlign:{
                ini:'top',
                listbox:['top','bottom'],
                action:function(v){
                    var hl = this.getSubNode('ITEMS');
                    if(v=='top')
                        hl.cssRegion({top:0,bottom:'auto'});
                    else
                        hl.cssRegion({bottom:0,top:'auto'});
                }
            },
            barSize:{
                ini:50,
                action:function(v){
                    var self=this,
                        t=self.properties,
                        hs = self.getSubNode('LIST'),
                        hl = self.getSubNode('ITEMS');
                    if(t.barLocation=='left'||t.barLocation=='right'){
                        hs.merge(hl).width(v);
                    }else{
                        hs.height(v);
                    }
                    var t=self.getRootNode().style;
                    linb.UI.$tryResize(self,t.width, t.height,true);
                }
            }
        },
        LayoutTrigger:function(){
            var pro = this.properties;
            this.boxing().setBarLocation(pro.barLocation,true)
            .setBarHAlign(pro.barHAlign,true)
            .setBarVAlign(pro.barVAlign,true);
        },
        _onresize:function(profile,width,height,force,key){
            var t=profile.properties,
                item = profile.getItemByItemId(key);
            if(!item)
                key=t.$UIvalue;
            var o = profile.boxing().getPanel(key),
                top, left,
                hs = profile.getSubNode('LIST'),
                hl = profile.getSubNode('ITEMS'),
                wc=null,hc=null;

            if(t.barLocation=='top'||t.barLocation=='bottom'){
                if(width){
                    hs.width(width);
                    hl.width(width);
                    left = 0;
                    wc=width;
                }
                if(height-t.barSize>0)hc=height-t.barSize-2;
                top = t.barLocation=='top'?2- -t.barSize:0;
            }else{
                if(height){
                    hs.height(height);
                    top=0;
                    hc=height;
                }
                if(width){
                    left = t.barLocation=='left'?2- -t.barSize:0;
                    wc=width-t.barSize-2;
                }
            }
            if(o && !o.isEmpty())o.cssRegion({width:wc?wc:null,height:hc?hc:null,left:left,top:top},true);
        }
    }
});Class("linb.UI.RadioBox", "linb.UI.List",{
    Initialize:function(){
        //modify default template for shell
        var t = this.getTemplate();
        t.ITEMS.className='';
        t.$submap={
            items:{
                ITEM:{
                    className:'{itemClass}  {disabled}',
                    style:'{itemStyle}',
                    tagName: 'a',
                    href :linb.$href,
                    tabindex: '{_tabindex}',
                    MARK:{
                        $order:0,
                        className:'uicmd-radio'
                    },
                    ICON:{
                        $order:1,
                        className:'ui-icon {imageClass}',
                        style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                    },
                    CAPTION:{
                        text : '{caption}',
                        $order:2
                    }
                }
            }
        };
        this.setTemplate(t);
    },
    Static:{
        _DIRTYKEY:'MARK',
        Appearances:{
            ITEM:{
               display:linb.$inlineBlock,
               zoom:linb.browser.ie6?1:null,
               'font-family':' "Verdana", "Helvetica", "sans-serif"',
               border:0,
               padding:'4px',
               position:'relative',
               zoom:linb.browser.ie?1:null,
               cursor:'pointer',
               overflow:'hidden',
               'vertical-align':'middle',
               'font-size':'12px'
            },
            CAPTION:{
                'vertical-align':'middle'
            },
            ITEMS:{
                overflow:'auto',
                'overflow-x': (linb.browser.ie || linb.browser.gek)?'hidden':'',
                position:'relative',
                'line-height':'14px'
            }
        },
        Behaviors:{
            HoverEffected:{ITEM:'MARK'},
            ClickEffected:{ITEM:'MARK'}
        },
        _onresize:function(){}
    }
});
Class("linb.UI.TreeBar",["linb.UI","linb.absList","linb.absValue"],{
    Instance:{
        _setCtrlValue:function(value, flag){
            return this.each(function(profile){
                if(!profile.renderId)return;

                var box = profile.boxing(),
                    uiv = box.getUIValue(),
                    properties = profile.properties,
                    fun=function(key,o,b){
                        profile.getSubNodeByItemId(key, o).tagClass('-checked', b);
                    },
                    selmode=properties.selMode
                    ;
                if(selmode=='single'){
                    var itemId = profile.getSubIdByItemId(uiv);
                    if(uiv && itemId)
                        profile.getSubNode('BAR',itemId).tagClass('-checked',false);

                    itemId = profile.getSubIdByItemId(value);
                    if(itemId)
                        profile.getSubNode('BAR',itemId).tagClass('-checked')
                }else if(selmode=='multi'){
                    uiv = uiv?uiv.split(';'):[];
                    value = value?value.split(';'):[];
                    if(flag){
                        _.arr.each(value,function(o){
                            fun('BAR', o);
                        });
                    }else{
                        //check all
                        _.arr.each(uiv,function(o){
                            if(_.arr.indexOf(value,o)==-1){
                                fun('BAR', o, false);
                            }
                        });
                        _.arr.each(value,function(o){
                            if(_.arr.indexOf(uiv,o)==-1){
                                fun('BAR', o);
                            }
                        });
                    }
                }
            });
        },
        insertItems:function(arr, pid, base ,before){
            var node,arr2;
            return this.each(function(profile){
                // prepare properties format
                var tar,r,k;
                
                arr2=profile.box._adjustItems(arr);
                
                if(!pid){
                    k=profile.properties;
                    tar = k.items ||(k.items=[])
                }else{
                    k=profile.getItemByItemId(pid);
                    tar = k.sub || (k.sub= []);
                }
                if(profile.renderId){
                    if(!base){
                        if(!pid)
                            node=profile.getSubNode('ITEMS');
                        else if(pid && k._created)
                            node=profile.getSubNodeByItemId('SUB', pid);
                        if(node){
                            r=profile._buildItems('items', profile.box._prepareItems(profile, arr2, pid));
                            if(before)
                                node.prepend(r);
                            else
                                node.append(r);
                        }
                    }else{
                        node=profile.getSubNodeByItemId('ITEM', base);
                        if(node){
                            r=profile._buildItems('items', profile.box._prepareItems(profile, arr2, pid));
                            if(before)
                                node.addPrev(r);
                            else
                                node.addNext(r);
                        }
                    }
                }
                //must be here
                if(!base)
                    _.arr.insertAny(tar,arr2, before?0:-1);
                else{
                    var index = _.arr.subIndexOf(tar, 'id', base);
                    _.arr.insertAny(tar,arr2, before?index:(index+1));
                }
                
                var obj;
                if(pid)
                    if((obj=profile.getSubNodeByItemId('TOGGLE', pid)).css('display')=='none')
                        obj.setInlineBlock();

                //open parent node
                if(!(('iniFold' in k)?k.iniFold:profile.properties.iniFold))
                    if(!pid || profile.getItemByItemId(pid)._created)
                        profile.boxing()._toggleNodes(arr2, true);

            });
        },
        _toggleNodes:function(items, expend, recursive){
            var self=this;
            _.arr.each(items,function(o){
                self.toggleNode(o.id, expend, recursive)
            });
            return self;
        },
        /*
        *expend:true->expend false->fold
        *recursive:true open recursively
        */
        toggleNode:function(id, expend, recursive){
            var profile=this.get(0),
                o=profile.getItemByItemId(id);
            if(o && o.sub)
                profile.box._setSub(profile, o, typeof expend=="boolean"?expend:!o._checked, recursive);
            return self;
        },
        /*
        *open to deep node
        */
        openToNode:function(id){
            return this.each(function(profile){
                var res=false, a=[],
                    fun=function(arr, catId, layer){
                        layer = layer || 0;
                        var me=arguments.callee;
                        _.arr.each(arr,function(o){
                            if(o.id==catId){
                                a.push(o);
                                res=true;
                                return false;
                            }
                            if(o.sub){
                                res = me.call(me, o.sub, catId, ++layer)
                                if(res){
                                    a.push(o);
                                    return false;
                                }
                            }
                        });
                        return res;
                    }
                fun(profile.properties.items, id);
                if(res){
                    a.reverse();
                    _.arr.each(a,function(o){
                        if(o.sub){
                            profile.boxing().toggleNode(o.id,true);
                        }else
                            profile.boxing().fireItemClickEvent(o.id);
                    });
                }
            });
        },
        fireItemClickEvent:function(subId){
            this.getSubNodeByItemId('BAR', subId).onClick();
            return this;
        }     
    },
    Initialize:function(){
        this.addTemplateKeys(['DISABLED']);
    },
    Static:{
        Templates:{
            tagName : 'div',
            style:'{_style}',
            ondrag:'return false',
            onselectstart:'return false',
            BORDER:{
                tagName : 'div',
                BOX:{
                    tagName : 'div',
                    onselectstart:'return false',
                    ITEMS:{
                        tagName : 'div',
                        text:"{items}"
                    }
                }
            },
            $submap:{
                items:{
                    ITEM:{
                        className:'{itemClass} {disabled}',
                        style:'{itemStyle}',
                        tagName : 'div',
                        onselectstart:'return false',
                        unselectable:'on',
                        BAR:{
                            $order:0,
                            tagName: 'a',
                            href :"{href}",
                            tabindex: '{_tabindex}',
                            className:'{cls_group} ',
                            onselectstart:'return false',
                            unselectable:'on',
                            MARK2:{
                                $order:0,
                                style:'{mark2Display}'
                            },
                            TOGGLE:{
                                $order:1,
                                className:'uicmd-toggle',
                                style:'{mark}'
                            },
                            ITEMICON:{
                                $order:2,
                                className:'ui-icon {imageClass}',
                                style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                            },
                            ITEMCAPTION:{
                                text : '&nbsp;{caption}',
                                className:"{disabled} ",
                                $order:3
                            }
                        },
                        SUB:{
                            $order:1,
                            tagName : 'div',
                            text:linb.UI.$childTag
                        }
                    }
                }
            }
        },
        Appearances:{
            KEY: {
                'font-family': 'Verdana, Helvetica, sans-serif',
                'border':0
            },
            BOX:{
                left:0,
                overflow: 'auto',
                'overflow-x':(linb.browser.ie ||linb.browser.gek)?'hidden':'',
                position:'relative'
            },
            ITEMS:{
                overflow: 'hidden'
            },
            ITEM:{
                'white-space': 'nowrap',
                position:'relative',
                overflow:'hidden'
            },
            BAR:{
               cursor:'pointer',
               zoom:linb.browser.ie?1:null,
               position:'relative',
               display:'block',
               overflow: 'hidden',
               'font-size':'12px',
               padding:'2px 4px',
               border: '1px solid',
               'border-color':'#EDF4FC #698AB3 #698AB3 #698AB3',
               'background-color':'#CCE4FC'
            },
            DISABLED:{
                color:'#808080'
            },
            'BAR-mouseover':{
                $order:1,
               'background-color': '#fffa9f'
            },
            'BAR-checked':{
                $order:2,
               'background-color': '#fffa9f'
            },
            'BAR-GROUP':{
                $order:2,
                'border-top': 'none',
                'border-bottom': 'none',
                padding:'5px 4px',
                height:'18px',
                background: linb.UI.$bg('bar_vertical.gif','repeat-x left -380px', true)
            },
            'BAR-GROUP-mouseover':{
                $order:3,
                'background-position': 'left -410px'
            },
            'BAR-GROUP-checked':{
                $order:4,
                'background-position': 'left -440px'
            },
            SUB:{
                overflow:'hidden',
                '*zoom':1,
                height:0,
                'font-size':'1px',
                //1px for ie8
                'line-height':'1px',
                position:'relative',
                'margin-left':'12px'
            },

            MARK2:{
               cursor:'pointer',
               width:'16px',
               height:'16px',
               'vertical-align':'middle',
               background: linb.UI.$bg('icons.gif', 'no-repeat -20px -70px', true)
            },
            'BAR-checked MARK2':{
                $order:3,
                'background-position': '0 -70px'
            },
            ITEMCAPTION:{
                'vertical-align':'middle',
                padding:'2px'
            }
        },
        Behaviors:{
            HoverEffected:{TOGGLE:'TOGGLE', BAR:'BAR'},
            ClickEffected:{TOGGLE:'TOGGLE', BAR:'BAR'},
            DragableKeys:["BAR"],
            DropableKeys:["BAR","TOGGLE","BOX"],
            onSize:linb.UI.$onSize,
            TOGGLE:{
                onClick:function(profile, e, src){
                    var properties = profile.properties,
                        domId=linb.use(src).id(),
                        item = profile.getItemByDom(domId);

                    if(properties.disabled || item.disabled)return false;
                    if(!('sub' in item))return false;
                    profile.box._setSub(profile, item, !item._checked);

                    // not to fire BAR's onclick event;
                    return false;
                }
            },
            BAR:{
                onClick:function(profile, e, src){
                    var properties = profile.properties,
                        domId=linb.use(src).id(),
                        item = profile.getItemByDom(domId),
                        itemId =profile.getSubId(domId),
                        box = profile.boxing(),
                        ks=linb.Event.getKey(e),
                        rt,rt2;

                    if(properties.disabled|| item.disabled)return false;
                    //group not fire event
                    if(item.sub && (item.hasOwnProperty('group')?item.group:properties.group)){
                        profile.getSubNode('TOGGLE', itemId).onClick();
                        return false;
                    }

                    switch(properties.selMode){
                    case 'none':
                        rt=box.onItemSelected(profile, item, src);
                        break;
                    case 'multi':
                        var value = box.getUIValue(),
                            arr = value?value.split(';'):[];
                        if(arr.length&&(ks[1]||ks[2]||properties.noCtrlKey)){
                            //for select
                            rt2=false;
                            if(ks[2]){
                                if(profile.$firstV._pid!=item._pid)return false;
                                var items=properties.items;
                                if(item._pid){
                                    var pitem=profile.getItemByItemId(item._pid);
                                    if(pitem)items=pitem.sub;
                                }
                                var i1=_.arr.subIndexOf(items,'id',profile.$firstV.id),
                                    i2=_.arr.subIndexOf(items,'id',item.id),
                                    i;
                                arr.length=0;
                                for(i=Math.min(i1,i2);i<=Math.max(i1,i2);i++)
                                    arr.push(items[i].id);
                            }else{
                                if(_.arr.indexOf(arr,item.id)!=-1)
                                    _.arr.removeValue(arr,item.id);
                                else
                                    arr.push(item.id);
                            }
                            arr.sort();
                            value = arr.join(';');

                            //update string value only for _setCtrlValue
                            if(box.getUIValue() == value)
                                rt=false;
                            else{
                                box.setUIValue(value);
                                if(box.getUIValue() == value)
                                    rt=box.onItemSelected(profile, item, src)||rt2;
                            }
                            break;
                        }
                    case 'single':
                        if(box.getUIValue() == item.id)
                            rt=false;
                        else{
                            profile.$firstV=item;
                            box.setUIValue(item.id);
                            if(box.getUIValue() == item.id)
                                rt=box.onItemSelected(profile, item, src);
                        }
                        break;
                    }

                    profile.getSubNode('BAR', itemId).focus();
                    return rt;
                },
                onKeydown:function(profile, e, src){
                    var keys=linb.Event.getKey(e), key = keys[0], shift=keys[2],
                        cur = linb(src),
                        root = profile.getRoot(),
                        first = root.nextFocus(true, true, false),
                        last = root.nextFocus(false, true, false);

                    switch(linb.Event.getKey(e)[0]){
                        case 'tab':
                            if(shift){
                                if(cur.get(0)!=first.get(0)){
                                    first.focus();
                                    return false;
                                }
                            }else{
                                if(cur.get(0)!=last.get(0)){
                                    last.focus();
                                    return false;
                                }
                            }
                            break;
                        case 'up':
                            var next = cur.nextFocus(false, true, false);
                            if(cur.get(0)==first.get(0))
                                last.focus();
                            else
                                cur.nextFocus(false);
                             return false;
                             break;
                        case 'down':
                            var next = cur.nextFocus(true, false, false);
                             if(cur.get(0)==last.get(0))
                                first.focus();
                             else
                                cur.nextFocus();
                             return false;
                             break;
                        case 'right':
                        case 'left':
                            profile.getSubNode('TOGGLE',profile.getSubId(src)).onClick();
                            return false;
                    }
                }
            },
            BOX:{
                onScroll:function(profile, e, src){
                    //for ie 'href focus' will scroll view
                    if((e=linb.use(src)).scrollLeft()!==0)
                        e.scrollLeft(0);
                }
            }
        },
        EventHandlers:{
            onGetContent:function(profile, item, callback){},
            onItemSelected:function(profile, item, src){}
        },
        DataModel:{
            listKey:null,
            width:200,
            height:200,
            iniFold:true,
            animCollapse:false,
            dock:'fill',
            group:{
                ini:false,
                action:function(v){
                    var self = this,
                        items = self.properties.items,
                        results = self.queryItems(items, function(o){return o.sub && o.group===undefined }),
                        nodes=linb();
                    _.arr.each(results,function(o){
                        nodes.merge( self.getSubNodeByItemId('BAR', o.id) );
                    });
                    var cls1=self.getClass('BAR'), cls2 = self.getClass('BAR', '-group');
                    if(v)
                       nodes.replaceClass(new RegExp('(\\b)' + cls1 + '([^b]*\\b)','g'), '$1'+cls2+'$2');
                    else
                       nodes.replaceClass(new RegExp('(\\b)' + cls2 + '([^b]*\\b)','g'), '$1'+cls1+'$2');
                }
            },
            selMode:{
                ini:'single',
                listbox:['single','none','multi'],
                action:function(value){
                    var ns=this,p=this.properties,sels=[];
                    _.each(this.SubSerialIdMapItem,function(o){
                        if(!(o.sub && (o.hasOwnProperty('group')?o.group:p.group)))
                            sels.push(ns.getSubNodeByItemId('MARK2',o.id).get(0));
                    });
                    linb(sels).css('display',value=='multi'?'':'none');
                }
            },
            noCtrlKey:true,
            singleOpen:false,
            dynDestory:false,
            position:'absolute'

        },
        RenderTrigger:function(){
            var self=this, pro=self.properties;
            if(!pro.iniFold)
                self.boxing()._toggleNodes(pro.items, true);
        },
        _onStartDrag:function(profile, e, src, pos){
            var pos=linb.Event.getPos(e);
            linb.use(src).startDrag(e, {
                dragType:'icon',
                shadowFrom:src,
                targetLeft:pos.left+12,
                targetTop:pos.top+12,
                dragCursor:'pointer',
                dragDefer:1,
                dragKey: profile.box.getDragKey(profile, src),
                dragData: profile.box.getDragData(profile, e, src)
            });
            return false;
        },
        _onDropTest:function(profile, e, src, key, data, item){
            var fid=data&&data.domId, tid=linb.use(src).id();
            if(fid){
                if(fid==tid)return false;
                if(_.get(linb.use(src).get(0),['parentNode','previousSibling','firstChild','id'])==fid)return false;
            }
        },
        _onDrop:function(profile, e, src, key, data, item){
            linb.DragDrop.setDragIcon('none');

            var k=profile.getKey(linb.use(src).id()),
                po=data.profile,
                ps=data.domId,
                oitem,
                ks=profile.keys,
                t=linb.absObj.$specialChars,
                b=profile.boxing();
            //remove
            oitem=_.clone(po.getItemByDom(ps),function(o,i){return !t[(i+'').charAt(0)]});
            po.boxing().removeItems([oitem.id]);

            //add
            if(k==ks.BOX)
                b.insertItems([oitem], null, null, false);
            else if(k==ks.BAR)
                b.insertItems([oitem], item._pid, item.id, true);
            else if(k==ks.TOGGLE)
                b.insertItems([oitem], item.id, null, false);

            return false;
        },
        _ensureValue:function(profile,value){
            if(profile.properties.selMode=='multi'){
                var arr = (value||"").split(';');
                arr.sort();
                return arr.join(';');
            }else
                return value;
        },
        _prepareItem:function(profile, item, oitem, pid){
            var p=profile.properties;

            if(pid)oitem._pid=pid;
            // set 'visible' will show when parent call .height()
            item.mark = item.sub?'':'display:none';
            item.disabled = item.disabled?profile.getClass('KEY', '-disabled'):'';
            item.mark2Display = (p.selMode=='multi')?'':'display:none';
            item._tabindex = p.tabindex;
            item.href = item.href || linb.$href;
            //change css class
            if(item.sub && (item.hasOwnProperty('group')?item.group:p.group)){
                item.cls_group = profile.getClass('BAR', '-group');
                item.mark2Display = 'display:none';
            }
        },
        _setSub:function(profile, item, flag, recursive){
            var id=profile.domId,
                itemId = profile.getSubIdByItemId(item.id),
                properties = profile.properties,
                barNode = profile.getSubNode('BAR', itemId),
                markNode = profile.getSubNode('TOGGLE', itemId),
                subNs = profile.getSubNode('SUB', itemId);
                ;

            if(linb.Thread.isAlive(profile.key+profile.id)) return;
            //close
            if(item._checked){
                if(!flag){
                    var h=subNs.height()

                    if(properties.animCollapse)
                        subNs.animate({'height':[h,0]},null,null, 100, 5, 'expoIn', profile.key+profile.id).start();
                    else
                        subNs.height(0);

                    markNode.tagClass('-checked', false);
                    item._checked = false;

                    if(item.group || properties.group)
                        barNode.tagClass('-checked', false);
                    if(properties.dynDestory){
                        var s=item.sub, arr=[];
                        for(var i=0,l=s.length;i<l;i++)
                            arr.push(s[i].id);
                        profile.boxing().removeItems(arr);
                        item.sub=true;
                        delete item._created;
                    }
                }
                if(recursive && item.sub && !properties.dynDestory){
                    _.arr.each(item.sub,function(o){
                        if(o.sub && o.sub.length)
                            profile.box._setSub(profile, o, false, true);
                    });
                }
            }else{
                //open
                if(flag){
                    var openSub = function(profile, item, id, markNode, subNs, barNode, sub, recursive){
                            var b=profile.boxing(),
                                p=profile.properties;
                            //created
                            if(!item._created){
                                delete item.sub;
                                //before insertRows
                                item._created=true;
                                //subNs.css('display','none');
                                if(typeof sub=='string')
                                    subNs.html(item.sub=sub,false);
                                else if(_.isArr(sub))
                                    b.insertItems(sub, item.id);
                                else if(sub['linb.Template']||sub['linb.UI'])
                                    subNs.append(item.sub=sub.render(true));

                                //set checked items
                                b._setCtrlValue(b.getUIValue(), true);
                            }

                            if(p.singleOpen)
                                b._toggleNodes(item._pid?profile.getItemByItemId(item._pid).sub:p.items, false)

                            if(!recursive){
                                var h = subNs.height(true);
                                if(p.animCollapse)
                                    subNs.animate({'height':[0,h]},null,function(){subNs.height('auto')}, 100, 5, 'expoOut', profile.key+profile.id).start();
                                else
                                    subNs.height('auto');
                            }else
                                subNs.height('auto');

                            markNode.tagClass('-checked');
                            if(item.group || properties.group)
                                barNode.tagClass('-checked');

                            item._checked = true;
                        },
                        sub=item.sub,
                        callback=function(sub){
                            openSub(profile, item, id, markNode, subNs, barNode, sub, recursive)
                        },
                        t;
                    if((t=typeof sub)=='string'||t=='object')
                        callback(sub);
                    else if(profile.onGetContent){
                        var r=profile.boxing().onGetContent(profile, item, callback);
                        if(r) callback(r);
                    }
                }
                if(recursive && item.sub){
                    _.arr.each(item.sub,function(o){
                        if(o.sub && o.sub.length && !o._checked)
                            profile.box._setSub(profile, o, true, true);
                    });
                }
            }
        },
        _onresize:function(profile,width,height){
            profile.getSubNode('BORDER').cssSize({ width :width?width:null, height :height?height:null});
            profile.getSubNode('BOX').cssSize({ width :width?width:null, height : height?height:null});
        }
    }
});
Class("linb.UI.PopMenu",["linb.UI.Widget","linb.absList"],{
    Instance:{
        _adjustSize:function(){
            this.each(function(profile){
                var
                root = profile.getRoot(),
                items = profile.getSubNode('ITEMS'),
                border = profile.getSubNode('BORDER'),
                size1 = root.cssSize(),
                size2 = border.cssSize(),
                pro=profile.properties,
                h = Math.min(pro._maxHeight, items.height() + size1.height - size2.height+1),
                w = Math.min(pro._maxWidth, items.width() + size1.width - size2.width+1)
                ;

                pro.width=w;
                pro.height=h;
                //set size first, for adding shadow later
                root.cssSize({width:w,height:h});

                //avoid blazing(shadow elements) when resize the border
                linb.UI.$doResize(profile,w,h,true);
            });
            return this._setScroll();
        },
        _setScroll:function(){
            return this.each(function(profile){
                var
                o=profile.getSubNode('ITEMS'),
                t=o.offsetTop(),
                h=o.offsetHeight(),
                b = profile.getSubNode('BORDER'),
                hh=b.offsetHeight();
                profile.getSubNode('TOP').css('display',t===0?'none':'block');
                profile.getSubNode('BOTTOM').css('display',(hh>h+t)?'none':'block');
            })
        },
        _scrollToBottom:function(){
            return this.each(function(profile){
                var o = profile.getSubNode('ITEMS'),
                border = profile.getSubNode('BORDER'),
                y = o.offsetTop(),
                offset,
                h = o.offsetHeight(),
                b=false,
                bh = border.height();
                if(bh<h+y){
                    if(!profile.$scrollStep)profile.$scrollStep=1;

                    if(profile.$scrollStep<30)
                        profile.$scrollStep = profile.$scrollStep*1.1;

                    y -= profile.$scrollStep;
                    if(bh>h+y){
                        y=bh-h;
                        b=true;
                    }
                    o.top(y);
                    if(b){
                        profile.getSubNode('BOTTOM').css('display','none');
                        profile.$scrollTobottom=false;
                        profile.$scrollStep=null;
                    }else{
                        profile.getSubNode('TOP').css('display','block');
                        if(profile.$scrollTobottom)
                            _.asyRun(arguments.callee, 0, [profile], this);
                    }
                }
            });
        },
        _scrollToTop:function(){
            return this.each(function(profile){
                var o = profile.getSubNode('ITEMS'),
                y = o.offsetTop(),
                b=false;

                if(y<0){
                    if(!profile.$scrollStep)profile.$scrollStep=1;

                    if(profile.$scrollStep<10)
                        profile.$scrollStep = profile.$scrollStep*1.03;

                    y += profile.$scrollStep;
                    if(y>=-1){
                        y=0;
                        b=true;
                    }
                    o.top(y);
                    if(b){
                        profile.getSubNode('TOP').css('display','none');
                        profile.$scrollToTop=false;
                        profile.$scrollStep=null;
                    }else{
                        profile.getSubNode('BOTTOM').css('display','block');
                        if(profile.$scrollToTop)
                            _.asyRun(arguments.callee, 0, [profile], this);
                    }
                }
            });
        },
        pop:function(obj, type, parent){
            var profile=this.get(0);
            //ensure rendered
            if(!profile.renderId){
                var o=profile.boxing().render(true);
                //use empty idv for LayoutTrigger
                linb.Dom.getEmptyDiv().append(o);
            }
            var root = profile.getRoot();

            //clear highLight first
            if(profile.$highLight)
                linb([profile.$highLight]).tagClass('-mouseover',false);
            profile._conainer=parent;

            root.popToTop(obj, type, parent);

            var f=function(){
                var p=arguments.callee.profile;
                p.boxing().hide();
                p.$popGrp.length=0;
            };
            f.profile=profile;

            if(!profile.$popGrp || !profile.$popGrp.length){
                profile.$popGrp = [root._get(0)];
                //group blur trigger
                root.setBlurTrigger(profile.$linbid, null);
                root.setBlurTrigger(profile.$linbid, f, profile.$popGrp);
            }
            return this;
        },
        hide:function(triggerEvent){
            var t,
                profile=this.get(0),
                root=profile.getRoot(),
                sms='$subPopMenuShowed',
                cm='$childPopMenu';

            if(false!==triggerEvent)
                if(false===profile.boxing().beforeHide(profile))
                    return this;

            if(!root || root.css('display')=='none')return;

            //remove trigger
            root.setBlurTrigger(profile.$linbid,null);

            if(profile.$hideMenuPool)
                profile.$hideMenuPool.append(root);
            else
                root.css('display','none');

            //hide all parent pop
            var p=profile[cm],q;
            if(t=profile[sms])t.hide();
            while(p){
                p.boxing().hide();
                p=(q=p)[cm];
                q[cm] = q[sms] = null;
            }
            profile[cm]=profile[sms]=null;
            if(t=profile.$parentPopMenu)t[sms]=null;

            _.arr.removeValue(profile.$popGrp,root._get(0));

            if(false!==triggerEvent)
                profile.boxing().onHide(profile);
            return this;
        }
    },
    Initialize:function(){
        //modify default template fro shell
        var t = this.getTemplate();
        _.merge(t.FRAME.BORDER,{
             TOP:{},
             BOTTOM:{},
             BOX:{
                tagName:'div',
                 ITEMS:{
                    tagName:'div',
                    text:"{items}"
                 }
             },
             POOL:{
                tagName : 'div',
                style:'display:none;'
             }
        },'all');
        t.$submap = {
            'items':function(profile,template,v,tag,result){
                var t;
                tag = tag+'.'+v.type;
                //for linb.UI or linb.Template
                if(t=v.object){
                    //[v] is for linb.Template
                    result[result.length]=t.build(v);
                }else{
                    if(template[tag])
                        linb.UI.$doTemplate(profile,template,v,tag,result);
                }
             },
            'items.split':{
                ITEMSPLIT:{
                    tagName : 'a'
                }
            },
            'items.button':{
                ITEM:{
                    tagName : 'a',
                    href :linb.$href,
                    tabindex: 1,
                    className: '{itemClass} {disabled}',
                    style:'{itemStyle}',
                    ICON:{
                        $order:0,
                        className:'ui-icon {imageClass}',
                        style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                    },
                    CAPTION:{
                        text : '{caption}',
                        $order:1
                    },
                    RULER:{
                        style:'{displayAdd}',
                        $order:2
                    },
                    ADD:{
                        tagName : 'div',
                        style:'{displayAdd}',
                        text : '{add}',
                        $order:2
                    },
                    SUB:{style:'{tagClass}'}
                }
            },
            'items.checkbox':{
                ITEM:{
                    tagName : 'a',
                    href :linb.$href,
                    tabindex: 1,
                    className: '{itemClass} {disabled}',
                    style:'{itemStyle}',
                    CHECKBOX:{
                        $order:0,
                         className:'ui-icon {checkboxCls}'
                    },
                    CAPTION:{
                        text : '{caption}',
                        $order:1
                    },
                    RULER:{
                        style:'{displayAdd}',
                        $order:2
                    },
                    ADD:{
                        tagName : 'div',
                        style:'{displayAdd}',
                        text : '{add}',
                        $order:2
                    }
                }
            }
        };
        this.setTemplate(t);
    },
    Static:{
        $noDomRoot:true,
        Appearances:{
            KEY:{
                'font-size':'12px',
                visibility:'hidden'
            },
            BORDER:{
                border:'1px solid',
                'border-color':'#FFF #ACA899 #ACA899 #FFF'
            },
            BOX:{
                'background-color':'#EEF7FF',
                overflow:'hidden',
                position:'absolute',
                left:0,
                top:0,
                'font-size':'12px',
                'z-index':'3'
            },
            ITEMS:{
                position:'absolute',
                top:0,
                left:0,
                overflow:'visible',
                background: linb.UI.$bg('bg.gif', 'repeat-y left top')
            },
            ITEM:{
                display:'block',
                position:'relative',
                overflow:'visible',
                'white-space': 'nowrap',
                color:'#000',
                'font-family': '"Verdana", "Helvetica", "sans-serif"',
                cursor:'pointer',
                padding:'2px 20px 2px 2px'
            },
            ITEMSPLIT:{
                display:'block',
                position:'relative',
                overflow:'visible',
                'white-space': 'nowrap',
                'font-size':'1px',
                'line-height':'1px',
                padding:'1px',
                margin:'2px 2px 2px 26px',
                background: linb.UI.$bg('split_horizontal.gif', 'repeat-x left top', true)
            },
            'ITEM-mouseover':{
                $order:1,
                'background-color':'#FFFA9F',
                border:'solid 1px #94A3A8',
                padding:'1px 19px 1px 1px'
            },
            'ITEM-checked':{
                $order:2,
                'background-color':'#FFFA9F',
                border:'solid 1px #94A3A8',
                padding:'1px 19px 1px 1px'
            },
            CHECKBOX:{
               background: linb.UI.$bg('icons.gif', 'no-repeat -20px -70px', true),
               margin:0
            },
            ICON:{
                margin:0
            },
            'CHECKBOX-checked':{
               $order:1,
               background: linb.UI.$bg('icons.gif', 'no-repeat -0px -70px', true)
            },
            TOP:{
                cursor:'pointer',
                display:'none',
                position:'absolute',
                'margin-left':'-8px',
                right:0,
                height:'16px',
                width:'16px',
                'z-index':'10',
                top:0,
                background: linb.UI.$bg('icons.gif', 'no-repeat -48px -244px', true)
            },
            BOTTOM:{
                cursor:'pointer',
                display:'none',
                position:'absolute',
                'margin-left':'-8px',
                right:0,
                height:'16px',
                width:'16px',
                'z-index':'10',
                bottom:0,
                background: linb.UI.$bg('icons.gif', 'no-repeat -66px -244px', true)
            },
            'CHECKBOX, CHECKBOX-checked':{
                cursor:'pointer',
                'vertical-align':'middle',
                width:'16px',
                height:'16px'
            },
            CAPTION:{
                'vertical-align':'middle',
                'padding-left':'6px'
            },
            RULER:{
                width:'100px',
                'font-size':0,
                'line-height':0
            },
            ADD:{
                position:'absolute',
                top:'3px',
                right:0,
                width:'80px',
                'padding-right':'20px',
                'text-align':'right',
                'z-index':'10'
            },
            SUB:{
                position:'absolute',
                top:'2px',
                right:'2px',
                width:'8px',
                height:'16px',
                background: linb.UI.$bg('icons.gif', 'no-repeat -200px -70px', true)
            }
        },
        Behaviors:{
            ITEM:{
                onMouseover:function(profile, e, src){
                    var sms='$subPopMenuShowed',
                        all='$allPops',
                        hl='$highLight',
                        showp='$showpops',
                        popgrp='$popGrp';
                    //for stop second trigger by focus event
                    if(profile[hl] == src)return;

                    var properties = profile.properties,
                        item = profile.getItemByDom(src),
                        itemId = item.id,
                        Cancel = false,
                        pop,popp,t;
                    //if sub pop menu showed
                    if(t=profile[sms]){
                        //if the showed menu is self
                        if(t == _.get(profile,[all,itemId]))
                            Cancel=true;
                        else{
                            t.hide();
                            profile[sms] = null;
                        }
                    }
                    if(!Cancel){
                        if(t=profile[hl])
                            linb([t]).tagClass( '-mouseover',false);
                        profile[hl] = src;
                        linb.use(src).tagClass('-mouseover');
                        //don't fire events here
                        try{linb.use(src).get(0).focus()}catch(e){}
                    }

                    if(!Cancel && item.sub){
                        if(_.isArr(item.sub) && item.sub.length){
                            profile[all] = profile[all] || {};

                            //no create
                            if(!(pop = profile[all][itemId])){
                                pop = (new linb.UI.PopMenu({position:'absolute', items:item.sub, autoHide:profile.properties.autoHide})).render(true);
                                pop.onMenuSelected(function(pro, item, src){
                                    profile.boxing().onMenuSelected(profile, item, src);
                                });
                                popp=pop.get(0);
                                //set pool to parent
                                popp.$hideMenuPool = profile.$hideMenuPool || profile.getSubNode('POOL');

                                profile[all][itemId] = pop;

                                //collect
                                profile[showp] = profile[showp] || [profile];
                                popp[showp] = profile[showp];
                                profile[showp].push(popp);
                            }else popp=pop.get(0);

                            //input a copy of root for group trigger
                            profile[popgrp].push(popp.getRoot()._get(0));
                            popp[popgrp] = profile[popgrp];

                            //set parent pop
                            popp.$parentPopMenu = profile;
                            profile.$childPopMenu = popp;

                            pop.pop(src, 2);
                            profile[sms] = pop;
                        }else
                            if(profile.onShowSubMenu){
                                var r=profile['$sub:'+item.id];
                                if(r && r['linb.UI'] && !r.isEmpty()){}
                                else
                                    r=profile.boxing().onShowSubMenu(profile, item, src);
                                if(r && r['linb.UI'] && !r.isEmpty()){
                                    profile[sms] = r;
                                    r=r.reBoxing();
                                    r.onMouseout(function(p,e,src){
                                        profile.box._mouseout(profile, e, src);
                                    },null,-1);
                                    profile[popgrp].push(r._get(0));

                                    r.popToTop(src,2,profile._conainer);
                                }
                            }
                    }
                },
                onMouseout:function(profile, e, src){
                    var properties = profile.properties,
                        item = profile.getItemByDom(src),
                        itemId = item.id,
                        action = true,
                        t;
                    //if cursor move to submenu, keep the hover face
                    if(t=profile.$subPopMenuShowed){
                        var node = e.toElement||e.relatedTarget,
                            target = t.get(0).getRootNode();
                        try{
                            do{
                                if(node==target)
                                    return;
                            }while((node && (node=node.parentNode)))
                        }catch(a){}
                    }
                    linb.use(src).tagClass('-mouseover',false);
                    profile.$highLight = null;
                },
                onClick:function(profile, e, src){
                    var prop = profile.properties,
                        item = profile.getItemByDom(src),
                        itemId = item.id;
                    if(prop.disabled || item.disabled)return false;

                    if(!item.sub){
                        if(item.type=='checkbox')
                            profile.getSubNodeByItemId('CHECKBOX',item.id).tagClass('-checked', item.value = !item.value);

                        if(profile.onMenuSelected)profile.boxing().onMenuSelected(profile, item, src);

                        if(prop.hideAfterClick){
                            linb.use(src).tagClass('-mouseover',false);
                            //hide all parent pop
                            _.asyRun(function(){
                                var p=profile,q;
                                while(p){
                                    p.boxing().hide();
                                    p=(q=p).$parentPopMenu;
                                    q.$parentPopMenu = q.$subPopMenuShowed = null;
                                }
                                //reset
                                profile.$subPopMenuShowed = null;
                                profile.$popGrp.length=0;
                            },100);
                        }
                    }
                    return false;
                },
                onFocus:function(profile, e, src){
                    var box = profile.getSubNode('BOX'),
                        top=box.scrollTop(), h=box.scrollHeight(),
                        n = linb.use(src).offsetTop();

                    if(n<top || n>top+h)
                        linb.use(src).offsetTop(top);

                    linb.use(src).onMouseover();
                },
                onKeydown : function(profile, e, src){
                    var item = profile.getItemByDom(src),
                        items = profile.properties.items,
                        key = linb.Event.getKey(e)[0],
                        itemId = item.id,
                        flag,r,tid,node,t;

                    switch(key){
                        case 'up':
                            r=true;
                            flag=false;
                            _.arr.each(items,function(o,i){
                                if(o.type == 'split')return;
                                if(flag){
                                    tid=o.id;
                                    return r=false;
                                }
                                if(o.id == itemId)flag=true;
                            },null,true);
                            //last
                            if(r)tid=items[items.length-1].id;
                            node = profile.getSubNodeByItemId('ITEM', tid).get(0);
                            break;
                        case 'down':
                            r=true;
                            flag=false;
                            _.arr.each(items,function(o,i){
                                if(o.type == 'split')return;
                                if(flag){
                                    tid=o.id;
                                    return r=false;
                                }
                                if(o.id == itemId)flag=true;
                            });
                            //first
                            if(r)tid=items[0].id;
                            node = profile.getSubNodeByItemId('ITEM', tid).get(0);
                            break;
                        case 'left':
                            if(t=profile.$parentPopMenu){
                                if(t=profile.$parentPopMenu.$highLight)
                                    node = t;
                            }
                            break;
                        case 'right':
                            if((t=profile.$subPopMenuShowed) && t == profile.$allPops[itemId])
                                t.activate();
                            break;
                    }
                     if(node&&node.tagName)try{node.focus()}catch(e){}
                }
            },
            TOP:{
                onMouseover:function(profile){
                    profile.$scrollToTop=true;
                    profile.boxing()._scrollToTop();
                },
                onMouseout:function(profile){
                    profile.$scrollToTop=false;
                    profile.$scrollStep=null;
                },
                onClick:function(profile){
                    profile.$scrollStep=1000;
                }
            },
            BOTTOM:{
                onMouseover:function(profile){
                    profile.$scrollTobottom=true;
                    profile.boxing()._scrollToBottom();
                },
                onMouseout:function(profile){
                    profile.$scrollTobottom=false;
                    profile.$scrollStep=null;
                },
                onClick:function(profile){
                    profile.$scrollStep=1000;
                }
            },
            ITEMS:{
                beforeKeydown:function(profile, e){
                    var key=linb.Event.getKey(e)[0];
                    if(key=='tab' || key=='enter')
                        return true;
                    else if(key=='esc'){
                        //top
                        do{
                            profile.boxing().hide();
                        }while(profile = profile.$parentPopMenu)

                        return false;
                    }else return false;
                }
            },
            BORDER:{
                onMouseout:function(profile, e, src){
                    profile.box._mouseout(profile, e, src);
                }
            }
        },
        DataModel:({
            dock:null,
            tabindex:null,
            tips:null,
            border:null,
            resizer:null,

            shadow:true,
            _maxHeight:260,
            _maxWidth:300,
            left:-10000,

            hideAfterClick:true,

            autoHide:false,

            height:100,
            //opera needs more space for initialize
            width:300,
            position:'absolute',
            $hborder:1,
            $vborder:1
        }),
        EventHandlers:{
            onShowSubMenu:function(profile, item, src){},
            beforeHide:function(profile){},
            onHide:function(profile){},
            onMenuSelected:function(profile, item, src){}
        },
        RenderTrigger:function(){
            this.boxing()._adjustSize();
        },
        _mouseout:function(profile, e){
            if(profile.properties.autoHide){
                var p1=linb.Event.getPos(e),
                    size, p2, b;
                _.arr.each(profile.$popGrp,function(o){
                    o=linb([o]);
                    p2=o.offset();
                    size=o.cssSize();
                    if(p1.left>p2.left && p1.top>p2.top && p1.left<p2.left+size.width && p1.top<p2.top+size.height)
                        return b=1;
                });
                if(!b){
                    while(b=profile.$parentPopMenu)profile=b;
                    profile.boxing().hide();
                    profile.$popGrp.length=0;
                }
            }
        },
        _prepareItem:function(profile, item){
            item.add = item.add || '';
            item.displayAdd = item.add?'':'display:none';
            item.tagClass = item.sub?'':'display:none';

            item.imageDisplay=true;

            item.type=item.type||'button';
            if(item.type=='checkbox'){
                item.checkboxCls =profile.getClass('CHECKBOX', item.value?'-checked':'');
            }
        },

        _onresize:function(profile,width,height){
            var size = arguments.callee.upper.apply(this,arguments);
            profile.getSubNode('BOX').cssSize(size);
        }
    }
});
Class("linb.UI.MenuBar",["linb.UI","linb.absList" ],{
    Instance:{
        updateItem:function(subId,options){
            var self=this,
                profile=self.get(0),
                box=profile.box,
                items=profile.properties.items,
                rst=profile.queryItems(items,function(o){return typeof o=='object'?o.id===subId:o==subId},true,true,true),
                item;
            if(typeof options=='string')options={caption:options};
            if(rst.length){
                rst=rst[0];
                if(typeof rst[0]!='object')
                    item=rst[2][rst[1]]={id:rst[0]};
                else
                    item=rst[0];

                //merge options
                _.merge(item, options, 'all');
                //ensure the original id.
                item.id=subId;

                //the root
                if(items.indexOf(item)!=-1)
                    arguments.callee.upper.apply(this,arguments);
                //try each sub popmenu
                else{
                    _.each(profile.$allPops,function(o){
                        o.updateItem(subId,options);
                    });
                }
            }
            return self;
        },
        _pop:function(id,src){
            var menu, 
                self=this,
                profile=self.get(0),
                pro=profile.properties,
                all='$allPops';
            //hide first
            if(profile.$curPop)self.hide();

            linb.use(src).tagClass('-mousedown');

            profile[all] = profile[all] || {};
            if(!(menu = profile[all][id])){
                var item=profile.getItemByItemId(id),
                    sub = item.sub;
                sub  = sub ||[];

                menu = linb.create('PopMenu',{position:'absolute', items:sub, autoHide:!!pro.autoShowTime});
                profile.getSubNode('POOL').append(menu);

                menu.onHide(function(pro){
                    self.hide(false);
                }).onMenuSelected(function(pro, item, src){
                    return profile.boxing().onMenuSelected(profile, pro, item, src);
                }).onShowSubMenu(function(pro, item, src){
                    return profile.boxing().onShowSubMenu(profile, pro, item, src);
                });
                menu.get(0).$hideMenuPool = profile.getSubNode('POOL');
                menu.get(0)[all] = profile[all];

                profile[all][id] = menu;
            }
            var target = linb(src);
            menu.pop(target, 1, linb(pro.parentID));

            profile.$curPop=id;
            profile.$curElem=src;
        },
        _afterInsertItems:function(){
            this.clearPopCache();
        },
        hide:function(){
            var profile=this.get(0),menu,
            id = profile.$curPop,
            node = profile.$curElem;

            if(menu = profile.$allPops[id]){
                //To avoid trigger recursive call
                if(false!==arguments[0])
                    menu.hide(false);
                // collect
                profile.getSubNode('POOL').append(menu.reBoxing());
                linb([node]).tagClass('-mousedown',false);
            }
            profile.$menuPop=profile.$curPop=profile.$curElem=null;
        },
        clearPopCache:function(){
            var profile=this.get(0);
            if(profile.renderId){
                profile.getSubNode('POOL').empty();
                profile.$allPops=profile.$curPop=profile.$curElem=null;
            }
        }
    },
    Initialize:function(){
        linb.SC('linb.UI.PopMenu');
    },
    Static:{
        Templates:{
            tagName:'div',
            POOL:{
                tagName:'div'
            },
            BORDER:{
                className:'uibg-bar uiborder-outset',
                tagName:'div',
                LIST:{
                    tagName:'div',
                    HANDLER:{
                        style:'{handler}'
                    },
                    ITEMS:{
                        $order:1,
                        text:"{items}"
                    }
                }
            },
            $submap:{
                items:{
                    ITEM:{
                        ITEMI:{
                            ITEMC:{
                                ITEMA:{
                                    tagName:'a',
                                    href :linb.$href,
                                    tabindex: '{_tabindex}',
                                    className:' {typeCls} {disabled}',
                                    ICON:{
                                        $order:1,
                                        className:'ui-icon {imageClass}',
                                        style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                                    },
                                    CAPTION:{
                                        $order:2,
                                        text : '{caption}',
                                        style:'{captionDisplay}'
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        Appearances:{
            KEY:{
                'font-size':0,
                'line-height':0,
                position:'absolute',
                left:0,
                top:0
            },
            POOL:{
                width:0,
                height:0,
                visibility:'hidden',
                position:'absolute',
                left:'-10000px'
            },
            BORDER:{
                left:0,
                top:0,
                'font-size':0,
                'line-height':0
            },
            HANDLER:{
                height:'22px',
                width:'7px',
                background: linb.UI.$bg('handler.gif', ' left top', true),
                cursor:'move',
                'vertical-align':'middle'
            },
            LIST:{
                padding:'2px'
            },
            ITEMS:{
                'vertical-align':'middle'
            },
            'LIST-disabled':{
                'background-color':'#E4E4E4'
            },
            'ITEM-mouseover, ITEM-mouseover ITEMI, ITEM-mouseover ITEMC, ITEM-mousedown, ITEM-mousedown ITEMI, ITEM-mousedown ITEMC':{
                background:linb.UI.$bg('button.gif', 'no-repeat',true)
            },
            ITEM:{
                height:'22px',
                'white-space': 'nowrap',
                'vertical-align':'top',
                overflow:'hidden',
                margin:'0  3px 0 3px',
                'padding-right':'6px',
                'font-size':0,
                'line-height':0
            },
            'ITEM *':{
                cursor:'pointer'
            },
            ITEMI:{
                height:'22px',
                'padding-left':'6px',
                'vertical-align':'top'
            },
            ITEMC:{
                height:'22px',
                'padding-top':'3px',
                'vertical-align':'top'
            },
            ITEMA:{
                display:linb.$inlineBlock
            },
            'ITEM-mouseover':{
                $order:2,
                'background-position':'right -90px'
            },
            'ITEM-mousedown':{
                $order:3,
                'background-position':'right -180px'
            },
            'ITEM-mouseover ITEMI':{
               $order:2,
                'background-position':'left -150px'
            },
            'ITEM-mousedown ITEMI':{
                $order:3,
                'background-position':'left -240px'
            },            
            'ITEM-mouseover ITEMC':{
                $order:2,
                'background-position':'left -120px',
                'background-repeat': 'repeat-x'
            },
            'ITEM-mousedown ITEMC':{
                $order:3,
                'background-position':'left -210px',
                'background-repeat': 'repeat-x'
            },            
            CAPTION:{
                'font-size':'12px',
                'line-height':'14px',
                'vertical-align':'middle'
            }
        },
        Behaviors:{
            ITEM:{
                onMouseover:function(profile, e, src){
                    var p = profile.properties, ns=src;
                    if(p.disabled)return;
                    var item = profile.getItemByDom(src),
                        itemId = item.id;
                    if(item.disabled)return;
                    if(profile.$menuPop){
                        if(profile.$menuPop != itemId){
                            linb.use(ns).tagClass('-mousedown');
                            //show current popmenu
                            profile.boxing()._pop(itemId, ns);
                            profile.$menuPop = itemId;
                        }
                    }else{
                        linb.use(ns).tagClass('-mouseover');

                        if(p.autoShowTime)
                            _.resetRun(profile.$linbid+':autoShowTime', function(){
                                profile.boxing()._pop(itemId, ns);
                            },p.autoShowTime);
                    }
                },
                onMouseout:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled)return;
                    var item = profile.getItemByDom(src);
                    if(item.disabled)return;

                    linb.use(src).tagClass('-mouseover',false);

                    if(p.autoShowTime){
                        var pop = profile.$allPops;
                        if(pop=pop && pop[profile.$curPop]){
                            var node=pop.get(0).getRoot(),
                                p1=linb.Event.getPos(e),
                                size=node.cssSize(),
                                add=3,
                                p2=node.offset();

                            if(p1.left>p2.left && p1.top>p2.top-add && p1.left<p2.left+size.width && p1.top<p2.top+size.height){}else
                                pop.hide();
                        }
                        _.resetRun(profile.$linbid+':autoShowTime', null);
                    }
                },
                onMousedown:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled)return;
                    var item = profile.getItemByDom(src),
                        itemId = item.id;
                    if(item.disabled)return;
                    if(profile.$menuPop){
                        profile.$menuPop=null;
                        profile.boxing().hide(itemId);
                     }else{
                        profile.$menuPop=itemId;
                        profile.boxing()._pop(itemId, src);

                        //stop bubble to document.body
                        //popmenu will add blue trigger to document.body.beforeMousedown
                        return false;
                     }
                },
                onKeydown:function(profile, e, src){
                    var keys=linb.Event.getKey(e), key = keys[0], shift=keys[2],
                    cur = linb(src),
                    first = profile.getRoot().nextFocus(true, true, false),
                    last = profile.getRoot().nextFocus(false, true, false);

                    switch(linb.Event.getKey(e)[0]){
                        case 'tab':
                            if(shift){
                                if(cur.get(0)!=first.get(0)){
                                    first.focus();
                                    return false;
                                }
                            }else{
                                if(cur.get(0)!=last.get(0)){
                                    last.focus();
                                    return false;
                                }
                            }
                            break;
                        case 'left':
                        case 'up':
                            var next = cur.nextFocus(false, true, false);
                            if(cur.get(0)==first.get(0))
                                last.focus();
                            else
                                cur.nextFocus(false);
                            return false;
                            break;
                        case 'right':
                        case 'down':
                            var next = cur.nextFocus(true, false, false);
                            if(cur.get(0)==last.get(0))
                                first.focus();
                            else
                                cur.nextFocus();
                            return false;
                            break;
                        case 'enter':
                            cur.onMousedown();
                            return false;
                            break;
                    }
                },
                onClick:function(){
                    return false;
                }
            }
        },
        DataModel:{
            listKey:null,

            //can't change height
            height:{
                ini:'auto',
                readonly:true
            },
                
            width:'auto',
            parentID:'',
            $hborder:1,
            $vborder:1,
            left:0,
            top:0,

            autoShowTime:200,

            handler:{
                ini:true,
                action:function(v){
                    this.getSubNode('HANDLER').css('display',v?'':'none');
                }
            },
            position:'absolute',
            dock:{
                ini:'top',
                listbox:['top','bottom']
            }
        },
        EventHandlers:{
            onShowSubMenu:function(profile, popProfile, item, src){},
            onMenuSelected:function(profile, popProfile, item, src){}
        },
        RenderTrigger:function(){
            if(this.properties.disabled)this.boxing().setDisabled(true,true);
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile);
            data.handler = data.handler?'':'display:none';
            return data;
        }
    }
});

Class("linb.UI.ToolBar",["linb.UI","linb.absList"],{
    Instance:{
        updateItem:function(subId,options){
            if(options.type){
                return arguments.callee.upper.apply(this,[subId,options,'items.sub']);
            }else{
                var self=this,
                    profile=self.get(0),
                    box=profile.box,
                    items=profile.properties.items,
                    rst=profile.queryItems(items,function(o){return typeof o=='object'?o.id===subId:o==subId},true,true,true),
                    item,n1,n2,t;
                if(_.isStr(options))options={caption:options};
                //ensure the original id
                delete options.id;
                delete options._pid;
                if(rst.length){
                    rst=rst[0];
                    if(item=rst[0]){
                        //in dom already?
                        n1=profile.getSubNodeByItemId('ICON',subId);
                        n2=profile.getSubNodeByItemId('CAPTION',subId);
    
                        if('value' in options && options.value!=item.value)
                            profile.getSubNodeByItemId('BTN',subId).tagClass('-checked', !!options.value);
                        if('caption' in options&& options.caption!=item.caption)
                            n2.html(options.caption);
                        if('image' in options&& options.image!=item.image)
                            n1.css('background-image',options.image);
                        if('imagePos' in options&& options.imagePos!=item.imagePos)
                            n1.css('background-position',options.imagePos);
                        if('imageClass' in options&& options.imageClass!=item.imageClass){
                            if(item.imageClass)
                                n1.removeClass(item.imageClass);
                            if(options.imageClass)
                                n1.addClass(options.imageClass);
                        }
    
                        //merge options
                        _.merge(item, options, 'all');
                    }
                }
                return self;
            }
        },
        showItem:function(itemId, value){
            return this.each(function(profile){
                profile.getItemByItemId(itemId).visible=value!==false;
                profile.getSubNodeByItemId('ITEM', itemId).css('display',value===false?'none':'');
            });
        },
        showGroup:function(grpId, value){
            return this.each(function(profile){
                _.arr.each(profile.properties.items,function(o){
                    if(o.id==grpId){
                        o.visible=value!==false;
                        return false;
                    }
                });
                profile.getSubNodeByItemId('GROUP', grpId).css('display',value===false?'none':'');
                linb.UI.$dock(profile,true,true);
            });
        }
    },
    Static:{
        _ITEMKEY:'GROUP',
        Templates:{
            tagName:'div',
            ITEMS:{
                className:'uibg-bar uiborder-outset',
                tagName:'div',
                style:'{mode}',
                text:'{items}'
            },
            $submap:{
                items:{
                    GROUP:{
                        className:'{groupClass}',
                        style:'{grpDisplay} {groupStyle}',
                        HANDLER:{
                            style:'{mode2}'
                        },
                        LIST:{
                            $order:1,
                            tagName:'text',
                            text:'{sub}'
                        }
                    }
                },
                'items.sub':{
                    ITEM:{
                        style:'{itemDisplay}',
                    //for firefox2 image in -moz-inline-box cant change height bug
                        IBWRAP:{
                            tagName:'div',
                            SPLIT:{
                                style:'{splitDisplay}'
                            },
                            LABEL:{
                                className:" {disabled}",
                                style:'{labelDisplay}',
                                text:'{label}'
                            },
                            BTN:{
                                className:'ui-btn {itemClass}',
                                style:'{itemStyle} {boxDisplay}',
                                BTNI:{
                                    className:'ui-btni',
                                    BTNC:{
                                        className:'ui-btnc',
                                        BOX:{ 
                                            tagName:'a',
                                            href:linb.$href,
                                            tabindex: '{_tabindex}',
                                            BOXWRAP:{
                                                tagName:'div',
                                                ICON:{
                                                    $order:1,
                                                    className:'ui-icon {imageClass}',
                                                    style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                                                },
                                                CAPTION:{
                                                    $order:2,
                                                    text : '{caption}',
                                                    className:" {disabled}",
                                                    style:'{captionDisplay}'
                                                },
                                                DROP:{
                                                    $order:3,
                                                    style:'{dropDisplay}'
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        },
        Appearances:{
            KEY:{
                'font-size':0,
                'line-height':0,
                position:'absolute',
                left:0,
                top:0
            },
            ICON:{
                margin:0,
                'vertical-align':'top'
            },
            ITEMS:{
                display:'block',
                'padding-bottom':'1px',
                'font-size':0,
                'line-height':0
            },
            HANDLER:{
                height:'22px',
                width:'7px',
                background: linb.UI.$bg('handler.gif', ' left top', true),
                cursor:'move',
                'vertical-align':'middle'
            },
            GROUP:{
                'font-size':0,
                'line-height':0,
                position:'relative',
                padding:'2px 4px 0px 2px',
                'vertical-align':'middle'
            },
            ITEM:{
                'vertical-align':'middle',
                padding:'1px'
            },
            'BTNC a':{
                padding:0
            },
            'SPLIT':{
                $order:1,
                width:'6px',
                height:'19px',
                'vertical-align':'middle',
                background: linb.UI.$bg('split_vertical.gif', 'repeat-y left top', true)
            },
            BTN:{
                'padding-right':'3px'
            },
            BTNI:{
                'padding-left':'3px'
            },
            DROP:{
                width:'14px',
                height:'16px',
                'vertical-align':'top',
                background: linb.UI.$bg('drop.gif', 'no-repeat left center', 'Button')
            },
            'BTN-mouseover DROP':{
                $order:2,
                'background-position':'-16px center'
            },
            'BTN-mousedown DROP, BTN-checked DROP':{
                $order:2,
                'background-position':'-32px center'
            },
            'LABEL, CAPTION':{
                height:'16px',
                'vertical-align':'middle',
                'margin-left':'2px',
                'margin-right':'2px',
                 cursor:'default',
                 'font-size':'12px'
            },
            LABEL:{
                'padding-top':'3px'
            }
        },
        Behaviors:{
            HoverEffected:{BTN:['BTN']},
            ClickEffected:{BTN:['BTN']},
            BTN:{
                onClick:function(profile, e, src){
                    if(profile.properties.disabled)return;
                    var id2=linb.use(src).parent(3).id(),
                        item2 = profile.getItemByDom(id2);
                    if(item2.disabled)return;

                    var item = profile.getItemByDom(src);
                    if(item.disabled)return;

                    linb.use(src).focus();
                    if(item.statusButton)
                        linb.use(src).tagClass('-checked',item.value=!item.value);

                    profile.boxing().onClick(profile, item, item2, e, src);
                    return false;
                }
            }
        },
        DataModel:{
            listKey:null,
            height:{
                ini:'auto',
                readonly:true
            },
            width:'auto',

            left:0,
            top:0,

            handler:{
                ini:true,
                action:function(v){
                    this.getSubNode('HANDLER',true).css('display',v?'':'none');
                }
            },
            position:'absolute',
            hAlign:{
                ini:'left',
                listbox:['left','center','right'],
                action:function(v){
                    this.getSubNode('ITEMS', true).css('textAlign', v);
                }
            },
            dock:{
                ini:'top',
                listbox:['top','bottom']
            }
        },
        EventHandlers:{
            onClick:function(profile, item, group, e, src){}
        },
        _adjustItems:function(arr){
            if(!arr)arr=[_()+''];
            if(_.isStr(arr))arr=[arr];

            var a=_.copy(arr),m;
            _.arr.each(a,function(o,i){
                if(typeof o== 'object'){
                    //copy group
                    a[i]=_.copy(o);
                    a[i].sub=[];
                    //copy sub(tool item)
                    if(o.sub)
                        _.arr.each(o.sub,function(v){
                            a[i].sub.push(_.copy(v));
                        });
                }
            });
            return a;
        },
        _prepareData:function(profile){
            var d=arguments.callee.upper.call(this, profile);
            var p = profile.properties;

            d.mode = p.hAlign=='right'?'text-align:right;':'';

            return d;
        },
        _prepareItem:function(profile, oitem, sitem, pid,  mapCache, serialId){
            var dn='display:none', 
                fun=function(profile, dataItem, item, pid, mapCache,serialId){
                    var id=dataItem[linb.UI.$tag_subId]=typeof serialId=='string'?serialId:('a_'+profile.pickSubId('aitem')), t;
                    if(typeof item=='string')
                        item={caption:item};
    
                    if(false!==mapCache){
                        profile.ItemIdMapSubSerialId[item.id] = id;
                        profile.SubSerialIdMapItem[id] = item;
                    }
    
                    if(t=item.object){
                        t=dataItem.object=t['linb.absBox']?t.get(0):t;
                        //relative it.
                        if(t['linb.UIProfile']){
                            t.properties.position='relative';
                            if(!t.CS.KEY)t.CS.KEY='';
                            t.CS.KEY ='vertical-align:middle;margin-left:4px;' + t.CS.KEY;
                        }
                        item.$linbid=t.$linbid;
                        t.$item=item;
                        t.$holder=profile;
                        if(!profile.$attached)profile.$attached=[];
                        profile.$attached.push(t);
                    }else{
                        if(item.type=='split')item.split=true;
                        linb.UI.adjustData(profile,item, dataItem);
    
                        if(!item.caption)item.caption="";

                        dataItem.splitDisplay=dataItem.split?'':dn;
                        dataItem.labelDisplay=dataItem.label?'':dn;
                        dataItem.captionDisplay=dataItem.caption?'':dn;
                        dataItem.dropDisplay=item.dropButton?'':dn;
                        dataItem.boxDisplay= (!dataItem.split && (dataItem.caption || dataItem.image || dataItem.imageClass))?'':dn;
                    }
                    dataItem.itemDisplay=item.visible===false?dn:'';
                    item._pid=pid;
                };

            if(pid){
                fun(profile,oitem,sitem,pid,mapCache,serialId);
            }else{
                var arr=[],
                dataItem,
                a=sitem.sub||[];

                pid=sitem.id;
                oitem.mode2 = profile.properties.handler ? '' : dn;
                oitem.grpDisplay=sitem.visible===false?dn:'';
                oitem.sub = arr;
                _.arr.each(a,function(item){
                    dataItem={id: item.id};
                    fun(profile,dataItem,item,pid,mapCache,serialId);
                    arr.push(dataItem);
                });
            }
        }
    }
});
Class("linb.UI.Layout",["linb.UI", "linb.absList"],{
    Instance:{
        getPanel:function(subId){
            return this.get(0).getSubNodeByItemId('PANEL', subId);
        },
        append:function(target, subId){
            var pro=this.get(0);
            return arguments.callee.upper.call(this, target, subId||'main');
        },
        fireCmdClickEvent:function(subId){
            this.getSubNodeByItemId('CMD', subId).onMousedown();
            return this;
        }
    },
    Static:{
        Templates:{
            tagName:'div',
            style:'{_style}',
            text:"{items}",
            $submap:{
                items:{
                    ITEM:{
                        tagName:'div',
                        className:'{cls1} {itemClass}',
                        style:'{size};{itemStyle}',
                        MOVE:{
                            $order:0,
                            tagName:'div',
                            className:'uibg-bar {cls2} ',
                            style:'{display}'
                        },
                        CMD:{
                            $order:1,
                            tagName:'div',
                            style:'{cmdDisplay}',
                            className:'{cls3} '
                        },
                        PANEL:{
                            tagName:'div',
                            className:'uibg-base',
                            style:'position:absolute;left:0;top:0;',
                            text:linb.UI.$childTag
                        }
                    }
                }
            }
        },
        Appearances:{
            '.setting-linb-layout':{
                width:'9px'
            },
            KEY:{
                position:'absolute',
                overflow:'hidden',
                left:0,
                top:0,
                'font-size':linb.browser.ie?0:null,
                'line-height':linb.browser.ie?0:null
            },
            MOVE:{
                $order:0,
                position:'absolute',
                'z-index':'10',
                'font-size':linb.browser.ie?0:null,
                'line-height':linb.browser.ie?0:null
            },
            'MOVE-mouseover':{
                $order:1,
                'background-color':'#C8E1FA'
            },
            CMD:{
                position:'absolute',
                cursor:'pointer',
                'z-index':'20',
                'font-size':linb.browser.ie?0:null,
                'line-height':linb.browser.ie?0:null
            },
            ITEM:{
                position:'absolute',
                "z-index":1,
                overflow:'hidden',
                'border-width':linb.browser.opr?'0px':null,
                'font-size':linb.browser.ie?0:null,
                'line-height':linb.browser.ie?0:null
            },
            PANEL:{
                position:'absolute',
                overflow:'hidden',
                /*for opera, opera defalut set border to 3 ;( */
                'border-width':linb.browser.opr?'0px':null,
                'font-size':linb.browser.ie?0:null,
                'line-height':linb.browser.ie?0:null
            },
            'ITEM-MAIN':{
                left:0,
                right:0,
                top:0,
                bottom:0
            },
            'ITEM-TOP, ITEM-BOTTOM':{
                left:0,
                right:0
            },
            'ITEM-LEFT, ITEM-RIGHT':{
                top:0,
                bottom:0
            },
            'MOVE-TOP, MOVE-BOTTOM':{
                width:'100%',
                height:'7px',
                cursor:'n-resize',
                'border-top':'solid 1px #c8e1fa',
                'border-bottom':'solid 1px #648cb4'
            },
            'MOVE-LEFT, MOVE-RIGHT':{
                height:'100%',
                width:'7px',
                cursor:'w-resize',
                'border-left':'solid 1px #c8e1fa',
                'border-right':'solid 1px #648cb4'
            },
            'MOVE-TOP':{
                bottom:0
            },
            'MOVE-BOTTOM':{
                top:0
            },
            'MOVE-LEFT':{
                right:0
            },
            'MOVE-RIGHT':{
                left:0
            },
            'CMD-TOP, CMD-BOTTOM, CMD-LEFT, CMD-RIGHT':{
                background: linb.UI.$bg('icons.gif', 'no-repeat', true)
            },
            'CMD-TOP':{
                $order:1,
                left:'50%',
                'margin-left':'-20px',
                bottom:0,
                width:'40px',
                height:'9px',
                'background-position':'-360px -232px'
            },
            'CMD-BOTTOM':{
                $order:1,
                left:'50%',
                'margin-left':'-20px',
                top:0,
                width:'40px',
                height:'9px',
                'background-position':'-360px -258px'
            },
            'CMD-LEFT':{
                $order:1,
                top:'50%',
                'margin-top':'-20px',
                right:0,
                height:'40px',
                width:'9px',
                'background-position':'-310px -240px'
            },
            'CMD-RIGHT':{
                $order:1,
                top:'50%',
                'margin-top':'-20px',
                left:0,
                height:'40px',
                width:'9px',
                'background-position':'-336px -240px'
            },
            'CMD-TOP-mouseover':{
                $order:2,
                'background-position':'-360px -245px'
            },
            'CMD-BOTTOM-mouseover':{
                $order:2,
                'background-position':'-360px -271px'
            },
            'CMD-LEFT-mouseover':{
                $order:2,
                'background-position':'-323px -240px'
            },
            'CMD-RIGHT-mouseover':{
                $order:2,
                'background-position':'-349px -240px'
            },

            'MOVE-MAIN':{
                $order:5,
                display:'none'
            },
            'CMD-MAIN':{
                $order:5,
                display:'none'
            }
        },
        Behaviors:{
            DropableKeys:['PANEL'],
            HoverEffected:{MOVE:'MOVE',CMD:'CMD'},
            onSize:linb.UI.$onSize,
            MOVE:{
                onMousedown:function(profile, e, src){
                    var itemId = profile.getSubId(src),
                        item = profile.getItemByDom(src);
                    if(item.hide)return;

                    var main = profile.getItemByItemId('main'),
                        o=profile.getSubNode('ITEM', itemId),
                        m=profile.getSubNodeByItemId('ITEM', 'main'),
                        cursor=linb.use(src).css('cursor'),
                        t=profile.properties,
                        h,w,mh,mw,offset1,offset2;

                    profile.pos=item.pos;

                    if(t.type=='vertical'){
                        h = profile._cur = o.height();
                        mh = m.height();
                        if(item.pos=='before'){
                            offset1 = h - item.min;
                            offset2 = item.max?Math.min(parseInt(item.max)-h, (mh-main.min)):(mh-main.min);
                        }else{
                            offset1 = item.max?Math.min(parseInt(item.max)-h, (mh-main.min)):(mh-main.min);
                            offset2 = h - item.min;
                        }

                        linb.use(src).startDrag(e,{
                            dragType:'copy',
                            targetReposition:false,
                            verticalOnly:true,
                            maxTopOffset:offset1,
                            maxBottomOffset:offset2,
                            dragCursor:cursor
                        });
                    }else{
                        w = profile._cur = o.width();
                        mw = m.width();
                        if(item.pos=='before'){
                            offset1 = w - item.min;
                            offset2 = item.max?Math.min(parseInt(item.max)-w, (mw-main.min)):(mw-main.min);
                        }else{
                            offset1 = item.max?Math.min(parseInt(item.max)-w, (mw-main.min)):(mw-main.min);
                            offset2 = w - item.min;
                        }

                        linb.use(src).startDrag(e,{
                            dragType:'copy',
                            targetReposition:false,
                            horizontalOnly:true,
                            maxLeftOffset:offset1,
                            maxRightOffset:offset2,
                            dragCursor:cursor
                        });
                    }

                    profile._limited=0;
                },
                onDrag:function(profile, e, src){
                    var t=profile.properties,
                        d=linb.DragDrop,
                        p=linb.DragDrop._profile,
                        b=0;
                    if(t.type=='vertical'){
                        if((p.y<=p.restrictedTop) || (p.y>=p.restrictedBottom))b=true;
                    }else{
                        if(p.x<=p.restrictedLeft || p.x>=p.restrictedRight)b=true;
                    }

                    if(b){
                        if(!profile._limited){
                            profile._bg=p.proxyNode.css('backgroundColor');
                            p.proxyNode.css('backgroundColor','#ff6600');
                            profile._limited=true;
                        }
                    }else{
                        if(profile._limited){
                            p.proxyNode.css('backgroundColor',profile._bg);
                            profile._limited=0;
                        }
                    }

                },
                onDragstop:function(profile, e, src){
                    var t=profile.properties,
                        o=linb.use(src).parent(),
                        r=profile.getRoot(),
                        item = profile.getItemByDom(src);

                    //add offset and refresh
                    if(t.type=='vertical'){
                        //use size to ignore onresize event once
                        o.height(item.size =  profile._cur + (profile.pos=='before'?1:-1)*linb.DragDrop.getProfile().offset.y);
                        linb.UI.$tryResize(profile,null,r.height(),true);
                    }else{
                        o.width(item.size = profile._cur + (profile.pos=='before'?1:-1)*linb.DragDrop.getProfile().offset.x);
                        //use size to ignore onresize event once
                        linb.UI.$tryResize(profile,r.width(),null,true);
                    }
                    profile._limited=0;
                }
            },
            CMD:{
                onMousedown:function(profile, e, src){
                    var t=profile.properties,
                        itemId = profile.getSubId(src),
                        item = profile.getItemByDom(src),
                        r=profile.getRoot(),
                        main = profile.getItemByItemId('main'),
                        m=profile.getSubNodeByItemId('ITEM', 'main'),
                        o = profile.getSubNode('ITEM',itemId),
                        panel = profile.getSubNode('PANEL',itemId),
                        move = profile.getSubNode('MOVE',itemId),
                        _handlerSize=linb.UI.$getCSSValue('setting-linb-layout','width');

                    if(t.type=='vertical'){
                        // restore resize mode
                        if(item.hide){
                            if(item.size <= m.height() - main.min + _handlerSize){
                                //restore h
                                o.height(item.size);
                                panel.show();

                                item.hide=false;
                                //set appearance
                                if(item.pos=='before')
                                    linb.use(src).replaceClass(/bottom/g,'top');
                                else
                                    linb.use(src).replaceClass(/top/g,'bottom');

                                //hidden 'move'
                                if(!item.locked)move.css('cursor','n-resize');
                                profile.getSubNode('MOVE').tagClass('-checked',false);
                            }else
                                linb.message('no enough space!');
                        // to min and fix mode
                        }else{
                            o.height(_handlerSize);
                            panel.hide();

                            item.hide=true;
                            if(item.pos=='before')
                                linb.use(src).replaceClass(/top/g,'bottom');
                            else
                                linb.use(src).replaceClass(/bottom/g,'top');

                            if(!item.locked)
                                move.css('cursor','default');
                            profile.getSubNode('MOVE').tagClass('-checked');
                        }
                        linb.UI.$tryResize(profile,null,r.height(),true);
                    }else{
                        if(item.hide){
                            if(item.size <= m.width()-main.min + _handlerSize){
                                o.width(item.size);
                                panel.show();
                                item.hide=false;
                                if(item.pos=='before')
                                    linb.use(src).replaceClass(/right/g,'left');
                                else
                                    linb.use(src).replaceClass(/left/g,'right');

                                if(!item.locked)move.css('cursor','w-resize');
                                profile.getSubNode('MOVE').tagClass('-checked',false);
                            }else
                                linb.message('no enough space!');
                        }else{
                            o.width(_handlerSize);
                            panel.hide();
                            item.hide=true;
                            if(item.pos=='before')
                                linb.use(src).replaceClass(/left/g,'right');
                            else
                                linb.use(src).replaceClass(/right/g,'left');


                            if(!item.locked)
                                move.css('cursor','default');
                            profile.getSubNode('MOVE').tagClass('-checked');
                        }
                        linb.UI.$tryResize(profile,r.width(),null,true);
                    }

                    return false;
                }
            }
        },
        DataModel:{
            disabled:null,
            position:'absolute',
            type:{
                listbox:['vertical', 'horizontal'],
                ini:'vertical',
                action:function(value, ovalue){
                    if(value != ovalue){
                        var self=this, auto='auto',
                        nodes2 = self.getSubNode('ITEM',true),
                        nodes1 = self.getSubNode('MOVE',true),
                        nodes3 = self.getSubNode('CMD',true);
                        nodes1.merge(nodes2).merge(nodes3);

                        if(value=='vertical'){
                            nodes1.replaceClass(/(-left)(\b)/ig,'-top$2');
                            nodes1.replaceClass(/(-right)(\b)/ig,'-bottom$2');
                            nodes2.each(function(o){
                                linb(o).height(linb(o).width());
                            })
                            .cssRegion({left:0,top:auto,right:auto,bottom:auto})
                            ;
                        }else{
                            nodes1.replaceClass(/(-top)(\b)/ig,'-left$2');
                            nodes1.replaceClass(/(-bottom)(\b)/ig,'-right$2');
                            nodes2.each(function(o){
                                linb(o).width(linb(o).height());
                            })
                            .cssRegion({left:auto,top:0,right:auto,bottom:auto})
                            ;

                        }

                        var size = self.getRoot().cssSize();
                        linb.UI.$tryResize(self, size.width, size.height,true);
                    }
                }
            },
            dock:'fill',
            listKey:null,
            width:200,
            height:200,

            items:{
                ini:[],
                set:function(value){
                   var o=this;
                    if(o.renderId){
                        var box = o.boxing(),
                            temp = linb.$getGhostDiv(),
                            //keep children
                            children = _.copy(o.children),
                            p,vv
                        ;
                        o.children.length=0;
                        _.arr.each(children,function(o){
                            //for flush dock
                            delete o[0].$dockParent;
                            //keep it in dom
                            temp.appendChild(o[0].getRootNode());
                        });

                        //bak value

                        //clear all
                        box.clearItems();

                        //set items
                        //for adjust 'main'
                        vv = o.box._prepareV(o, value);
                        //inset items
                        box.insertItems(vv);

                        //restore children
                        _.arr.each(children,function(v){
                            box.append.apply(box,v);
                        });

                        //clear
                        temp.innerHTML='';
                        //set value

                        //resize
                        var size = o.getRoot().cssSize();
                        linb.UI.$tryResize(o, size.width, size.height,true);
                    }else
                        o.properties.items = _.copy(value);
                }
            }
        },
        _prepareV:function(profile, items){
            var main, before=[], after=[];
            //arrage items
            _.arr.each(items,function(o){
                if(o.id=='main'){
                    main=o
                }else{
                    if(o.pos=='before')
                        before.push(o);
                    else{
                        o.pos='after';
                        after.push(o);
                    }
                }
            });

            main = main || {};
            main.id = 'main';
            main.min = main.min || 10;

            //reset items
            items.length = 0;
            _.arr.insertAny(items, before,0);
            _.arr.insertAny(items, main);
            _.arr.insertAny(items, after);

            //set the items to default value
            _.arr.each(items,function(o){
                o.id = _.isStr(o.id)?o.id:profile.$linbid+':'+_.id();
                o.min = o.min || 10;
                if(o.id!='main'){
                    o.size = parseInt(o.size) || 20;
                    o.locked= typeof o.locked=='boolean'?o.locked:false;
                    o.hide = typeof o.hide=='boolean'?o.hide:false;
                    o.cmd = typeof o.cmd=='boolean'?o.cmd:false;
                }
            });
            return items;
        },
        _prepareData:function(profile){
            var prop=profile.properties;
            if(!prop.items || prop.items.constructor != Array)
            prop.items = _.clone([
                {id:'before', pos:'before', locked:false, size:60, min: 50, max:200},
                {id:'after',pos:'after', locked:false, size:60, min: 50, max:200}
            ]);

            prop.items = this._prepareV(profile, prop.items);
            return arguments.callee.upper.call(this, profile);
        },
        _prepareItem:function(profile, item){
            var pp=profile.properties;
            if(item.id=='main'){
                item.cls1=profile.getClass('ITEM', '-main');
                item.cls2  = profile.getClass('MOVE', '-main');
                item.cls3  = profile.getClass('CMD', '-main' );
                return;
            }

            if(pp.type=='vertical')
                item.size = 'height:'+item.size+'px';
            else
                item.size = 'width:'+item.size+'px';

            var pos;
            if(pp.type=='vertical'){
                if(item.pos=='before')
                    pos='top';
                else
                    pos='bottom';
            }else{
                if(item.pos=='before')
                    pos='left';
                else
                    pos='right';
            }

            item.cls1  = profile.getClass('ITEM', '-' + pos );
            item.cls2  = profile.getClass('MOVE', '-' + pos );
            item.cls3  = profile.getClass('CMD', '-' + pos );
            item.display = item.locked?'display:none':'';
            item.cmdDisplay = item.cmd?'':'display:none';
        },
        RenderTrigger:function(){
            var t, profile=this;
            _.arr.each(profile.properties.items,function(item){
                if(item.id!='main'){
                    if(item.hide && (t=profile.getSubIdByItemId(item.id))){
                            item.hide=false;
                            profile.getSubNode('CMD',t).onMousedown();
                        }
                }
            });
        },
        _onresize:function(profile,width,height){
            var _t,t=profile.properties, m,n, itemId, temp1,temp2,temp, key=profile.keys.ITEM, panel=profile.keys.PANEL,
            move=profile.getSubNode('MOVE',true),
            _handlerSize=linb.UI.$getCSSValue('setting-linb-layout','width');

            var obj={}, obj2={};
            _.arr.each(t.items,function(o){
                itemId = profile.getSubIdByItemId(o.id);
                obj[itemId] = {};
                obj2[itemId] = {};
            });
            if(t.type!='vertical'){
                if(!_.isNull(width)){
                    //get left
                    temp=temp1=temp2=0;
                    _.arr.each(t.items,function(o){
                        if(o.id=='main')return;
                        itemId = profile.getSubIdByItemId(o.id);
                        if(o.pos=='before'){
                            n=profile.getSubNode('ITEM', itemId);

                            if(o.hide){
                                m=obj2[itemId].width=_handlerSize;
                            }else
                                m= n.width();

                            obj2[itemId].left=temp1;
                            temp1 +=m;
                            obj2[itemId].right='auto';
                            obj[itemId].right='auto';
                            obj[itemId].left=0;
                            obj[itemId].width = m - (o.locked?0:_handlerSize);
                        }
                    });
                    _.arr.each(t.items,function(o){
                        if(o.id=='main')return;
                        itemId = profile.getSubIdByItemId(o.id);
                        if(o.pos=='after'){
                            n =profile.getSubNode('ITEM', itemId);

                            if(o.hide){
                                m=obj2[itemId].width=_handlerSize;
                            }else
                                m= n.width();

                            obj2[itemId].right=temp2;
                            temp2 +=m;
                            obj2[itemId].left='auto';
                            obj[itemId].right=0;
                            obj[itemId].left='auto';
                            obj[itemId].width = m-(o.locked?0:_handlerSize);
                        }
                    },null,true);
                    temp = temp1+temp2;

                    //set main
                    //specify widht/height first,
                    if(width-temp>=0){
                        _t=profile.getSubIdByItemId('main');
                        obj[_t].width=width-temp;
                        obj2[_t].width=width-temp;
                        obj2[_t].left=temp1;
                    }
                }
                if(!_.isNull(height)){
                    _.each(obj,function(o,id){
                        o.height=height;
                        obj2[id].height=height;
                    });
                }
            }else{
                if(!_.isNull(height)){
                    //get top
                    temp=temp1=temp2=0;
                    _.arr.each(t.items,function(o){
                        if(o.id=='main')return;
                        itemId=profile.getSubIdByItemId(o.id);
                        if(o.pos=='before'){
                            n=profile.getSubNode('ITEM', itemId);

                            if(o.hide){
                                m=obj2[itemId].height=_handlerSize;
                            }else
                                m= n.height();
                            obj2[itemId].top=temp1;
                            temp1 += m;
                            obj2[itemId].bottom='auto';
                            obj[itemId].top=0;
                            obj[itemId].bottom='auto';
                            obj[itemId].height=m-(o.locked?0:_handlerSize);
                        }
                    });
                    _.arr.each(t.items,function(o){
                        if(o.id=='main')return;
                        itemId=profile.getSubIdByItemId(o.id);
                        if(o.pos=='after'){
                            n=profile.getSubNode('ITEM', itemId);
                            m=n.height();//offsetHeight();

                            if(o.hide){
                                m=obj2[itemId].height=_handlerSize;
                            }else
                                m= n.height();

                            obj2[itemId].bottom=temp2;
                            temp2 += m;
                            obj2[itemId].top='auto';
                            obj[itemId].bottom=0;
                            obj[itemId].top='auto';
                            obj[itemId].height=m-(o.locked?0:_handlerSize);
                        }
                    },null,true);

                    temp =temp1+temp2;
                    //set main
                    if(height-temp>=0){
                        _t=profile.getSubIdByItemId('main');
                        obj[_t].height=height-temp;
                        obj2[_t].height=height-temp;
                        obj2[_t].top=temp1;
                    }
                }
                if(!_.isNull(width)){
                    _.each(obj,function(o, id){
                        o.width=width;
                        obj2[id].width=width;
                    });
                }
            }

            //collect width/height in size
            _.each(obj2, function(o, id){
                profile.getSubNode('PANEL', id).cssRegion(obj[id], true);
                profile.getSubNode('ITEM', id).cssRegion(obj2[id]);
            });
        }
    }
});
//rowMap => row_SerialIdMapItem
//rowMap2 => row_ItemIdMapSerialId
//colMap => header_SerialIdMapItem
//colMap2 => header_ItemIdMapSerialId
//cellMap => cells_SerialIdMapItem
Class("linb.UI.TreeGrid",["linb.UI","linb.absValue"],{
    Instance:{
        _setCtrlValue:function(value){
            return this.each(function(profile){
                if(!profile.renderId)return;
                if(profile.properties.activeMode=='none')return;

                var box = profile.boxing(),
                    uiv = box.getUIValue(),
                    p = profile.properties,
                    k = p.activeMode=='row'?'CELLS':'CELL',
                    getN = function(k,i){return profile.getSubNode(k,i)},
                    getI = function(i){
                        var map1=profile.rowMap2;
                        if(p.activeMode=='row')
                            return map1[i];
                        else{
                            if(!i)return;
                            var r=i.split('|');
                            return _.get(profile.rowMap,[map1[r[0]],'_cells',r[1]]);
                        }
                    };

                if(p.selMode=='single'){
                    var itemId = getI(uiv);
                    if(uiv && itemId)
                        getN(k,itemId).tagClass('-checked',false);

                    itemId = getI(value);
                    if(itemId)
                        getN(k,itemId).tagClass('-checked');

                    //scroll
                    if(itemId){
                        var o = getN(k,itemId);
                        if(o){
                            var top = o.offsetTop(),
                            items = getN('SCROLL'),
                            sh=items.scrollHeight(),
                            st=items.scrollTop(),
                            hh=items.height()
                            ;
                            if(sh > hh)
                                if(top<st || top>st+hh)
                                    items.scrollTop(top);

                        }
                    }
                }else if(p.selMode=='multi'){
                    uiv = uiv?uiv.split(';'):[];
                    value = value?value.split(';'):[];
                    //check all
                    _.arr.each(uiv,function(o){
                        if(_.arr.indexOf(value,o)==-1)
                            getN(k, getI(o)).tagClass('-checked',false)
                    });
                    _.arr.each(value,function(o){
                        if(_.arr.indexOf(uiv,o)==-1)
                            getN(k, getI(o)).tagClass('-checked')
                    });
                }
            });
        },
        /*insert rows to dom
        arr is formatted properties
        pid,base are item id
        before: insert before?
        */
        _insertRowsToDom:function(profile, arr, pid, base, before){
            //if parent not open, return
            if(pid){
                var parent = profile.rowMap[pid];
                if(parent && !parent._created)return;
            }

            var obj,hw,
                hw=profile.getSubNode('HFCELL').width();
            //give width at here
            _.arr.each(arr,function(o){
                o._row0DfW = hw?('width:'+hw+'px'):'';
                _.arr.each(o.cells,function(v,i){
                    v.width=v._col.width;
                })
            });

            //build dom
            var nodes = profile._buildItems('rows', arr);
            //get base dom
            if(!base){
                //no base add to parent
                if(pid){
                    obj = profile.getSubNode('SUB', pid);
                }else{
                    obj = profile.getSubNode('BODY');
                }
                if(before)
                    obj.prepend(nodes);
                else
                    obj.append(nodes);
            }else{
                //
                obj = profile.getSubNode('ROW', base);
                if(before)
                    obj.addPrev(nodes);
                else{
                    obj.addNext(nodes);
                }
            }

            //add sub
            _.arr.each(arr,function(o){
                o.open=false;
            });

            //clear rows cache
            delete profile.$allrowscache;
        },
        _refreshHeader:function(header){
            var profile=this.get(0),
                pro=profile.properties,
                rows = this.getRows('data');

            _.breakO(profile.colMap,2);

            header=profile.box._adjustHeader(header);

            var arr = profile.box._prepareHeader(profile, header);

            var ol=pro.header.length;
            pro.header = header;
            this.removeAllRows();
            profile.getSubNode('HCELL', true).remove();
            if(arr.length)
                profile.getSubNode('HCELLS').append(profile._buildItems('header', arr));
            if(ol==arr.length && rows.length)
                this.insertRows(rows);
            profile.box._ajdustBody(profile);
        },
        _expendRows:function(rows){
            var self=this;
            if(rows && rows.length)
                _.arr.each(rows,function(o){
                    if(o.sub && o.sub.length && !o.iniFold && !o._checked)
                        self.toggleRow(o.id, true);
                });
        },


        /*rows related*/
        //type: 'original', 'data', 'min'
        getRows:function(type){
            var v=this.get(0).properties.rows;
            if(type=='data')
                return _.clone(v,true);
            else if(type=='min'){
                var a=_.clone(v,true),b;
                _.arr.each(a,function(o,i){
                    _.each(b=a[i]=a[i].cells,function(v,j){
                        b[j] = v.value;
                    });
                });
                return a;
            }else
                return v;
        },
        toggleRow:function(id, expend){
            var profile = this.get(0),
            row = profile.rowMap[profile.rowMap2[id]];
            if(row && row.sub)
                profile.box._setSub(profile, row, typeof expend=="boolean"?expend:!row._checked);
        },
        getRowbyRowId:function(rowId){
            var profile=this.get(0),v=profile.rowMap2[rowId];
            return v?profile.rowMap[v]:null;
        },
        getRowbyCell:function(cell){
            return cell._row;
        },
        updateRow:function(rowId,options){
            var ns=this, orow=ns.getRowbyRowId(rowId);
            if(orow){
                var rid=orow._serialId, t,tt;
                if(!orow)return ns;

                if(typeof options!='object') options={caption:options};
                else _.filter(options,true);
                options.id=rowId;
                if(('group' in options && options.group!=orow.group) ||
                    'cells' in options ||
                    ('sub' in options && !((!options.sub && orow.sub && orow.sub.length==0) || (options.sub && options.sub.length==0 && !orow.sub)))
                ){
                    var id="__special",pid=orow._pid,profile=ns.get(0);
                    orow.id=id;
                    profile.rowMap2[id]=profile.rowMap2[rowId];
                    delete profile.rowMap2[rowId];
                    _.each(profile.colMap,function(o){
                        if(o._cells)
                            delete o._cells[rowId];
                    });
                    orow=_.clone(orow,true);
                    _.merge(orow, options, 'all');
                    if('sub' in options && !options.sub)delete orow.sub;
                    ns.insertRows([orow],pid,id,true);
                    ns.removeRows([id]);
                }else{
                    if('sub' in options){
                        t=ns.getSubNode('FCELLCMD',rid);
                        if(options.sub)
                            t.removeClass('uicmd-empty').addClass('uicmd-toggle2')
                        else
                            t.removeClass('uicmd-toggle2').addClass('uicmd-empty')

                    }

                    if(t=options.height)
                        ns.getSubNode('CELLS',rid).height(t);
                    if(t=options.rowStyle)
                        (tt=ns.getSubNode('CELLS',rid)).attr('style',tt.attr('style')+";"+t);
                    if(t=options.rowClass)
                        ns.getSubNode('CELLS',rid).addClass(t);
                    if(t=options.firstCellStyle)
                        (tt=ns.getSubNode('FCELL',rid)).attr('style',tt.attr('style')+";"+t);
                    if(t=options.firstCellClass)
                        ns.getSubNode('FCELL',rid).addClass(t);

                    if(options.hasOwnProperty('caption'))
                        ns.getSubNode('FCELLCAPTION',rid).get(0).innerHTML=options.caption;
                    if(options.hasOwnProperty('preview')){
                        if(options.preview)
                            ns.getSubNode('PREVIEW',rid).css('display','block').html(options.preview);
                        else
                            ns.getSubNode('PREVIEW',rid).css('display','none');
                    }
                    if(options.hasOwnProperty('summary')){
                        if(options.summary)
                            ns.getSubNode('SUMMARY',rid).css('display','block').html(options.summary);
                        else
                            ns.getSubNode('SUMMARY',rid).css('display','none');
                    }
                    if(options.hasOwnProperty('rowResizer')){
                        t=!!options.rowResizer;
                        ns.getSubNode('FHANDLER',rid).css('display',(options.rowResizer=t)?"block":'none');
                    }

                    _.merge(orow, options, 'all');
                }
            }
            return ns;
        },
        //pid,base are id
        insertRows:function(arr, pid, base ,before){
            var c=this.constructor, profile=this.get(0), pro=profile.properties, row_m=profile.rowMap2, t;
            base = row_m[base];
            if(base){
                t=profile.rowMap[base];
                if(t)pid=t._pid;
            }

            arr=c._adjustRows(arr);

            //prepareData(add links)
            var rows = c._prepareItems(profile, arr, pid),
                tar,
                b=profile.rowMap;

            pid = row_m[pid];
            if(!pid)
                tar = (pro.rows || (pro.rows=[]));
            else
                tar = (b[pid].sub || (b[pid].sub=[]));
            if(!base)
                _.arr.insertAny(tar,arr, before?0:-1);
            else{
                var index = _.arr.subIndexOf(tar,'_serialId', base);
                _.arr.insertAny(tar,arr, before?index:(index+1));
            }

            //insert
            if(rows.length)
                this._insertRowsToDom(profile, rows, pid, base, before);

            if(!pro.iniFold)
                profile.boxing()._expendRows(rows);

            profile.box._asy(profile);
            return this;
        },
        //delete row according to id
        //linb.UI.TreeGrid.getAll().removeRows(['2','5'])
        removeRows:function(ids){
            var self=this,
                profile=self.get(0),
                p=profile.properties,
                cell=profile.cellMap,
                nodes=[],v;

            //get array
            ids = _.isArr(ids)?ids:[ids];
            _.arr.each(ids,function(id){
                //get item id
                if(!(id=profile.rowMap2[id]))return;

                //get row
                var row;
                if(row = profile.rowMap[id]){
                    var tdids = row._cells,
                        rowid = row.id,
                        temp;
                    //for sub delete
                    if(row.sub && _.isArr(row.sub)){
                        var arr=[];
                        _.arr.each(row.sub,function(o){
                            arr.push(o.id)
                        });
                        self.removeRows(arr);
                    }

                    ////delete and clear links
                    _.each(tdids,function(o,i){
                        //clear colMap/properties.header
                        delete cell[o]._col._cells[rowid];
                        _.breakO(cell[o]);
                        //clear cellMap
                        delete cell[o];
                        profile.reclaimSubId(o.slice(2), 'cell');
                    });

                    //clear properties.row array
                    if(temp= row._pid?(temp=profile.rowMap[profile.rowMap2[row._pid]])?temp.sub:null:profile.properties.rows)
                        if(_.isArr(temp))
                            _.filter(temp,function(o){
                                return o._serialId != id;
                            });

                    //clear profile.rowMap2
                    delete profile.rowMap2[rowid];

                    //clear rowMap
                    _.breakO(profile.rowMap[id]);
                    delete profile.rowMap[id];

                    nodes.push(profile.getSubNode('ROW', id).get(0));
                }
                    profile.reclaimSubId(id.slice(2), 'row');
            });
            // clear value
            if(v=p.value){
                if((v=v.split(';')).length>1){
                    _.filter(v,function(o){
                        return _.arr.indexOf(arr,o)==-1;
                    });
                    p.value=v.join(';');
                }else{
                    if(_.arr.indexOf(arr,p.value)!=-1)
                        p.value=null;
                }
            }
            linb(nodes).remove();
            profile.box._asy(profile);
            return self;
        },
        removeAllRows:function(){
            var profile=this.get(0);
            for(var i in profile.cellMap)
                profile.reclaimSubId(i.slice(2), 'cell');
            for(var i in profile.rowMap)
                profile.reclaimSubId(i.slice(2), 'row');

            //remove links
            _.each(profile.colMap,function(o){
                o._cells={};
            });
            _.breakO([profile.rowMap, profile.cellMap],3);

            profile.rowMap={};
            profile.cellMap={};
            profile.rowMap2={};

            profile.properties.rows.length=0;
            if(profile.renderId){
                profile.getSubNode('BODY').empty();
                profile.getSubNode('SCROLL').scrollTop(0).scrollLeft(0);
            }
            return this;
        },
        resetRowValue:function(rowId){
            var profile=this.get(0),row=this.getRowbyRowId(rowId),arr=[];
            _.each(row.cells,function(o){
                if(o._$value!==o.value){
                    o._$value=o.value;
                    arr.push(profile.getSubNode('CELLA',o._serialId).get(0));
                }
            });
            linb(arr).removeClass('ui-dirty');
        },
        getActiveRow:function(){
            var ar,profile=this.get(0);
            if(profile.properties.activeMode!='row')return;
            if(!(ar=profile.$activeRow))return;
            return profile.rowMap[profile.getSubId(ar)];
        },
        setActiveRow:function(rowId){
            var dr, row, profile=this.get(0);
            if(profile.properties.activeMode!='row')return;
            if(!(row=this.getRowbyRowId(rowId)))return;
            if(!(dr=profile.getSubNode('CELLS',row._serialId)).isEmpty())
                profile.box._activeRow(profile, dr.get(0).id);
            return this;
        },

        /*column and header related*/
        //type: 'original', 'data', 'min'
        getHeader:function(type){
            var v=this.get(0).properties.header;
            if(type=='data')
                return _.clone(v,true);
            else if(type=='min'){
                var a=_.clone(v,true),b;
                _.arr.each(a,function(o,i){
                    a[i]=o.id;
                });
                return a;
            }else
                return v;
        },
        updateHeader:function(colId,options){
            var ns=this, colh=ns.getHeaderByColId(colId);
            if(colh){
                var hid=colh._serialId, t;

                if(typeof options!='object') options={caption:options+''};
                else _.filter(options,true);
                delete options.id;

                if(t=options.width){
                    var n=[];
                    n.push(ns.getSubNode('HCELL',hid).get(0));
                    _.each(colh._cells,function(o){
                        n.push(ns.getSubNode('CELL',o).get(0));
                    });
                    linb(n).width(t);
                    ns.constructor._ajdustBody(ns.get(0));
                }

                if(t=options.headerStyle)
                    (tt=ns.getSubNode('HCELL',hid)).attr('style',tt.attr('style')+";"+t);
                if(t=options.headerClass)
                    ns.getSubNode('HCELL',hid).addClass(t);

                if(options.hasOwnProperty('caption'))
                    ns.getSubNode('HCELLCAPTION',hid).get(0).innerHTML=options.caption;
                if('colResizer' in options){
                    t=!!options.colResizer;
                    ns.getSubNode('HHANDLER',hid).css('display',(options.colResizer=t)?"block":'none');
                }

                _.merge(colh, options, 'all');
            }
            return ns;
        },
        getHeaderByColId:function(colId){
            var v=this.get(0).properties.header,
                i=_.arr.subIndexOf(v,"id",colId);
            return v[i];
        },
        getHeaderByCell:function(cell){
            return cell._col;
        },
        showColumn:function(colId, flag){
            return this.each(function(profile){
                var map=profile.colMap2,
                    cols=profile.colMap,
                    col,
                    sid,
                    cells,
                    n=[];
                if(col=cols[sid=map[colId]]){
                    n.push(profile.getSubNode('HCELL',sid).get(0));
                    _.each(col._cells,function(id){
                        n.push(profile.getSubNode('CELL',id).get(0));
                    });
                    linb(n).css('display',(col.visibility=(flag===false?false:true))?'':'none');
                }
                profile.box._ajdustBody(profile);
            });
        },

        /*cell realted*/
        getCellbyRowCol:function(rowId, colId){
            var profile=this.get(0),v;
            v=_.get(profile.rowMap,[profile.rowMap2[rowId], '_cells',colId]);
            return v?profile.cellMap[v]:null;
        },
        updateCellByRowCol:function(rowId, colId, options, dirtyMark){
            var t,self=this,con=self.constructor;
            if(t=con._getCellId(self.get(0), rowId, colId))
                con._updCell(self.get(0), t, options, dirtyMark);
            return self;
        },
        updateCell:function(cellId, options, dirtyMark){
            var self=this;
            self.constructor._updCell(self.get(0),cellId,options, dirtyMark);
            return self;
        },
        editCellbyRowCol:function(rowId, colId){
            var profile=this.get(0),con=profile.box;
            return con._editCell(profile, con._getCellId(profile, rowId, colId));
        },
        getActiveCell:function(){
            var ar,profile=this.get(0);
            if(profile.properties.activeMode!='cell')return;
            if(!(ar=profile.$activeCell))return;
            return profile.cellMap[profile.getSubId(ar)];
        },
        setActiveCell:function(rowId, colId){
            var dr, cell, profile=this.get(0);
            if(profile.properties.activeMode!='cell')return;
            if(!(cell=this.getCellbyRowCol(rowId, colId)))return;
            if(!(dr=profile.getSubNode('CELL',cell._serialId)).isEmpty())
                profile.box._activeCell(profile, dr.get(0).id);
            return this;
        },

        /*others*/
        // reset all cells' value, and clear all dirty mark
        resetGridValue:function(){
            return this.each(function(profile){
                _.each(profile.cellMap,function(v){
                    v._$value=v.value;
                });
                profile.getSubNode('CELLA',true).removeClass('ui-dirty');
            })
        },
        getSubNodeInGrid:function(key, rowId, colId){
            var ns=this,
                t=  (rowId && colId) ? ns.getCellbyRowCol(rowId, colId) :
                    colId ? ns.getHeaderByColId(colId):
                    rowId ? ns.getRowbyRowId(rowId):null;
            return ns.getSubNode(key, (t&&t._serialId)||true);
        }
    },
    Initialize:function(){
        this.addTemplateKeys(['ALT','PROGRESS']);
    },
    Static:{
        Templates:{
            tagName : 'div',
            style:'{_style}',
            BORDER:{
                tagName : 'div',
                BOX:{
                    tagName:'div',
                    HEADER:{
                        $order:0,
                        tagName:'div',
                        style:"{showHeader}",
                        //for scroll performance
                        HI:{
                            tagName:'div',
                            HCELLS:{
                                tagName:'div',
                                style:'{headerHeight};',
                                /*the first col (row handler) in table header*/
                                HFCELL:{
                                    $order:0,
                                    style:'{rowHandlerDisplay};{_row0DfW};',
                                    HFCELLA:{
                                        HHANDLER:{
                                            tagName:'div',
                                            style:'{colDDDisplay}'
                                        },
                                        FHANDLER:{
                                            tagName:'div',
                                            style:'{rowDDDisplay}'
                                        },
                                        HFMARK:{
                                            className:"uicmd-check",
                                            style:'{_rowMarkDisplay}'
                                        },
                                        GRIDCAPTION:{
                                            $order:2,
                                            text:'{gridHandlerCaption}'
                                        }
                                    }
                                },
                                OTHERHCELLS:{
                                    $order:1,
                                    tagName:'text',
                                    text:'{header}'
                                }
                            }
                        }
                    },
                    SCROLL:{
                        $order:1,
                        tagName:'div',
                        className:'uibg-base ',
                        BODY:{
                            tagName:'div',
                            text:'{rows}'
                        }
                    },
                    FOOTER:{
                        $order:2
                    },
                    COLLIST:{
                        tagName:'div'
                    }
                }
            },
            $submap : {
                /*the other header in table header*/
                header:{
                    HCELL:{
                        style:"width:{width}px;",
                        HCELLA:{
                            className:'{headerClass}',
                            style:"{headerStyle}",
                            HCELLCAPTION:{
                                text:"{caption}"
                            },
                            SORT:{
                                style:'{sortDisplay}'
                            },
                            HHANDLER : {
                                $order:2,
                                tagName:'div',
                                style:'{colDDDisplay}'
                            }
                        }
                    }
                },
                rows:{
                    ROW:{
                        tagName:'div',
                        PREVIEW:{
                            $order:1,
                            tagName:'div',
                            style:'{previewDisplay}',
                            text:'{preview}'
                        },
                        CELLS:{
                            $order:2,
                            tagName:'div',
                            className:'{rowCls} {rowClass}',
                            style:'height:{rowHeight}px;{rowStyle}',
                            FCELL:{
                                $order:0,
                                style:'{rowHandlerDisplay};{_row0DfW};{cellStyle}{firstCellStyle}',
                                className:'{cellClass}{firstCellClass}',
                                FCELLA:{
                                    FCELLRULER:{
                                        style:'width:{_rulerW}px'
                                    },
                                    FCELLCMD:{
                                        $order:2,
                                        className:'{subClass}'
                                    },
                                    FHANDLER:{
                                        tagName:'div',
                                        style:'{rowDDDisplay}'
                                    },
                                    FCELLINN:{
                                        $order:3,
                                        ROWNUM:{},
                                        FCELLCAPTION:{
                                            $order:1,
                                            text:'{caption}'
                                        }
                                    },
                                    MARK:{
                                        $order:1,
                                        style:'{_rowMarkDisplay}'
                                    }
                                }
                            },
                            OTHERCELLS:{
                                tagName:'text',
                                $order: 1,
                                text:'{cells}'
                            }
                        },
                        SUB:{
                            $order:3,
                            tagName:'div'
                        },
                        SUMMARY:{
                            $order:4,
                            tagName:'div',
                            style:'{summaryDisplay}',
                            text:'{summary}'
                        }
                    }
                },
                'rows.cells':function(profile,template,v,tag,result){
                    var me=arguments.callee,map=me._m||(me._m={'checkbox':'.checkbox','button':'.button','progress':'.progress'});
                    linb.UI.$doTemplate(profile,template,v,tag+(map[v.type]||'.input'),result)
                 },
                'rows.cells.input':{
                    CELL:{
                        style:'width:{width}px;{cellDisplay};',
                        className:'{cellCls}',
                        CELLA:{
                            tagName:'a',
                            className:'{cellClass}',
                            style:'{bgcolor};{color};{cellStyle}',
                            href :linb.$href,
                            tabindex: '{_tabindex}',
                            text:"{caption}"
                        }
                    }
                },
                'rows.cells.button':{
                    CELL:{
                        style:'width:{width}px;{cellDisplay};',
                        className:'{cellCls}',
                        CELLA:{
                            tagName:'button',
                            className:'{cellClass}',
                            style:'{cellStyle}',
                            tabindex: '{_tabindex}',
                            text:"{caption}"
                        }
                    }
                },
                'rows.cells.checkbox':{
                    CELL:{
                        style:'width:{width}px;{cellDisplay}',
                        className:'{cellCls}',
                        CELLA:{
                            tagName:'a',
                            className:'{cellClass}',
                            style:'{cellStyle}',
                            href :linb.$href,
                            tabindex: '{_tabindex}',
                            CHECKBOX:{
                                className:'{checkboxCls}'
                            }
                        }
                    }
                },
                'rows.cells.progress':{
                    CELL:{
                        style:'width:{width}px;{cellDisplay}',
                        className:'{cellCls}',
                        CELLA:{
                            tagName:'a',
                            className:'{cellClass}',
                            style:'{cellStyle}',
                            href :linb.$href,
                            tabindex: '{_tabindex}',
                            PROGRESS:{
                                tagName:'div',
                                style:'width:{progress};',
                                text:'{caption}'
                            }
                        }
                    }
                }
            }
        },
        Appearances:{
            KEY:{
                //in firefox, a can focused with display:block
                display:'block',
                position:'absolute',
                overflow:'hidden'
            },
            BOX:{
                display:'block',
                position:'relative',
                overflow:'hidden'
            },

            HEADER:{
                background:  linb.UI.$bg('head.gif', '#CAE3FF repeat-x left top'),
                position:'relative',
                overflow:'hidden'
            },
            HI:{
                position:'relative'
            },
            SCROLL:{
                overflow:'auto',
                position:'relative'
            },
            COLLIST:{
                position:'absolute',
                'z-index':'10',
                left:0,
                top:0,
                cursor:'pointer',
                visibility:'hidden',
                background:  linb.UI.$bg('collist.gif', '#FFF1A0 no-repeat center bottom'),
                border:'1px solid',
                'border-color':  '#fff #ACA899 #ACA899 #fff'
            },
            BODY:{
                overflow:'visible',
                position:'absolute',
                'background-color':'#fff',
                left:0,
                top:'0',
                'font-size':0,
                'line-height':0,
                'border-bottom': '1px solid #ACA899'
            },
            'SORT, SORT-checked':{
                width:'16px',
                height:'16px'
            },
            SORT:{
                background: linb.UI.$bg('icons.gif', 'no-repeat -110px -220px', true),
                position:'absolute',
                right:'2px',
                bottom:'2px'
            },
            'HCELL-mouseover SORT':{
                $order:1,
                'background-position': '-110px -240px'
            },
            'HCELL-mousedown SORT':{
                $order:2,
                'background-position': '-110px -260px'
            },
            'SORT-checked':{
                $order:3,
                'background-position': '-130px -220px'
            },
            'HCELL-mouseover SORT-checked':{
                $order:4,
                'background-position': '-130px -240px'
            },
            'HCELL-mousedown SORT-checked':{
                $order:5,
                'background-position': '-130px -260px'
            },
            HHANDLER:{
                position:'absolute',
                //if set z-index, disappearing in opera
                //'z-index':'10',
                background: linb.browser.ie?'url('+linb.ini.file_bg+')':null,
                width:'4px',
                top:'0',
                right:'0',
                height:'100%',
                cursor:'e-resize',
                'font-size':0,
                'line-height':0
            },
            'HCELLS, CELLS':{
                //for ie height change trigger
                'overflow-y': linb.browser.ie ?'hidden':'',
                position:'relative',
                'white-space': 'nowrap',
                'font-size':'12px',
                'line-height':'18px'
            },
            HCELLS:{
                'padding-bottom':'2px'
            },
            'CELLS-group':{
                $order:1,
                'border-right': '1px solid #ACA899'
            },
            'CELLS-group FCELL':{
                'border-right':0,
                'padding-right':'1px'
            },
            'CELLS-group FCELLCAPTION, CELLS-group FCELLA':{
                'font-weight':'bold',
                color:'#3764A0',
                overflow:'visible'
            },
            'PREVIEW,SUMMARY':{
                position:'relative',
                display:'none',
                'padding-left':'16px',
                'border-right': '1px solid #ACA899'
            },
            PREVIEW:{
                'border-bottom': '1px dashed #ACA899'
            },
            SUMMARY:{
                'border-top': '1px dashed #ACA899'
            },
           'CELLS-mouseover':{
                $order:4,
                'background-color':'#DFE8F6'
            },
            'CELL-disabled':{
                 $order:8,
                 'background-color':'#EBEADB'
            },
            'CELL-disabled CELLA':{
                 $order:8,
                 color:'#999'
            },
            'CELLS-active, CELL-active':{
                 $order:5,
                 'background-color':'#A3BAE9'
            },
            'CELLS-checked, CELL-checked, CELLS-checked CELLA, CELL-checked CELLA':{
                 $order:6,
                'background-color':'#7199E8',
                color:'#fff'
            },
            'HFCELLA, FCELLA':{
                '-moz-box-flex':'1',
                '-moz-user-select':'none',
                display:'block',
                position:'relative',
                overflow:'hidden',
                height:'100%'
            },
            FCELLA:{
                'text-align': 'left',
                'padding-left':'4px'
            },
            HFCELLA:{
                'text-align': 'center',
                'padding-left':'2px'
            },
            FHANDLER:{
                position:'absolute',
                'height':'4px',
                left:'0px',
                width:'100%',
                bottom:'0px',
                cursor:'n-resize',
                'z-index':10,
                'font-size':0,
                'line-height':0
            },
            FCELLINN:{
                'vertical-align':'middle'
            },
            'HFCELL, HCELL':{
               height:'100%',
               'border-left':'1px solid #fff',
               'border-top':'1px solid #fff',
               'border-right':'1px solid #A2BBD9',
               padding:0,
               'vertical-align':'top',
                'font-size':'12px',
                'line-height':'14px'
            },
            'HCELL-mouseover':{
                background:  linb.UI.$bg('head-mouseover.gif', '#FFF1A0 repeat-x left top')
            },
            ROW:{
                position:'relative',
                zoom:linb.browser.ie?1:null,
                width:linb.browser.ie?'100%':null,
                'border-top': '1px solid #A2BBD9',
                'font-size':0,
                'line-height':0
            },
            ROWNUM:{
                'padding-right':'6px',
                color:'#808080'
            },
            'FCELL, CELL':{
                //firefox:height:100% without overflow:hidden
                'padding-left':'1px',
                'border-right':'1px solid #A2BBD9',
                height:'100%',
                position:'relative',
                overflow:linb.browser.ie6?'hidden':'',
                'font-size':'12px',
                'line-height':'20px',
                'vertical-align':'top'
            },
            'ALT':{
                'background-color':'#EFF8FF'
            },
            //
            'CELL-label a':{
                color: '#000'
            },
            'CELL-input':{
            },
            'CELL-number':{
                'text-align':'right'
            },
            'CELL-checkbox':{
                'text-align':'center'
            },
            'CELL-button CELLA':{
                width:'100%'
            },
            'CELL-mouseover':{
                $order:5,
                'background-color':'#DFE8F6'
            },
            HCELLA:{
                position:'relative',
                'text-align': 'center'
            },
            'HCELLA, CELLA':{
                display:'block',
                overflow:'hidden',
                '-moz-box-flex':'1',
                '-moz-user-select':'none',
                height:'100%',
                color:'#000',
                //ie need this
                width:linb.browser.ie?'100%':''
            },
            'CELLA-inline':{
                $order:5,
                display:'inline',
                '-moz-box-flex':0
            },
            PROGRESS:{
                height:'100%',
                'background-color':'#00ffff',
                'text-align':'center',
                overflow:'visible',
                opacity:0.7,
                '*filter':'alpha(opacity=70)'
            },
            'CHECKBOX, MARK':{
               cursor:'pointer',
               width:'16px',
               height:'16px',
               'vertical-align':'middle',
               background: linb.UI.$bg('icons.gif', 'no-repeat -20px -70px', true)
            },
            'CELL-mouseover CHECKBOX':{
                $order:1,
                'background-position': '-20px -90px'
            },
            'CELL-mousedown CHECKBOX':{
                $order:2,
                'background-position': '-20px -110px'
            },
            'CHECKBOX-checked, CELLS-checked MARK':{
                $order:3,
                'background-position': '0 -70px'
            },
            'CELL-mouseover CHECKBOX-checked':{
                $order:4,
                'background-position': '0 -90px'
            },
            'CELL-mousedown CHECKBOX-checked':{
                $order:5,
                'background-position': '0 -110px'
            },
            SUB:{
                //for ie bug: relative , height='auto' will disppear
                '*zoom':1,
                height:0,
                position:'relative',
                overflow:'hidden',
                'font-size':'1px',
                //1px for ie8
                'line-height':'1px'
            }
        },
        Behaviors:{
            HoverEffected:{FCELLCMD:'FCELLCMD', HCELL:'HCELL'},
            ClickEffected:{FCELLCMD:'FCELLCMD', CELL:'CELL', HCELL:'HCELL'},
            DropableKeys:['SCROLL','CELLS','FCELLCMD'],
            DragableKeys:['FCELL'],

            onSize:linb.UI.$onSize,
            HFCELLA:{
                onClick:function(profile,e,src){
                    if(profile.onClickGridHandler)
                        profile.boxing().onClickGridHandler(profile,e,src);
                }
            },
            HFMARK:{
                onClick:function(profile,e,src){
                    if(profile.properties.selMode!='multi')return;

                    var rows=[];
                    _.each(profile.rowMap,function(o){
                        rows.push(o.id);
                    });
                    if(profile._$checkAll){
                        delete profile._$checkAll;
                        profile.boxing().setUIValue("");
                        linb.use(src).tagClass('-checked',false)
                    }else{
                        profile._$checkAll=true;
                        linb.use(src).tagClass('-checked')
                        profile.boxing().setUIValue(rows.join(';'));
                    }
                    return false;
                }
            },
            //key navigator
            SCROLL:{
                onScroll:function(profile, e, src){
                    var l=linb.use(src).get(0).scrollLeft||0;
                    if(profile.$sl!=l)
                        profile.getSubNode('HEADER').get(0).scrollLeft=profile.$sl=l;
                }
            },
            //colomn resizer
            HHANDLER:{
                onMousedown:function(profile, e, src){
                    var p=profile.properties,
                    o=linb(src),
                    minW =o.parent(2).width()-p._minColW,
                    scroll = profile.getSubNode('SCROLL'),
                    maxW = scroll.offset().left + scroll.width() - linb.Event.getPos(e).left - 4,
                    id = profile.getSubId(src),
                    col = profile.colMap[id];

                    if(p.disabled)return false;
                    if(col && col.disabled)return false;

                    o.startDrag(e, {
                        horizontalOnly:true,
                        dragType:'blank',
                        dragDefer:2,
                        maxLeftOffset:minW,
                        maxRightOffset:maxW,
                        targetReposition:false
                    });
                    linb.use(src).parent(2).onMouseout(true,{$force:true}).onMouseup(true);
                },
                onDragbegin:function(profile, e, src){
                    linb.DragDrop.getProfile().proxyNode
                    .css({
                        height:profile.getRoot().height()+'px',
                        width:'4px',
                        backgroundColor:'#ddd',
                        cursor:'e-resize'
                    });
                },
                onDrag:function(profile, e, src){
                    var d=linb.DragDrop,p=d.getProfile(),b=0;
                    if(p.x<=p.restrictedLeft || p.x>=p.restrictedRight)b=true;
                    if(b){
                        if(!profile._limited){
                            p.proxyNode.css('backgroundColor','#ff6600');
                            profile._limited=true;
                        }
                    }else{
                        if(profile._limited){
                            p.proxyNode.css('backgroundColor','#ddd');
                            profile._limited=0;
                        }
                    }
                },
                onDragstop:function(profile, e, src){
                    var o=linb(src).parent(2),
                        w=o.width() + linb.DragDrop.getProfile().offset.x,
                        col=profile.colMap[profile.getSubId(src)];
                    o.width(w);
                    if(col)col.width=w;

                    //collect cell id
                    var ids=[],ws=[];
                    if(_.str.startWith(linb.use(src).parent().id(),profile.keys.HFCELLA))
                        profile.box._setRowHanderW(profile,w);
                    else{
                        var cells = profile.colMap[profile.getSubId(src)]._cells;
                        _.each(cells,function(o){
                            ids.push(profile.getSubNode(profile.keys.CELL,o).id())
                        });
                        linb(ids).width(w);
                    }

                    profile.getSubNode('SCROLL').onScroll();
                    profile.box._ajdustBody(profile);
                    profile._limited=0;
                },
                onClick:function(){
                    return false
                },
                onDblclick:function(profile, e, src){
                    //for row0
                    if(profile.getKey(linb.use(src).parent().id())==profile.keys['HFCELLA']){
                        profile.box._setRowHanderW(profile,true);
                        return;
                    }
                    //for other rows
                    var p = profile.properties,
                        sid = profile.getSubId(src),
                        header = profile.colMap[sid],
                        cells=header._cells,
                        cls=profile.getClass('CELLA','-inline'),
                        n,ns=[],ws=[],w;
                    _.each(cells,function(o){
                        n=profile.getSubNode('CELLA',o);
                        if(n._nodes.length){
                            ns.push(n.get(0));
                            ws.push(n.addClass(cls).width());
                        }
                    });
                    ws.push(p._minColW);
                    w=parseInt(Math.max.apply(null,ws));
                    if(w>p._maxColW)w=p._maxColW;
                    linb(ns).parent().width(w);
                    linb.use(src).parent(2).width(header.width=w);
                    linb(ns).removeClass(cls);

                    profile.box._ajdustBody(profile);
                    return false;
                }
            },
            //row resizer
            FHANDLER:{
                onMousedown:function(profile, e, src){
                    var p=profile.properties,
                    row = profile.rowMap[profile.getSubId(src)],
                    o=linb(src),
                    minH =o.parent(3).height()-p._minRowH,
                    scroll = profile.getSubNode('SCROLL'),
                    maxH = scroll.offset().top + scroll.height() - linb.Event.getPos(e).top - 4;

                    if(p.disabled || (row&&row.disabled))return false;
                    o.startDrag(e, {
                        verticalOnly:true,
                        dragType:'blank',
                        dragDefer:2,
                        maxTopOffset:minH,
                        maxBottomOffset:maxH ,
                        targetReposition:false
                    });
                    linb.use(src).parent(2).onMouseout(true,{$force:true}).onMouseup(true);
                },
                onDragbegin:function(profile, e, src){
                    linb.DragDrop.getProfile().proxyNode
                    .css({
                        width:profile.getRoot().width()+'px',
                        height:'4px',
                        backgroundColor:'#ddd',
                        cursor:'n-resize'
                    });
                },
                onDrag:function(profile, e, src){
                    var d=linb.DragDrop,p=d.getProfile(),b=0;
                    if(p.y<=p.restrictedTop || p.y>=p.restrictedBottom)b=true;
                    if(b){
                        if(!profile._limited){
                            p.proxyNode.css('backgroundColor','#ff6600');
                            profile._limited=true;
                        }
                    }else{
                        if(profile._limited){
                            p.proxyNode.css('backgroundColor','#ddd');
                            profile._limited=0;
                        }
                    }
                },
                onDragstop:function(profile, e, src){
                    var o=linb(src).parent(3),
                        h=o.height()+linb.DragDrop.getProfile().offset.y,
                        row = profile.rowMap[profile.getSubId(src)]

                    //for ie's weird bug
                    if(linb.browser.ie && h%2==1)h+=1;
                    o.height(h);
                    if(_.str.startWith(linb.use(src).parent().id(),profile.keys.HFCELLA)){
                        profile.properties.headerHeight=h;
                        linb.UI.$tryResize(profile,null,profile.getRoot().height(),true);
                    }else
                        row.height=h;
                    profile._limited=0;
                },
                onDblclick:function(profile, e, src){
                    var p = profile.properties,
                        sid = profile.getSubId(src),
                        row,cells;
                    if(sid){
                        row=profile.rowMap[sid];
                        cells=profile.getSubNode('CELLS', sid);
                        cells.height(row.height=cells.height('auto').height());
                    }else{
                        cells=profile.getSubNode('HCELLS');
                        cells.height(profile.properties.headerHeight=cells.height('auto').height());
                        linb.UI.$tryResize(profile,null,profile.getRoot().height(),true);
                    }
                    return false;
                },
                onClick:function(){return false}
            },
            //mark click for tree build
            FCELLCMD:{
                onClick:function(profile, e, src){
                    var
                    p = profile.properties,
                    row = profile.rowMap[profile.getSubId(src)]
                    ;
                    if(p.disabled || row.disabled)return false;
                    //for selection click
                    if(!row.sub)return;

                    profile.box._setSub(profile, row, !row._checked);

                    return false;
                }
            },
            //HCELL handler dragdrop
            HCELL:{
                onClick:function(profile, e, src){
                    var p=profile.properties,
                    id = profile.getSubId(src),
                    col = profile.colMap[id];
                    linb(src).first().focus();
                    if(p.disabled || col.disabled)return false;
                    if(!(col.hasOwnProperty('colSortable')?col.colSortable:p.colSortable))return;

                    var order = col._order || false,
                    type = col.type || 'input',
                    sortby = col.sortby,
                    index = _.arr.indexOf(p.header,col),
                    me=arguments.callee,
                    fun = me.fun||(me.fun = function(profile, root, index, type, sortby,order){
                        var rows,parent,self=arguments.callee;
                        if(root){
                            rows = root.sub;
                            parent = profile.getSubNode('SUB', root._serialId).get(0);
                        }else{
                            root={_created:true};
                            rows = profile.properties.rows;
                            parent = profile.getSubNode('BODY').get(0);
                        }
                        //sor sub first
                        var a1=[], a2=[], a3=[], t,ff;
                        _.arr.each(rows,function(row){
                            if(row.sub && row.sub.length>1)
                                self(profile, row, index, type, sortby, order);
                             //for short input
                             a1[a1.length]=(t=row.cells)?(t=t[index])?t.value:'':row[index];
                             a2[a2.length]=a2.length;
                        });
                        if(typeof sortby!='function'){
                            switch(type){
                                case 'number':
                                    ff=function(n){return parseFloat(n)||0};
                                    break;
                                case 'date':
                                    ff=function(n){return new Date(n).getTime()||0};
                                    break;
                                default:
                                    ff=function(n){return n||''};
                            }
                            sortby=function(x,y){
                               x=ff(a1[x]); y=ff(a1[y]);
                               return (x>y?1:x==y?0:-1)*(order?1:-1);
                            };
                        }
                        a2.sort(sortby);

                        //sort memory array
                        //sort dom node
                        var b = root._created, bak=_.copy(rows), c;
                        if(b)
                            a1=parent.childNodes;
                        _.arr.each(a2,function(o,i){
                            rows[i]=bak[o];
                            if(b)a3[i]=a1[o];
                        });
                        if(b){
                            var fragment=document.createDocumentFragment();
                            for(var i=0;t=a3[i];i++)
                                fragment.appendChild(t);
                            parent.appendChild(fragment);
                        }
                    });

                    fun(profile, '', index, type, sortby,order);

                    //show sort mark
                    profile.getSubNode('SORT', true).css('display','none');
                    var node = profile.getSubNode('SORT', col._serialId).css('display','');
                    node.tagClass('-checked', !(col._order = !col._order));

                    profile.box._asy(profile);

                    //clear rows cache
                    delete profile.$allrowscache;
                    return false;
                },
                onMousedown:function(profile, e, src){
                    var p=profile.properties;
                    if(p.disabled)return;
                    var col=profile.colMap[profile.getSubId(src)];
                    if(!(col.hasOwnProperty('colMovable')?col.colMovable:p.colMovable))return;

                    //fire before event
                    if(false === profile.boxing().beforeColDrag(profile, col.id))return;

                    var pos=linb.Event.getPos(e),
                        o = linb(src),
                        itemId = profile.getSubId(src);

                    o.startDrag(e,{
                        dragType:'icon',
                        shadowFrom:src,
                        dragCursor:'pointer',
                        targetLeft:pos.left+12,
                        targetTop:pos.top+12,
                        targetReposition:false,
                        dragDefer: 2,
                        dragKey:profile.$linbid + ":col",
                        dragData:o.id()
                    });
                },
                onDragbegin:function(profile, e, src){
                    linb(src).onMouseout(true,{$force:true}).onMouseup(true);
                },
                beforeMouseover:function(profile, e, src){
                    if(false===profile.box._colDragCheck(profile,src))return;
                    linb.DragDrop.setDropElement(src).setDropFace(src,'move');
                },
                beforeMouseout:function(profile, e, src){
                    linb.DragDrop.setDropElement(null).setDropFace(null,'none');
                    if(false===profile.box._colDragCheck(profile,src))return;
                },
                onDrop:function(profile, e, src){
                    if(false===profile.box._colDragCheck(profile,src))return;

                    //check dragData
                    var p=profile.properties,
                    data=linb.DragDrop.getProfile().dragData,
                    fromId = data && profile.getSubId(data),
                    toId = profile.getSubId(src);

                    //get properties
                    var
                    map=profile.colMap,
                    fromTh=map[fromId],
                    toTh=map[toId]
                    ;

                    //fire before event
                    if(false === profile.boxing().beforeColMoved(profile,fromTh.id, toTh.id))return;

                    //remove dragover appearance
                    linb.DragDrop.setDropFace(src,'none');

                    //get index in HCELL array
                    var fromIndex = _.arr.subIndexOf(p.header,'_serialId',fromId),
                    toIndex = _.arr.subIndexOf(p.header,'_serialId',toId)
                    ;
                    //if same or same position, return
                    if(fromIndex===toIndex|| fromIndex===toIndex-1)return;


                    //reposition header dom node
                    profile.getSubNode('HCELL', toId).addPrev(linb(linb.DragDrop.getProfile().dragData));
                    //reposition cell dom nodes
                    _.each(toTh._cells, function(o,i){
                        profile.getSubNode('CELL',o).addPrev(profile.getSubNode('CELL',fromTh._cells[i]));
                    });

                    //update memory
                    //HCELL position
                    //keep refrence, and remove
                    var temp=p.header[fromIndex];
                    _.arr.removeFrom(p.header,fromIndex);
                    //insert to right pos
                    _.arr.insertAny(p.header,temp,toIndex);
                    //cell position rowMap
                    var allitems = profile.queryItems(p.rows, true, true);
                    _.arr.each(allitems,function(o){
                        //for those non-prepared data
                        o=o.cells?o.cells:o;
                        if(!o || o.constructor!=Array)return;
                        temp=o[fromIndex];
                        _.arr.removeFrom(o,fromIndex);
                        _.arr.insertAny(o,temp,toIndex);
                    });

                    //fire after event
                    profile.boxing().afterColMoved(profile, fromTh.id, toTh.id);

                    //clear rows cache
                    delete profile.$allrowscache;
                },
                onMouseover:function(profile,e,src){
                    var p=profile.properties;
                    if(p.disabled)return;
                    var col=profile.colMap[profile.getSubId(src)];
                    if(!(col.hasOwnProperty('colHidable')?col.colHidable:p.colHidable))return;

                    _.resetRun(profile.$linbid+':collist',null);
                    var region={},
                        pos=linb.use(src).offset(null,profile.getSubNode('BOX')),
                        size=linb.use(src).cssSize();
                    if(size.width<16)return;
                    region.height=size.height;var col=profile.colMap[profile.getSubId(src)];
                    region.width=14;
                    region.left=pos.left;
                    region.top=pos.top;
                    profile.getSubNode('COLLIST').cssRegion(region).css('visibility','visible');
                },
                onMouseout:function(profile,e,src){
                    var p=profile.properties;
                    if(p.disabled)return;
                    var col=profile.colMap[profile.getSubId(src)];
                    if(!(col.hasOwnProperty('colHidable')?col.colHidable:p.colHidable))return;

                    _.resetRun(profile.$linbid+':collist',function(){
                        profile.getSubNode('COLLIST').css({visibility:'hidden',left:0,top:0});
                    });
                }
            },
            COLLIST:{
                onMouseover:function(profile,e,src){
                    _.resetRun(profile.$linbid+':collist',null);
                },
                onMouseout:function(profile,e,src){
                    _.resetRun(profile.$linbid+':collist',function(){
                        linb.use(src).css('visibility','hidden');
                    });
                },
                onClick:function(profile,e,src){
                    var p=profile.properties;
                    if(!profile.$col_pop){
                        var items=[],pop;
                        _.arr.each(profile.properties.header,function(o){
                            if(o.hasOwnProperty('colHidable')?o.colHidable:p.colHidable)
                                items.push({id:o.id,caption:o.caption,type:'checkbox',value:true});
                        });
                        if(items.length){
                            pop=profile.$col_pop=new linb.UI.PopMenu({hideAfterClick:false,items:items}).render(true);
                            pop.onMenuSelected(function(p,i,s){
                                var b=1;
                                _.arr.each(p.properties.items, function(o){
                                    if(o.value!==false)
                                        return b=false;
                                });
                                if(!b){
                                    profile.boxing().showColumn(i.id, i.value);
                                }else{
                                    p.getSubNodeByItemId('CHECKBOX',i.id).tagClass('-checked');
                                    i.value=true;
                                }
                            })
                        }
                    }
                    if(profile.$col_pop)
                        profile.$col_pop.pop(src);
                }
            },
            CELLS:{
                afterMouseover:function(profile, e, src){
                    if(profile.properties.activeMode=='row')
                        linb.use(src).tagClass('-mouseover');
                },
                afterMouseout:function(profile, e, src){
                    if(profile.properties.activeMode=='row')
                        linb.use(src).tagClass('-mouseover',false);
                },
                onDblclick:function(profile, e, src){
                    var p = profile.properties,
                        row = profile.rowMap[profile.getSubId(src)];
                    if(p.disabled || row.disabled)return false;
                    if(profile.onDblClickRow)profile.boxing().onDblClickRow(profile, row, e, src);
                    return false;
                },
                onClick:function(profile,e,src){
                    var p = profile.properties,
                        row = profile.rowMap[profile.getSubId(src)];
                    if(row.group)
                        profile.getSubNode('FCELLCMD',row._serialId).onClick();
                }
            },
            CELL:{
                afterMouseover:function(profile, e, src){
                    if(profile.properties.activeMode=='cell')
                        linb.use(src).tagClass('-mouseover');
                },
                afterMouseout:function(profile, e, src){
                    if(profile.properties.activeMode=='cell')
                        linb.use(src).tagClass('-mouseover',false);
                }
            },
            CELLA:{
                onDblclick:function(profile, e, src){
                    var cell = profile.cellMap[profile.getSubId(src)];
                    if(!cell)return;
                    var box=profile.box,
                        getPro=box.getCellPro,
                        type=getPro(profile, cell, 'type'),
                        disabled=getPro(profile, cell, 'disabled'),
                        editable=getPro(profile, cell, 'editable');

                    if(!disabled && (!editable || (type=='button'||type=='label')))
                        profile.boxing().onDblClickCell(profile, cell, e, src);
                },
                onClick:function(profile, e, src){
                    var cell = profile.cellMap[profile.getSubId(src)];
                    if(!cell)return;
                    var p = profile.properties,
                        box=profile.box,
                        getPro=box.getCellPro,
                        type=getPro(profile, cell, 'type'),
                        disabled=getPro(profile, cell, 'disabled'),
                        event=getPro(profile, cell, 'event'),
                        mode = p.activeMode,
                        editable=getPro(profile, cell, 'editable'),
                        id;

                    if(!disabled && (!editable || (type=='button'||type=='label'))){
                        if(typeof event == 'function' && false===event.call(profile._host||profile, profile, cell, null,null,e,src)){}
                        else
                            profile.boxing().onClickCell(profile, cell, e, src);
                        if(type=='button')
                            return false;
                    }
                    if(!disabled &&type=='checkbox')
                        if(editable)
                            box._updCell(profile, cell, !cell.value);
                    if(!p.editable){
                        if(mode=='cell'){
                            if(getPro(profile, cell, 'disabled'))
                                return false;
                            id = linb(src).parent().id();
                            box._sel(profile, 'cell', src, id, e);
                        }else if(mode=='row'){
                            if(p.disabled || cell._row.disabled)
                                return false;
                            id = linb(src).parent(2).id();
                            box._sel(profile, 'row', src, id, e);
                        }
                    }
                    //ie6: if 'a' has a child 'span', you click 'span' will not tigger to focus 'a'
                    linb.use(src).focus();
                    return false;
                },
                onFocus:function(profile, e, src){
                    var p = profile.properties,
                        box=profile.box,
                        getPro=box.getCellPro,
                        cell = profile.cellMap[profile.getSubId(src)],
                        mode = p.activeMode, id;

                    if(getPro(profile, cell, 'editable')){
                        if(getPro(profile, cell, 'disabled'))
                            return false;
                        box._editCell(profile, cell._serialId);
                        _.asyRun(function(){
                            linb.use(src).parent().onMouseout(true,{$force:true})
                                      .parent().onMouseout(true,{$force:true});
                        });
                    }
                    if(!p.editable){
                        if(mode=='cell'){
                            id = linb.use(src).parent().id();
                            box._activeCell(profile, id);
                        }else if(mode=='row'){
                            id = linb.use(src).parent(2).id();
                            box._activeRow(profile, id);
                        }
                    }
                },
                onKeydown:function(profile, e, src){
                    var keys=linb.Event.getKey(e),
                        key = keys[0],
                        shift=keys[2],
                        cur = linb(src),
                        body = profile.getSubNode('BODY'),
                        first = body.nextFocus(true, true, false),
                        last = body.nextFocus(false, true, false);
                    switch(key){
                    //tab to next/pre
                    case 'tab':
                        if(shift){
                            if(src!=first.get(0)){
                                first.focus();
                                return false;
                            }
                        }else{
                            if(src!=last.get(0)){
                                last.focus();
                                return false;
                            }
                        }
                        break;
                    case 'left':
                        if(cur.get(0)==first.get(0))
                            last.focus();
                        else
                            cur.nextFocus(false);
                        return false;
                        break;
                    case 'right':
                        if(cur.get(0)==last.get(0))
                            first.focus();
                        else
                            cur.nextFocus();
                        return false;
                        break;
                    case 'up':
                        if(cur.get(0)==first.get(0)){
                            last.focus();
                            return;
                        }
                   case 'down':
                        //get no.
                        var count=1,
                            fkey=profile.keys.FCELL,
                            temp = cur.parent().get(0),
                            max=temp.parentNode.childNodes.length;
                        while(temp=temp.previousSibling)count++;

                        //get row
                        temp=cur.parent(2).get(0);

                        //get all rows(include header)
                        if(!profile.$allrowscache){
                            var all=profile.getSubNode('CELLS',true).get();
                            //filter dispaly==none
                            _.filter(all,function(o){
                                return !!o.offsetWidth && profile.getKey(o.lastChild.id)!=fkey;
                            });
                            profile.$allrowscache = all;
                        }

                        //get index
                        var index = _.arr.indexOf(profile.$allrowscache,temp),
                            rowLen = profile.$allrowscache.length;

                        //adjust index
                        if(key=='up'){
                            index--;
                            if(index==-1){
                                index = rowLen-1;
                                count--;
                                if(count==0)count=max;
                            }
                        }else{
                            index++;
                            if(index==rowLen){
                                index=0;
                                count++;
                                if(count==max+1)count=1;
                            }
                        }

                        //get node
                        node = linb(profile.$allrowscache[index]).first().next(count-1).first();
                        if(!node.isEmpty())
                            node.focus();
                        return false;
                        break;
                    }
                }
            },
            FCELL:{
                onClick:function(profile, e, src){
                    var p=profile.properties,
                        row = profile.rowMap[profile.getSubId(src)],
                        b=profile.box
                    if(!row.group){
                        if(p.disabled || row.disabled)
                            return false;
                        if(p.activeMode=='row')
                            b._sel(profile, 'row',src, src, e);
                        if(row.cells[0])
                            linb.use(src).next().first().focus();
                    }
                }
            }
        },
        DataModel:{
            directInput:true,
            listKey:null,
            selMode:{
                ini:'none',
                listbox:['single','none','multi'],
                action:function(value){
                    this.getSubNodes(['HFMARK','MARK'],true).css('display',value=='multi'?'':'none');
                }
            },
            dock:'fill',

            altRowsBg: {
                ini:false,
                action:function(value){
                    var ns=this;
                    var altCls = ns.getClass('ALT'),
                        nodes = ns.getSubNode('CELLS',true),alt,j;
                    nodes.removeClass(altCls);
                    if(value){
                        alt=[];
                        j=0;
                        nodes.each(function(o,i){
                            if(o.offsetHeight){
                                o=linb([o]);
                                if((j++)%2==1){
                                    if(!o.hasClass(altCls))o.addClass(altCls);
                                }else{
                                    if(o.hasClass(altCls))o.removeClass(altCls);
                                }
                            }
                        });
                        linb(alt).addClass(altCls);
                    }
                }
            },
            rowNumbered:{
                ini:false,
                action:function(value){
                    var ns=this,
                        f=ns.CF.getNumberedStr||function(a){return a},
                        nodes = ns.getSubNode('ROWNUM',true),
                        i=0,
                        map=ns.rowMap,
                        row,ol=0,l=0,a1=[],a2=[],tag='',temp,t;
                    if(value)
                        nodes.each(function(o){
                            if(o.parentNode.offsetWidth){
                                row=map[ns.getSubId(o.id)];
                                l=row._layer;
                                if(l>ol){
                                    a1.push(i);
                                    a2.push(tag);
                                    tag=tag+i+'.';
                                    i=0;
                                }else if(l<ol){
                                    while(l<ol--){
                                        i=a1.pop();
                                        tag=a2.pop();
                                    }
                                }
                                i++;
                                ol=l;
                                //o.innerHTML=''+tag+i;
                                temp=f(tag+i);
                                if(t=o.firstChild){
                                    if(t.nodeValue!=temp)
                                        t.nodeValue=temp;
                                }else
                                    o.appendChild(document.createTextNode(temp));
                            }
                        });
                    else
                        nodes.text('');
                }
            },
            editable:false,

            $subMargin:16,

            iniFold:true,
            animCollapse:false,

            position:'absolute',
            width:300,
            height:200,

            _minColW:5,
            _maxColW:300,
            _minRowH:20,

            gridHandlerCaption:{
                ini:"",
                action:function(v){
                    this.getSubNode('GRIDCAPTION').get(0).innerHTML=v;
                }
            },
            rowHandlerWidth: {
                ini:50,
                set:function(value){
                    var o=this;
                    if(o.renderId)
                        o.box._setRowHanderW(o,value);
                    else
                        o.properties.rowHandlerWidth=value;
                }
            },

            showHeader:{
                ini:true,
                action:function(value){
                    this.getSubNode('HEADER').css('display',value?'':'none');
                }
            },
            headerHeight:{
                ini:18,
                action:function(v){
                    this.getSubNode('HCELLS').height(v);
                    linb.UI.$tryResize(this, this.getRoot().width(), this.getRoot().height(),true);
                }
            },
            rowHeight:{
                ini:20,
                action:function(v){
                    this.getSubNode('CELLS', true).height(v);
                }
            },
            _colDfWidth: 80,

            rowHandler:{
                ini:true,
                action:function(value){
                    this.getSubNode('HFCELL').css('display',value?'':'none');
                    this.getSubNode('FCELL',true).css('display',value?'':'none');
                    this.box._ajdustBody(this);
                }
            },
            rowResizer:{
                ini:false,
                action:function(value){
                    this.getSubNode('FHANDLER',true).css('display',value?'':'none');
                }
            },

            colHidable:false,
            colResizer:{
                ini:true,
                action:function(value){
                    this.getSubNode('HHANDLER',true).css('display',value?'':'none');
                }
            },
            colSortable:{
                ini:true,
                action:function(value){
                    if(!value)
                        this.getSubNode('SORT',true).css('display','none');
                }
            },
            colMovable:false,

            header:{
                ini:{},
                set:function(value){
                    var o=this;
                    if(o.renderId){
                        o.boxing()._refreshHeader(value);
                    }else
                        o.properties.header = _.copy(value);
                }
            },
            rows:{
                //for default merge
                ini:{},
                set:function(value){
                    var o=this;
                    if(o.renderId)
                        o.boxing().removeAllRows().insertRows(value);
                    else
                        //use copy to avoid outer memory link
                        o.properties.rows = _.copy(value);
                }
            },
            activeMode:{
                ini:'row',
                listbox:['row','cell','none'],
                action:function(value){
                    var profile=this;
                    if(value!='cell' && profile.$activeCell){
                        linb(profile.$activeCell).tagClass('-active',false);
                        delete profile.$activeCell;
                    }
                    if(value!='row' && profile.$activeRow){
                        linb(profile.$activeRow).tagClass('-active',false);
                        delete profile.$activeRow;
                    }
                }
            },
            noCtrlKey:true
        },
        EventHandlers:{
            onGetContent:function(profile, row, callback){},
            onRowSelected:function(profile, row, src){},

            beforeColDrag:function(profile, colId){},
            beforeColMoved:function(profile, colId, toId){},
            afterColMoved:function(profile, colId, toId){},

            beforeRowActive:function(profile, row){},
            afterRowActive:function(profile, row){},
            beforeCellActive:function(profile, cell){},
            afterCellActive:function(profile, cell){},

            beforeIniEditor:function(profile, cell, cellNode){},
            beforeCellUpdated:function(profile, cell, options){},
            afterCellUpdated:function(profile, cell, options){},

            onDblClickRow:function(profile, row, e, src){},
            beoforeComboPop:function(profile, cell, proEditor, pos, e, src){},
            onClickCell:function(profile, cell, e, src){},
            onDblClickCell:function(profile, cell, e, src){},
            onClickGridHandler:function(profile, e, src){}
        },
        RenderTrigger:function(){
            var ns=this, pro=ns.properties,ins=ns.boxing();
            ns.destroyTrigger=function(){
                var ns=this, pro=ns.properties;
                _.breakO([ns.colMap, ns.rowMap, ns.cellMap], 3);
                pro.header.length=0;
                pro.rows.length=0;
            };
            ns.$cache_editor={};
            if(!pro.iniFold)
                ins._expendRows(pro.rows);
            ns.box._asy(ns);
            ns.box._ajdustBody(ns);
        },
        _asy:function(profile){
            var pro=profile.properties,b=profile.boxing(),id=profile.$linbid;
            if(pro.altRowsBg)_.resetRun(id+"1",function(){b.setAltRowsBg(true,true)});
            if(pro.rowNumbered)_.resetRun(id+"2",function(){b.setRowNumbered(true,true)});
        },
        _setRowHanderW:function(profile, flag){
            var pro=profile.properties,
                ww=pro.$subMargin,
                map=profile.rowMap,
                hcell=profile.getSubNode('HFCELL'),
                n,w;
            if(typeof flag=='number')
                w=flag;
            else if(flag===true){
                var ws=[],t;
                profile.getSubNode('FCELLINN',true).each(function(o){
                    if((t=o.parentNode).parentNode.offsetWidth>0 && linb.Dom.getStyle(t,'overflow')!='visible')
                        if(n=map[profile.getSubId(o.id)])
                            ws.push(linb([o]).width() + n._layer*ww);
                });
                ws.push(pro._minColW);
                w=parseInt(Math.max.apply(null,ws))+ww*2;
            }else
                w=hcell.width();

            //set width
            if(w){
                if(w<pro._minColW)w=pro._minColW;
                if(pro.rowHandlerWidth!=w){
                    hcell.width(pro.rowHandlerWidth=w);
                    profile.getSubNode('FCELL',true).width(w);
                    profile.getSubNode('FCELLRULER',true).each(function(o){
                        n=map[profile.getSubId(o.id)];
                        o.style.width=n._layer*ww+'px';
                    });
                    profile.box._ajdustBody(profile);
                }
            }
        },
        _onStartDrag:function(profile, e, src){
            var pos=linb.Event.getPos(e);
            profile.$_ond=src;
            linb.use(src).startDrag(e, {
                dragType:'icon',
                shadowFrom:linb.use(src).parent()._get(0),
                targetLeft:pos.left+12,
                targetTop:pos.top+12,
                dragCursor:'pointer',
                dragDefer:2,
                dragKey: profile.box.getDragKey(profile, src),
                dragData: profile.box.getDragData(profile, e, src)
            });
            return false;
        },
        _onDropTest:function(profile, e, src, key, data, item){
            var fid=data&&data.domId, tid=src, fp=data&&data.profile,t;
            if(tid){
                var k=profile.getKey(tid),
                    ks=profile.keys,
                    row=profile.rowMap[profile.getSubId(tid)];
                if(k==ks.FCELLCMD && !row.sub)
                    return false;
            }
            if(fp && fp.$linbid==profile.$linbid){
                if(fid && profile.getSubId(fid)==profile.getSubId(tid))
                    return false;
                t=profile.$_ond;

                src=linb(src).get(0);
                if(_.get(src,['parentNode','previousSibling'])==t)return false;
                do{
                    if(src==t){
                        src=t=null;
                        return false;
                    }
                }while(src && (src=src.parentNode) && src!==document && src!==window)
                src=t=null;
            }
        },
        _onDragstop:function(profile, e, src, key, data, item){
            delete profile.$_ond;
        },
        _onDrop:function(profile, e, src, key, data, item){
            linb.DragDrop.setDragIcon('none');
            if(!data.profile || !data.profile[profile.KEY])return;
            var k=profile.getKey(src),
                po=data.profile,
                ps=data.domId,
                oitem,
                ks=profile.keys,
                t=linb.absObj.$specialChars,
                b=profile.boxing(),

                orow= po.rowMap[po.getSubId(ps)],
                row= profile.rowMap[profile.getSubId(src)];

            //remove
            orow=_.clone(orow,function(o,i){return !t[(i+'').charAt(0)]});
            po.boxing().removeRows([orow.id]);

            //add
            if(k==ks.SCROLL)
                b.insertRows([orow], null, null, false);
            else if((k==ks.FCELLCMD) && row.sub)
                b.insertRows([orow], row.id, null, false);
            else if(k==ks.CELLS)
                b.insertRows([orow], row._pid, row.id, true);
            return false;
        },

        _beforeSerialized:function(profile){
            var o=arguments.callee.upper.call(this, profile),
                pp=profile.properties,
                map=linb.absObj.$specialChars,
                t;
            o.properties.header = _.clone(pp.header, function(o,i){return !map[(i+'').charAt(0)]});
            o.properties.rows = _.clone(pp.rows, function(o,i){return !map[(i+'').charAt(0)]});
            if(o.properties.header.length===0)delete o.properties.header;
            if(o.properties.rows.length===0)delete o.properties.rows;
            return o;
        },
        _clsCache:{},

        _colDragCheck:function(profile, src){
            var dd = linb.DragDrop.getProfile(), key=dd.dragKey, data=dd.dragData,
                col=profile.colMap[profile.getSubId(src)];
            if(!(col.hasOwnProperty('colMovable')?col.colMovable:profile.properties.colMovable))return;

            if(!key || !data || key!=(profile.$linbid+":col"))return false;
            if(data==linb.use(src).id() || data==linb.use(src).prev().id())return false;
        },
        _prepareData:function(profile){
            var data = arguments.callee.upper.call(this, profile),NONE='display:none';
            profile.rowMap2 = {};
            profile.rowMap = {};
            profile.cellMap = {};

            var pro=profile.properties;

            data.showHeader=pro.showHeader?'':NONE;
            data.colDDDisplay=pro.colResizer?'':NONE;
            data.rowDDDisplay=pro.rowResizer?'':NONE;
            data.rowHandlerDisplay=pro.rowHandler?'':NONE;
            data.headerHeight=data.headerHeight?('height:'+data.headerHeight+'px;'):'';
            data._rowMarkDisplay=pro.selMode=="multi"?"":"display:none;";

            if(pro.header && pro.header.constructor != Array)
                pro.header = [];
            if(pro.rows && pro.rows.constructor != Array)
                pro.rows = [];

            pro.header=this._adjustHeader(pro.header);
            data.header=this._prepareHeader(profile, pro.header);
            data._row0DfW=data.rowHandlerWidth?('width:'+data.rowHandlerWidth+'px'):'';

            arguments.callee.upper.call(this, profile);

            pro.rows=this._adjustRows(pro.rows);
            data.rows = this._prepareItems(profile, pro.rows);
            return data;
        },
        _prepareHeader:function(profile, arr){
            var a = profile.colMap2 = {},
                b = profile.colMap = {},
                SubID=linb.UI.$tag_subId,
                pro=profile.properties,
                header=[], temp, t,
                NONE='display:none';
            _.arr.each(arr,function(o,i){
                temp='h_'+profile.pickSubId('header');
                if(typeof o=='string')
                    o=arr[i]={id:o};
                if(typeof o.id!='string')
                    o.id=o.caption||(_()+'');

                //#
                o._cells={};
                o[SubID]=temp;
                b[temp]=o;
                o.width = o.width||pro._colDfWidth;

                t={
                    sortDisplay : NONE,
                    rowHandlerDisplay : pro.rowHandler?'':NONE
                };
                t[SubID]=temp;
                t._tabindex=pro.tabindex;

                t.colDDDisplay = (('colResizer' in o)?o.colResizer:pro.colResizer)?'':'display:none';

                if(!o.type)o.type='label';
                if(!o.caption)o.caption=o.id;
                linb.UI.adjustData(profile, o, t);

                // id to dom item id
                a[o.id]=temp;
                // dom item id to properties item
                header.push(t);
            });
            return header;
        },
        _renderCell:function(profile,cell,node,options){
            var getPro=profile.box.getCellPro,
                dom=node['linb.Dom'],
                ncell=dom?cell:node,
                type=getPro(profile, cell, 'type'),
                t1='',
                t2='',
                caption,
                capOut=(!dom)&&node.caption,
                reg1=/</g,
                me=arguments.callee,
                dcls=me._dcls||(me._dcls=profile.getClass('CELL', '-disabled')),
                //1. $caption in cell (for special set)
                //2. caption in ncell(if [ncell] is not [cell], the [caption] maybe is the result of cell.renderer)
                //3. renderer in cell
                //4. default caption function
                //5. value in cell
                //6. ""
                ren=me._ren||(me._ren=function(profile,cell,ncell,fun){return typeof cell.$caption=='string'? cell.$caption: typeof ncell.caption =='string'?ncell.caption: typeof cell.renderer=='function'? cell.renderer(cell) : typeof fun=='function'?fun(cell.value):String(cell.value) || ""}),
                f1=me._f1=(me._f1=function(v){return linb.Date.getText(new Date(parseInt(v)), 'ymd')}),
                f2=me._f2=(me._f2=function(v){return (v.split('\n')[0]||"").replace(/ /g,'&nbsp;').replace(reg1,'&lt;')}),
                f3=me._f3=(me._f3=function(v){return v*1000/10+'%'})
            ;

            switch(type){
                case 'number':
                    cell.value=parseFloat(cell.value)||0;
                    caption= capOut ||ren(profile,cell,ncell);
                    if(dom)node.html(caption||cell.value,false);
                break;
                case 'datepicker':
                    cell.value=(parseInt(cell.value)?new Date(parseInt(cell.value)):new Date()).getTime();
                    caption= capOut || ren(profile,cell,ncell,f1);
                    if(dom)
                        node.html(caption, false);
                break;
                case 'textarea':
                    cell.value=cell.value||"";
                    caption= capOut ||ren(profile,cell,ncell,f2);
                    if(dom)
                        node.html(caption,false);
                break;
                case 'colorpicker':
                    cell.value="#"+linb.UI.ColorPicker._ensureValue(0,cell.value);
                    caption= capOut ||ren(profile,cell,ncell);
                    t1=linb.UI.ColorPicker.getTextColor(cell.value);
                    if(dom){
                        node.html(caption,false);
                        node.css('color',t1).css('backgroundColor',cell.value);
                    }else{
                        node.color='color:'+t1+';';
                        node.bgcolor='background-color:'+cell.value+';';
                    }
                break;
                case 'checkbox':
                    cell.value=!!cell.value;
                    caption=cell.value+'';
                    if(dom)
                        node.first().tagClass('-checked', cell.value);
                    else
                        node.checkboxCls = profile.getClass('CHECKBOX', cell.value?'-checked':'');
                break;
                case 'progress':
                    cell.value=parseFloat(cell.value)||0;
                    cell.value=Math.min(Math.max(cell.value,0),1);
                    caption= capOut ||ren(profile,cell,ncell,f3);
                    if(dom){
                        node.first().html(caption, false).width(caption);
                    }else
                        node.progress=caption;

                break;
                default:
                    cell.value=cell.hasOwnProperty("value")?cell.value:"";
                    caption= capOut ||ren(profile,cell,ncell);
                    if(dom)node.html(caption||cell.value,false);
            }

            cell._$tips=caption;

            var t2=getPro(profile, cell, 'disabled');
            if(!dom){
/*
cellStyle
cellClass

renderer
type
disabled
editable
editorListKey
editorListItems
editorFormat
editorMask
editorReadonly
value
caption

sortby [for column only]
*/
                node.cellCls=profile.getClass('CELL', '-'+type) + (t2?(' '+dcls):'');
                node.type=type;
                node.value=cell.value;
                node.caption=caption;

                node.cellStyle=getPro(profile, cell, 'cellStyle');
                node.cellClass=getPro(profile, cell, 'cellClass');

            }else{
                if(t2) node.addClass(dcls);
                else node.removeClass(dcls);

                if(t2=options.cellStyle)
                    node.attr('style',node.attr('style')+";"+t2);
                if(t2=options.cellClass)
                    node.addClass(t2);
            }
        },
        _prepareItems:function(profile, arr, pid){
            var self=this,
                pro=profile.properties,
                mm = pro.$subMargin,
                a = profile.rowMap2,
                b = profile.rowMap,
                d = profile.cellMap,
                _layer=pid?b[a[pid]]?(b[a[pid]]._layer+1):0:0,
                SubID=linb.UI.$tag_subId,
                me=arguments.callee,
                ider = me._id||(me._id=new _.id()),
                rows=[],
                temp,cells,t,row,g,j,v,
                NONE='display:none';

            for(var i=0,l=arr.length;i<l;i++){
                temp='r_'+profile.pickSubId('row');

                //make sure the row id
                if(!arr[i].id || a[arr[i].id]){
                    while(a[t=ider.next()]);
                    arr[i].id=t;
                }

                row = arr[i];
                //#
                row._pid = pid;
                row._cells={};
                row._layer=_layer;


                row[SubID]=temp;
                row._tabindex=pro.tabindex;
                row._rowMarkDisplay=pro.selMode=="multi"?"":NONE;

                b[temp]=row;

                t={id: row.id};

                if(row.group)
                    t.rowCls = profile.getClass('CELLS','-group');

                if(row.summary)
                    t.summaryDisplay='display:block;';
                if(row.preview)
                    t.previewDisplay='display:block;';

                t._row0DfW=pro.rowHandlerWidth?('width:'+pro.rowHandlerWidth+'px'):'';
                t._rulerW=_layer*mm;

                t.rowHeight=row.height||pro.rowHeight;
                t.rowHandlerDisplay=pro.rowHandler?'':NONE;
                t.rowDDDisplay=(('rowResizer' in row)?row.rowResizer:pro.rowResizer)?'':NONE;

                cells = t.cells = [];

                t[SubID]=temp;
                t.subClass = row.sub?'uicmd-toggle2':'uicmd-empty';

                // id to dom item id
                a[row.id]=temp;

                // for cells
                if(row.group)
                    row.cells=null;
                if(!row.hasOwnProperty('caption') && row.hasOwnProperty('value'))
                    row.caption=''+row.value;

                if(row.caption && !row.tips)
                    row._$tips=row.caption;

                if(v=row.cells)
                    _.arr.each(pro.header,function(headCell,j){
                        g=v[j]||(v[j]={});

                        var n={};
                        //cell/cell link to row
                        g._row = row;
                        //cell/cell link to header
                        g._col=headCell;
                        g[SubID]='c_'+profile.pickSubId('cell');

                        self._adjustCell(profile, g, n);

                        cells.push(n);

                        // cell only link its' dom item id to properties item
                        d[n[SubID]]=g;

                        // row link to cell/cell
                        row._cells[headCell.id]=n[SubID];
                        // header link to cell/cell
                        headCell._cells[row.id]=n[SubID];
                    });

                linb.UI.adjustData(profile, row, t);

                rows.push(t);
            }
            return rows;
        },
        _adjustCell:function(profile, cell, uicell){
            var self=this,
                pro=profile.properties,
                col=cell._col,
                renderer;
            if(renderer=self.getCellPro(profile, cell, 'cellRenderer'))
                cell.renderer=renderer;

            //first
            linb.UI.adjustData(profile, cell, uicell);
            //next
            cell._$value=cell.value;

            if(!uicell.width)uicell.width=col.width;
            uicell._tabindex=pro.tabindex;
            uicell.cellDisplay=col.visibility===false?'display:none;':'';

            self._renderCell(profile, cell, uicell);
        },
        _setSub:function(profile, item, flag){
            var id=profile.domId,
                pro=profile.properties,
                serialId = profile.rowMap2[item.id],
                markNode = profile.getSubNode('FCELLCMD', serialId),
                subNs = profile.getSubNode('SUB', serialId)
                ;

            if(linb.Thread.isAlive(profile.key+profile.id)) return;
            //close
            if(item._checked){
                if(!flag){
                    var h = subNs.height();

                    if(pro.animCollapse)
                        subNs.animate({'height':[h,0]},null,null, 100, 5, 'expoIn', profile.key+profile.id).start();
                    else
                        subNs.height(0);

                    markNode.tagClass('-checked', false);
                    item._checked = false;
                    profile.box._asy(profile);
                }
            }else{
                //open
                if(flag){
                    var openSub = function(profile, item, id, markNode, subNs, sub){
                        var b=profile.boxing(),
                            p = profile.properties;
                        //created
                        if(!item._created){
                            delete item.sub;
                            //before insertRows
                            item._created=true;
                            //subNs.css('display','none');

                            if(typeof sub=='string')
                                subNs.html(item.sub=sub,false);
                            else if(_.isArr(sub))
                                b.insertRows(sub, item.id);
                            else if(sub['linb.Template']||sub['linb.UI'])
                                subNs.append(item.sub=sub.render(true));

                            //set checked items
                            b._setCtrlValue(b.getUIValue(), true);
                        }

                        var h = subNs.height(true);
                        if(p.animCollapse)
                            subNs.animate({'height':[0,h]},null,function(){subNs.css({height:'auto'})}, 100, 5, 'expoOut', profile.key+profile.id).start();
                        else
                            subNs.css({height:'auto'});

                        markNode.tagClass('-checked');
                        item._checked = true;
                        profile.box._asy(profile);
                    };

                    var sub = item.sub, callback=function(sub){
                        openSub(profile, item, id, markNode, subNs, sub);
                    },t;
                    if((t=typeof sub)=='string'||t=='object')
                        callback(sub);
                    else if(profile.onGetContent){
                        var r=profile.boxing().onGetContent(profile, item, callback);
                        if(r) callback(r);
                    }
                }
            }
            //clear rows cache
            delete profile.$allrowscache;
        },
        _getCellId:function(profile, rowId, colId){
            return _.get(profile.rowMap,[profile.rowMap2[rowId], '_cells',colId]);
        },
        _updCell:function(profile, cellId, options, dirtyMark){
            var box=profile.box,
                sc=linb.absObj.$specialChars,
                cell,node;

            if(typeof cellId == 'string')
                cell = profile.cellMap[cellId];
            else{
                cell = cellId;
                cellId = cell._serialId;
            }
            if(!cell)return;

            if(!_.isObj(options))options={value:options};
            options=_.filter(options,function(o,i){return !sc[i.charAt(0)] || i=='$caption' });

            if(false === profile.boxing().beforeCellUpdated(profile, cell, options))
                return;

            //special for caption
            delete cell.caption;
            if(cell.hasOwnProperty('caption')){
                options.caption=options.caption;
                delete options.caption;
            }
            _.merge(cell,options,'all');

            node=profile.getSubNode('CELLA', cellId);

            if('type' in options){
                var uicell={};
                box._adjustCell(profile, cell, uicell);
                node.parent().replace(profile._buildItems('rows.cells', [uicell]));
            }else
                box._renderCell(profile, cell, node, options);

            profile.boxing().afterCellUpdated(profile,cell, options);

            //if update value
            if('value' in options){
                if(dirtyMark===false)
                    cell._$value=cell.value;
                else{
                    if(cell.value===cell._$value)
                        node.removeClass('ui-dirty');
                    else
                        node.addClass('ui-dirty');
                }
            }
        },
        _ensureValue:function(profile,value){
            if(profile.properties.selMode=='multi'){
                var arr = (value||"").split(';');
                arr.sort();
                return arr.join(';');
            }else
                return value;
        },
        _sel:function(profile, type, src, id, e){
            var properties=profile.properties;
            if(properties.activeMode!=type)return;

            var targetId = profile.getSubId(id),
                map = type=='cell'?profile.cellMap:profile.rowMap,
                box=profile.boxing(),
                targetItem=map[targetId],
                ks=linb.Event.getKey(e),
                sid=type=='cell'?(targetItem._row.id+'|'+targetItem._col.id):targetItem.id,
                mode=properties.selMode,
                rt,rt2;
            switch(mode){
            case 'none':
                rt=box.onRowSelected(profile, targetItem, src);
                break;
            case 'multi':
                var value = box.getUIValue(),
                    arr = value?value.split(';'):[];
                if(arr.length&&(ks[1]||ks[2]||properties.noCtrlKey)){
                    //for select
                    rt2=false;
                    //todo: give cell multi selection function
                    if(ks[2] && type=='row'){
                        if(profile.$firstV._pid!=targetItem._pid)return false;
                        var items=properties.rows;
                        if(targetItem._pid){
                            var pitem=map[targetItem._pid];
                            if(pitem)items=pitem.sub;
                        }
                        var i1=_.arr.subIndexOf(items,'id',profile.$firstV.id),
                            i2=_.arr.subIndexOf(items,'id',targetItem.id),
                            i;
                        arr.length=0;
                        for(i=Math.min(i1,i2);i<=Math.max(i1,i2);i++)
                            arr.push(items[i].id);
                    }else{
                        if(_.arr.indexOf(arr,sid)!=-1)
                            _.arr.removeValue(arr,sid);
                        else
                            arr.push(sid);
                    }

                    arr.sort();
                    value = arr.join(';');

                    //update string value only for setCtrlValue
                    if(box.getUIValue() == value)
                        rt=false;
                    else{
                        box.setUIValue(value);
                        if(box.getUIValue() == value)
                            rt=box.onRowSelected(profile, targetItem, src);
                    }
                    break;
                }
            case 'single':
                if(box.getUIValue() == sid)
                    rt=false;
                else{
                    profile.$firstV=targetItem;
                    box.setUIValue(sid);
                    if(box.getUIValue() == sid)
                        rt=box.onRowSelected(profile, targetItem, src)||rt2;
                }
                break;
            }
            return rt;

        },
        _activeCell:function(profile, id){
            if(profile.properties.activeMode!='cell')return;

            var targetId = profile.getSubId(id),
                map = profile.cellMap,
                targetCell=map[targetId];

            if(profile.beforeCellActive && (false===profile.boxing().beforeCellActive(profile, targetCell)))return;

            if(profile.$activeCell)
                linb(profile.$activeCell).tagClass('-active', false);
            linb(profile.$activeCell=id).tagClass('-active');

            profile.boxing().afterCellActive(profile, targetCell);
        },
        _activeRow:function(profile, id){
            if(profile.properties.activeMode!='row')return;

            var targetId = profile.getSubId(id),
                map = profile.rowMap,
                targetRow=map[targetId];

            //before event
            if(profile.beforeRowActive && (false===profile.boxing().beforeRowActive(profile, targetRow)))return;

            if(profile.$activeRow)
               linb(profile.$activeRow).tagClass('-active', false);
            linb(profile.$activeRow = id).tagClass('-active');

            //after event
            profile.boxing().afterRowActive(profile, targetRow);

        },
        getCellPro:function(profile, cell, key){
            var t=cell;
            return (key in t)?t[key]:((t=cell._row)&&(key in t))? t[key]:((t=cell._col)&&(key in t))?t[key]:((t=profile.properties)&&(key in t))?t[key]:null;
        },
        _editCell:function(profile, cellId){
            var cell = typeof cellId=='string'?profile.cellMap[cellId]:cellId;
            if(!cell)return;

            var cellNode = profile.getSubNode('CELL', cellId),
                editor = profile.$curEditor;

            //clear the prev editor
            if(editor)
                _.tryF(editor.undo,[],editor);

            editor=null;

            //if beforeIniEditor doesn't return an editor
            var grid = this,
                baseNode = profile.getSubNode('SCROLL'),
                box=profile.box,
                getPro=function(key){return box.getCellPro(profile, cell, key)},
                type=getPro('type'),
                t;

            if(type=='checkbox'){
                cellNode.first().focus();
                return;
            }else if(type=='button'||type=='label')
                return;

            //try to get editor from cache
            //triggers beforeIniEditor event once only if the editor is a linb.UI.ComboInput/Input.
            if(profile.$cache_editor[type])
                editor=profile.$cache_editor[type];
            //create editor
            else{
                //beforeIniEditor, return false or a editor(linb.UI object)
                if(profile.beforeIniEditor){
                    editor=profile.boxing().beforeIniEditor(profile, cell, cellNode);
                    //handler editor by yourself
                    if(editor===false)
                        return;
                }
                if(!editor || !editor['linb.UI'])
                    editor=new linb.UI.ComboInput({left:-1000,top:-1000,position:'absolute',visibility:'hidden',zIndex:100});
                switch(type){
                    case 'number':
                        editor.setType('none').setCustomStyle('INPUT',"text-align:right;").setValueFormat("^-?(\\d\\d*\\.\\d*$)|(^-?\\d\\d*$)|(^-?\\.\\d\\d*$)");
                        break;
                    case 'progress':
                        editor.setType('none').setValueFormat("^(0([\\.]\\d*[0-9]+)|0|1)$").setCustomStyle('INPUT',"text-align:right;");
                        break;
                    case 'input':
                        editor.setType('none');
                        break;
                    case 'textarea':
                        editor.setType('none').setMultiLines(true).setSaveBtn(true).onSave(function(p){
                            p.boxing().hide();
                        });
                        _.tryF(editor.setResizer,[true],editor);
                        break;
                    case 'listbox':
                    case 'combobox':
                    case 'helpinput':
                    case 'timepicker':
                    case 'datepicker':
                    case 'colorpicker':
                    case 'getter':
                    case 'popbox':
                    case 'cmdbox':
                        editor.setType(type).beoforeComboPop(function(pro, pos, e, src){
                            var cell=pro.$cell,event=profile.box.getCellPro(profile, cell, 'event');
                            if(profile.box.getCellPro(profile, cell,'disabled'))
                                return false;
                            if(typeof event == 'function')
                                return event.call(profile._host||profile, profile, cell, pro, pos,e,src);
                            else
                                return profile.boxing().beoforeComboPop(profile, cell, pro, pos, e, src);
                        });
                        break;
                }
                baseNode.append(editor);
                //cache the editor
                profile.$cache_editor[type] = editor;
            }

            //set properities
            switch(type){
                case 'listbox':
                case 'combobox':
                case 'helpinput':
                    //set properties
                    if(t=getPro('editorListKey'))
                        editor.setListKey(t);
                    else if(t=getPro('editorListItems'))
                        editor.setItems(t);
                    break;
            }
            //$editorValue must be set in beforeIniEditor
            editor.setValue(cell.$editorValue||cell.value,true);
            delete cell.$editorValue;

            var editorFormat = getPro('editorFormat'),
                editorMask =  getPro('editorMask'),
                editorReadonly = getPro('editorReadonly');

            //$tag
            if(cell.$tag){
                if(editor.setCaption)editor.setCaption(cell.$tag);
                else if(editor.setValue)editor.setValue(cell.$tag);
            }
            if(editor.setReadonly){
                editor.setReadonly(!!editorReadonly);
            }
            if(editorFormat){
                if(typeof editorFormat=='function' && editor.beforeFormatCheck)
                    editor.beforeFormatCheck(editorFormat);
                else if(typeof editorFormat=='string' && editor.setValueFormat)
                    editor.setValueFormat(editorFormat);
            }
            if(editorMask && editor.setMask){
                editor.setMask(editorMask);
            }

            //give a reference
            editor.get(0).$cell = cell;
            //undo function is a must
            editor.undo=function(){
                var editor=this;
                profile.$curEditor=null;

                editor.getRoot().setBlurTrigger(profile.$linbid);
                if(!profile.properties.directInput){
                    editor.afterUIValueSet(null).beforeNextFocus(null);
                    if(editor.beforeFormatCheck)editor.beforeFormatCheck(null);
                    if(editor.setValueFormat)editor.setValueFormat('');
                    if(editor.setMask)editor.setMask('');
                    editor.setValue('',true);
                }
                delete editor.get(0).$cell;
                //don't use disply:none, firfox has many bugs about Caret or renderer
                editor.reBoxing().hide();
            };

            //editor change value, update cell value
            editor
            .afterUIValueSet(function(pro,oV,nV){
                if(getPro('type')=='number')nV=parseFloat(nV);
                grid._updCell(profile, cellId, {value:nV, $caption:pro.$caption});
            })
            .beforeNextFocus(function(pro, key, shift, e){
                if(editor){
                    _.tryF(editor.undo,[],editor);
                    var hash=linb.Event.getEventPara(e);
                    if(hash.keyCode=='enter')hash.keyCode='down';

                    profile.getSubNode('CELLA', cell._serialId).onKeydown(true,hash);
                }
                //prevent
                return false;
            })
            .getRoot().setBlurTrigger(profile.$linbid, function(){
                if(editor)
                    _.tryF(editor.undo,[],editor);
                return false;
            });

            var absPos=cellNode.offset(null, baseNode),
                size = cellNode.cssSize();
            //show editor
            if(type=='textarea'){
                editor.setWidth(Math.max(200,size.width+3)).setHeight(Math.max(100,size.height+2))
                .reLayout(true,true)
                .reBoxing()
                .popToTop(cellNode, 4, baseNode);
            }else{
                editor.setWidth(size.width+3).setHeight(size.height+2).reLayout(true);
                editor.reBoxing().show((absPos.left-1) + 'px',(absPos.top-1) + 'px');
            }

            //give a reference
            profile.$curEditor=editor;

            //activate editor
            _.asyRun(function(){
                _.tryF(editor&&editor.activate,[],editor);
            });
        },
        _ajdustBody:function(profile){
            _.resetRun(profile.$linbid+'4',function(){
                var body=profile.getSubNode('BODY'),
                    header=profile.getSubNode('HCELLS'),
                    t,l,last,keys=profile.keys;
                if(body.get(0).offsetHeight){
                    if(header.get(0).offsetHeight){
                        if(t=header.get(0).childNodes){
                            l=t.length;
                            while(l){
                                if(t[l-1].offsetHeight){
                                    last=t[l-1];
                                    break;
                                }
                                --l;
                            }
                        }
                        //set HI node
                        header.parent().width(last.offsetWidth+last.offsetLeft+100);
                    }else{
                        if(t=body.get(0).childNodes){
                            l=t.length;
                            while(l){
                                if(t[l-1].offsetHeight){
                                    last=t[l-1];
                                    break;
                                }
                                --l;
                            }
                            if(last){
                                var sid=profile.getSubId(last.id);
                                t=profile.getSubNode('CELLS',sid);
                                if(t=t.get(0).childNodes){
                                    l=t.length;
                                    while(l){
                                        if(t[l-1].offsetHeight){
                                            last=t[l-1];
                                            break;
                                        }
                                        --l;
                                    }
                                }
                            }
                        }
                    }
                }
                body.width(last?(last.offsetWidth+last.offsetLeft):0);
                t=last=null;
            });
        },
        _adjustHeader:function(arr){
            var a=_.copy(arr),m;
            _.arr.each(a,function(o,i){
                //id will be adjusted in _prepareHeader
                a[i]=_.copy(o);
            });
            return a;
        },
        _adjustRows:function(arr){
            var a,m;
            if(_.isArr(arr) && arr.length && typeof arr[0] !='object')a=[arr];
            else a=_.copy(arr);

            _.arr.each(a,function(o,i){
                //id will be adjusted in _prepareItems
                if(_.isArr(o))
                    a[i]={cells:o};
                else a[i]=_.copy(o);

                m=a[i].cells=_.copy(a[i].cells);
                _.arr.each(m,function(o,i){
                    //no need "id" in cell
                    if(typeof o!='object')
                        m[i]={value:o};
                    else
                        m[i]=_.copy(o);
                })
            });
            return a;
        },

        _showTips:function(profile, node, pos){
            if(profile.onShowTips)
                return profile.boxing().onShowTips(profile, node, pos);
            if(!linb.Tips)return;

            var ks=profile.keys,item,hcell=ks.HCELL+':',sid,id,pid;
            if(profile.properties.disabled)return;

            id=node.id;
            pid=node.parentNode.id;
            sid=profile.getSubId(id);

            if(id.indexOf(ks.FCELL)==0 || pid.indexOf(ks.FCELL)==0)
                item = profile.rowMap[sid];
            else if(id.indexOf(ks.HCELL)==0 || pid.indexOf(ks.HCELL)==0)
                item = profile.colMap[sid];
            else if(id.indexOf(ks.CELL)==0 || pid.indexOf(ks.CELL)==0)
                item = profile.cellMap[sid];

            if(item){
                linb.Tips.show(pos, ('tips' in item)?item.tips:(item._$tips||item.caption));
            }else
                linb.Tips.hide();
            return true;
        },
        _onresize:function(profile,width,height){
            profile.getSubNode('BORDER').cssSize({ width :width, height :height});
            var t1=profile.getSubNode('HEADER'),
                t2=profile.getSubNode('SCROLL'),
                rh=0;
            profile.getSubNode('BOX').cssSize({width: width, height:height});
            if(width)t1.width(width);
            if(height)rh=t1.offsetHeight();
            t2.cssSize({width:width, height: height?(height-rh):null});

            _.asyRun(function(){t2.onScroll()});
        }
   }
});
Class("linb.UI.Slider", ["linb.UI","linb.absValue"],{
    Instance:{
        _setCtrlValue:function(value){
            return this.each(function(profile){
                var p=profile.properties,
                    steps=p.steps,
                    fun=function(k){return profile.getSubNode(k)},
                    a=fun('IND1'),
                    b=fun('IND2'),
                    arr = profile.box._v2a(profile,value),
                    ori=p.type=='vertical'?'top':'left';
                a[ori](arr[0]+'%');
                if(p.isRange)
                    b[ori](arr[1]+'%');
            });
        },
        _setDirtyMark:function(){
            return this.each(function(profile){
                if(!profile.properties.dirtyMark)return;
                if(!profile.renderId)return;
                var properties = profile.properties,
                    flag=properties.value !== properties.$UIvalue;

                if(profile._dirtyFlag==flag)return;
                profile._dirtyFlag=flag;
                    
                var o=profile.getSubNode('BOX'),
                    cls=linb.UI.$css_tag_dirty;

                if(profile.beforeDirtyMark && false===profile.boxing().beforeDirtyMark(profile,flag))
                    return;

                if(flag)
                    o.addClass(cls);
                else
                    o.removeClass(cls);
            });
        }
    },
    Static:{
        Templates:{
            style:'{_style}',
            BOX:{
                tagName:'div',
                className:'{_cls}',
                BG:{
                    tagName:'div'
                },
                RULER:{
                    $order:1,
                    tagName:'div',
                    RULERLEFT:{},
                    RULERRIGHT:{}
                },
                IND:{
                    $order:2,
                    IND1:{
                        tagName:'a',
                        style:'{_showD}',
                        href:linb.$href,
                        tabindex:'{tabIndex}'
                    },
                    IND2:{
                        tagName:'a',
                        href:linb.$href,
                        tabindex:'{tabIndex}',
                        style:'{_showD2}'
                    }
                },
                DECREASE:{
                    tagName:'a',
                    style:'{_showDes}',
                    href:linb.$href,
                    tabindex:'{tabIndex}'
                },
                INCREASE:{
                    tagName:'a',
                    style:'{_showIns}',
                    href:linb.$href,
                    tabindex:'{tabIndex}'
                }
            }
        },
        Appearances:{
            'IND, BT, RULER, RULERLEFT, RULERRIGHT, IND1, IND2, DECREASE, INCREASE':{
                'font-size':0,
                'line-height':0,
                position:'absolute'
            },
            BOX:{
                position:'relative',
                left:0,
                top:0,
                width:'100%',
                height:'100%'
            },
            'BOX-h DECREASE, BOX-h INCREASE':{
                top:'50%',
                width:'17px',
                height:'17px',
                'margin-top':'-8px'
            },            
            'BOX-v DECREASE, BOX-v INCREASE, BOX-h DECREASE, BOX-h INCREASE, BOX-h IND1,BOX-h IND2, BOX-v IND1,BOX-v IND2':{
                background: linb.UI.$bg('icons.gif', 'no-repeat',true)
            },
            'BOX-h DECREASE':{
                $order:1,
                left:0,
                'background-position': '-80px -70px'
            },
            'BOX-h INCREASE':{
                $order:1,
                right:0,
                'background-position': '-100px -70px'
            },
            'BOX-h DECREASE-mouseover':{
                $order:2,
                'background-position':'-80px -90px'
            },
            'BOX-h DECREASE-mousedown':{
                $order:3,
                'background-position':'-80px -110px'
            },
            'BOX-h INCREASE-mouseover':{
                $order:2,
                'background-position':'-100px -90px'
            },
            'BOX-h INCREASE-mousedown':{
                $order:3,
                'background-position':'-100px -110px'
            },
            'BOX-h BG':{
                top:'50%'                
            },
            'BOX-h IND, BOX-h RULER':{
                'z-index':1,
                top:'50%',
                height:'6px',
                'margin-top':'-3px'
            },
            'BOX-h RULER, BOX-h RULERLEFT, BOX-h RULERRIGHT':{
                background: linb.UI.$bg('bar_vertical.gif', 'repeat-x',true)
            },
            'BOX-h RULER':{
                $order:2,
                'background-position':'left -482px'
            },
            'BOX-h RULERLEFT, BOX-h RULERRIGHT':{
                'z-index':1,
                height:'6px',
                width:'5px'
            },
            'BOX-h RULERLEFT':{
                $order:2,
                'background-position':'left -474px',
                left:'-4px',
                top:0
            },
            'BOX-h RULERRIGHT':{
                $order:2,
                'background-position':'left -490px',
                right:'-4px',
                top:0
            },
            'BOX-h IND1,BOX-h IND2':{
                $order:1,
                'z-index':2,
                'background-position': '-21px -282px',
                height:'18px',
                width:'8px',
                left:0,
                top:0,
                'margin-top':'-6px'
            },
            'BOX-h IND1-mouseover,BOX-h IND2-mouseover':{
                $order:2,
                'background-position':'-31px -282px'
            },
            'BOX-h IND1-mousedown,BOX-h IND2-mousedown':{
                $order:3,
                'background-position':'-41px -282px'
            },

            'BOX-v DECREASE, BOX-v INCREASE':{
                $order:10,
                left:'50%',
                width:'17px',
                height:'17px',
                'margin-left':'-8px'
            },            
            'BOX-v DECREASE':{
                $order:10,
                top:0,
                'background-position': '-120px -70px'
            },
            'BOX-v INCREASE':{
                $order:10,
                bottom:0,
                'background-position': '-140px -70px'
            },
            'BOX-v DECREASE-mouseover':{
                $order:11,
                'background-position':'-120px -90px'
            },
            'BOX-v DECREASE-mousedown':{
                $order:12,
                'background-position':'-120px -110px'
            },
            'BOX-v INCREASE-mouseover':{
                $order:11,
                'background-position':'-140px -90px'
            },
            'BOX-v INCREASE-mousedown':{
                $order:12,
                'background-position':'-140px -110px'
            },
            'BOX-v BG':{
                $order:10,
                left:'50%'                
            },
            'BOX-v IND, BOX-v RULER':{
                $order:10,
                'z-index':1,
                left:'50%',
                width:'6px',
                'margin-left':'-3px'
            },
            'BOX-v RULER, BOX-v RULERLEFT, BOX-v RULERRIGHT':{
                background: linb.UI.$bg('bar_horizontal.gif', 'repeat-y',true)
            },
            'BOX-v RULER':{
                $order:10,
                'background-position':'-482px top'
            },
            'BOX-v RULERLEFT, BOX-v RULERRIGHT':{
                $order:10,
                'z-index':1,
                width:'6px',
                height:'5px'
            },
            'BOX-v RULERLEFT':{
                $order:12,
                'background-position':'-490px top',
                top:'-4px',
                left:0
            },
            'BOX-v RULERRIGHT':{
                $order:12,
                'background-position':'-474px top',
                bottom:'-4px',
                left:0
            },
            'BOX-v IND1,BOX-v IND2':{
                $order:10,
                'z-index':2,
                'background-position': 'left -272px',
                width:'18px',
                height:'8px',
                left:0,
                top:0,
                'margin-left':'-6px'
            },
            'BOX-v IND1-mouseover,BOX-v IND2-mouseover':{
                $order:11,
                'background-position':'left -282px'
            },
            'BOX-v IND1-mousedown,BOX-v IND2-mousedown':{
                $order:12,
                'background-position':'left -292px'
            }
        },
        Behaviors:{
            HoverEffected:{IND1:'IND1',IND2:'IND2',DECREASE:'DECREASE',INCREASE:'INCREASE'},
            ClickEffected:{IND1:'IND1',IND2:'IND2',DECREASE:'DECREASE',INCREASE:'INCREASE'},
            onSize:linb.UI.$onSize,
            IND:{
                onClick:function(profile, e, src){
                    var p=profile.properties,
                        p1=linb.use(src).offset(),
                        p2=linb.Event.getPos(e),
                        arr=profile.box._v2a(profile,profile.properties.$UIvalue),
                        i1,i2,
                        type=p.type=='vertical',
                        k1=type?'top':'left',
                        k2=type?'offsetTop':'offsetLeft',
                        k3=type?'offsetHeight':'offsetWidth',
                        cur=p2[k1]-p1[k1],
                        v=(cur/linb.use(src).get(0)[k3])*100;
                    if(!p.isRange)
                        arr[0]=v;
                    else{
                        i1=profile.getSubNode('IND1')[k2](),
                        i2=profile.getSubNode('IND2')[k2]();
                        if(Math.abs(i1-cur)<Math.abs(i2-cur))
                            arr[0]=v;
                        else arr[1]=v;
                    }
                    profile.boxing().setUIValue(profile.box._adjustValue(profile,arr));
                }
            },
            IND1:{
                onKeydown:function(profile, e, src){
                    var p=profile.properties,
                        type=p.type=='vertical',
                        key=linb.Event.getKey(e)[0];
                    if(key==(type?'up':'left'))
                        profile.box._auto(profile, false);
                    if(key==(type?'down':'right'))
                        profile.box._auto(profile, true);
                },
                onKeyout:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onKeyup:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMousedown:function(profile, e, src){
                    var p=profile.properties,
                        type=p.type=='vertical',
                        k2=type?'offsetTop':'offsetLeft',
                        k3=type?'offsetHeight':'offsetWidth',
                        box=profile.box;
                    linb.use(src).startDrag(e,{
                        widthIncrement:p.steps?profile._size/p.steps:null,
                        dragType:'none',
                        targetReposition:true,
                        horizontalOnly:type?true:null,
                        verticalOnly:type?null:true,
                        maxLeftOffset: linb.use(src).get(0)[k2],
                        maxRightOffset: linb.use(src).parent().get(0)[k3]-linb.use(src).get(0)[k2],
                        dragCursor:'default'
                    });

                    linb.use(src).css('zIndex',10).focus();
                    profile.getSubNode('IND2').css('zIndex',5);
                },
                beforeDragbegin:function(profile, e, src){
                    var type=profile.properties.type=='vertical';
                    linb(src)[type?'top':'left'](profile.__x=linb.use(src).get(0)[type?'offsetTop':'offsetLeft']);
                },
                onDrag:function(profile, e, src){
                    var offset=linb.DragDrop.getProfile().offset,
                        type=profile.properties.type=='vertical',
                        arr=profile.box._v2a(profile,profile.properties.$UIvalue);
                    arr[0]=((profile.__x+offset[type?'y':'x'])/linb.use(src).parent().get(0)[type?'offsetHeight':'offsetWidth'])*100;
                    profile.boxing().setUIValue(profile.box._adjustValue(profile,arr));
                },
                onDragstop:function(profile, e, src){
                    linb(src).onMouseout(true,{$force:true}).onMouseup(true);
                },
                onClick:function(){return false}
            },
            IND2:{
                onKeydown:function(profile, e, src){
                    var p=profile.properties,
                        type=p.type=='vertical',
                        key=linb.Event.getKey(e)[0];
                    if(key==(type?'up':'left'))
                        profile.box._auto(profile, false);
                    if(key==(type?'down':'right'))
                        profile.box._auto(profile, true);
                },
                onKeyout:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onKeyup:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMousedown:function(profile, e, src){
                    var p=profile.properties,
                        type=p.type=='vertical',
                        k2=type?'offsetTop':'offsetLeft',
                        k3=type?'offsetHeight':'offsetWidth',
                        box=profile.box;
                    linb.use(src).startDrag(e,{
                        widthIncrement:p.steps?profile._size/p.steps:null,
                        dragType:'none',
                        targetReposition:true,
                        horizontalOnly:type?true:null,
                        verticalOnly:type?null:true,
                        maxLeftOffset: linb.use(src).get(0)[k2],
                        maxRightOffset: linb.use(src).parent().get(0)[k3]-linb.use(src).get(0)[k2],
                        dragCursor:'default'
                    });

                    linb.use(src).css('zIndex',10).focus();
                    profile.getSubNode('IND1').css('zIndex',5);
                },
                beforeDragbegin:function(profile, e, src){
                    var type=profile.properties.type=='vertical';
                    linb(src)[type?'top':'left'](profile.__x=linb.use(src).get(0)[type?'offsetTop':'offsetLeft']);

                },
                onDrag:function(profile, e, src){
                    var offset=linb.DragDrop.getProfile().offset,
                        type=profile.properties.type=='vertical',
                        arr=profile.box._v2a(profile,profile.properties.$UIvalue);
                    arr[1]=((profile.__x+offset[type?'y':'x'])/linb.use(src).parent().get(0)[type?'offsetHeight':'offsetWidth'])*100;
                    profile.boxing().setUIValue(profile.box._adjustValue(profile,arr));
                },
                onDragstop:function(profile, e, src){
                    linb(src).onMouseout(true,{$force:true}).onMouseup(true);
                },
                onClick:function(){return false}
            },
            RULERRIGHT:{
                onClick:function(profile, e, src){
                    var p=profile.properties,
                        b=profile.boxing(),
                        c=profile.box,
                        arr=c._v2a(profile,p.$UIvalue);
                    if(!p.isRange)
                        arr[0]=100;
                    else
                        arr[1]=100;
                    b.setUIValue(profile.box._adjustValue(profile,arr));
                }
            },
            DECREASE:{
                onMousedown:function(profile){
                    profile.box._auto(profile, false);
                },
                onMouseout:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMouseup:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                }
            },
            INCREASE:{
                onMousedown:function(profile){
                    profile.box._auto(profile, true);
                },
                onMouseout:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMouseup:function(profile){
                    linb.Thread.abort(profile.$linbid+':auto');
                }
            }
        },
        DataModel:{
            position:'absolute',
            width:{
                ini:200
            },
            height:{
                ini:50
            },
            steps:0,
            value:'0:0',
            type:{
                listbox:['vertical', 'horizontal'],
                ini:'horizontal',
                action:function(v){
                    this.boxing().refresh();
                }
            },
            isRange:{
                ini:true,
                action:function(v){
                    this.boxing().refresh();
                }
            },
            showIncreaseHandle:{
                ini:true,
                action:function(v){
                    this.boxing().refresh();
                }
            },
            showDecreaseHandle:{
                ini:true,
                action:function(v){
                    this.boxing().refresh();
                }
            }
        },
        _prepareData:function(profile){
            var d=arguments.callee.upper.call(this, profile),
                N='display:none';
            d._showDes=d.showDecreaseHandle?'':N,
            d._showIns=d.showIncreaseHandle?'':N,
            d._showD2=d.isRange?'':N;
            d._cls=profile.getClass('BOX',d.type=='vertical'?'-v':'-h');
            return d;
        },
        _adjustValue:function(profile,value){
            var p = profile.properties,
                b=[];
            b[0]=parseFloat(value[0])||0;
            b[1]=parseFloat(value[1])||0;
            if(p.steps){
                value=100/p.steps;
                b[0]=Math.ceil(b[0]/value);
                if(p.isRange)
                    b[1]=Math.ceil(b[1]/value);
            }
            return b.join(':');
        },
        _ensureValue:function(profile, value){
            var p = profile.properties,
                a = String(value).split(':'),
                min=0,
                max=p.steps?p.steps:100,
                b=[],
                f1=function(a){return parseFloat(a)||0},
                f2=function(a){return Math.min(max, Math.max(min,a))};
            b[0]= f1(a[0]);
            if(p.isRange){
                b[1]= f1(a[1]);
                if(b[0]>b[1]){
                    a=b[1];
                    b[1]=b[0];
                    b[0]=a;
                }
            }
            b[0]= f2(b[0]);
            if(p.isRange)
                b[1]= f2(b[1]);
            return p.isRange?b.join(':'):(b[0]+'');
        },
        _v2a:function(profile,v){
            var steps=profile.properties.steps,t;
            v = typeof v == 'string'? v.split(':') : v;
            v[0]=parseFloat(v[0])||0;v[1]=parseFloat(v[1])||0;
            if(steps)v[0]=v[0]*100/steps;
            if(steps)v[1]=v[1]*100/steps;
            if(v[0]>v[1]){
                t=v[0];
                v[1]=v[0];
                v[0]=t;
            }
            return v;
        },
        _auto:function(profile, flag){
            var id=profile.$linbid+':auto';
            if(linb.Thread.isAlive(id))return;
            var p=profile.properties,t,
                //%
                off=(p.steps?100/p.steps:1)*(flag?1:-1),
                task={delay:300},
                arr=profile.box._v2a(profile,p.$UIvalue),
                fun=function(){
                    arr[0] += off;
                    if(p.isRange)
                        arr[1] += off;
                    profile.boxing().setUIValue(profile.box._adjustValue(profile,arr));
                    task.delay *=0.8;
                };
            task.task=fun;
            linb.Thread(id,[task],500,null,fun,null,true).start();
        },
        _onresize:function(profile, width, height){
            var p=profile.properties,
            type=p.type,
            f=function(k){return profile.getSubNode(k)},

            ruler=f('RULER'),
            ind=f('IND'),

            ru1=f('RULERLEFT');
            if(type=='vertical'){
                var w=ru1.height(),
                w1=p.showDecreaseHandle?f('DECREASE').height():0,
                w2=p.showIncreaseHandle?f('INCREASE').height():0,
                w3=f('IND1').height();
    
                if(height){
                    ruler.top(w1+w).height(height-w1-w2-2*w);
                    ind.top(w1).height(profile._size=height-w1-w2-w3);
                }
            }else{
                var w=ru1.width(),
                w1=p.showDecreaseHandle?f('DECREASE').width():0,
                w2=p.showIncreaseHandle?f('INCREASE').width():0,
                w3=f('IND1').width();
    
                if(width){
                    ruler.left(w1+w).width(width-w1-w2-2*w);
                    ind.left(w1).width(profile._size=width-w1-w2-w3);
                }
            }
        }
    }
});Class("linb.UI.Dialog","linb.UI.Widget",{
    Instance:{
        show:function(parent, modal, left, top){
            parent = parent || linb('body');
            return this.each(function(profile){
                var t,
                    pro=profile.properties,
                    instance = profile.boxing(),
                    fun = function(){
                        var ins=profile.boxing();
                        if(left||left===0)
                            ins.setLeft(left);
                        if(top||top===0)
                            ins.setTop(top);

                        parent.append(ins);

                        var box=profile.box,
                            root=profile.getRoot();

                        root.show(left?(parseInt(left)||0)+'px':null, top?(parseInt(top)||0)+'px':null);

                        if(modal && !profile.$inModal)
                            box._modal(profile);

                        ins.activate();

                        if(profile.onShow)profile.boxing().onShow(profile);
                        if(profile.properties.status=='normal')
                            box._refreshRegion(profile);

                        delete profile.inShowing;
                    };

                if(profile.inShowing)return;
                profile.inShowing=1;
                if(t=pro.fromRegion)
                    linb.Dom.animate({border:'dashed 1px #ff0000'},{left:[t.left,pro.left],top:[t.top,pro.top],width:[t.width,pro.width],height:[t.height,pro.height]}, null,fun,360,12,'expoIn').start();
                else
                    fun();
            });
        },
        hide:function(){
            this.each(function(profile){
                var pro=profile.properties,
                    box=profile.box,
                    root=profile.getRoot();

                if(profile.inHiding)return;
                profile.inHiding=1;

                if(profile.$inModal)
                    box._unModal(profile);
                //max has dock prop
                if(pro.status=='max' || pro.status=='min')
                    box._restore(profile);

                root.hide();

                var t=pro.fromRegion, fun=function(){
                    delete profile.inHiding;
                };
                if(t)
                    linb.Dom.animate({border:'dashed 1px #ff0000'},{left:[pro.left,t.left],top:[pro.top,t.top],width:[pro.width,t.width],height:[pro.height,t.height]},  null, fun,360,12,'expoOut').start();
                else
                    fun();
            });
            return this;
        },
        close:function(){
            return this.each(function(profile){
                if(profile.beforeClose && false === profile.boxing().beforeClose(profile))
                    return;
                if(profile.inClosing)return;
                profile.inClosing=1;
                var pro=profile.properties, t=pro.fromRegion, fun=function(){
                    profile.boxing().destroy();
                    delete profile.inClosing;
                };

                if(t)
                    linb.Dom.animate({border:'dashed 1px #ff0000'},{left:[pro.left,t.left],top:[pro.top,t.top],width:[pro.width,t.width],height:[pro.height,t.height]}, null,fun,360,12,'expoOut').start();
                else
                    fun();
            });
        },
        activate:function(flag){
            var profile=this.get(0);
            profile.box._active(profile,flag);
            if(flag!==false){
                //set default focus, the min tabzindex
                _.resetRun("dlg_focus:"+profile.$linbid,function(){profile.getRoot().nextFocus()});
            }
        }
    },
    Initialize:function(){
        var ns=this, t=ns.getTemplate();
        _.merge(t.FRAME.BORDER,{
            TBAR:{
                tagName:'div',
                className:'uibar-top',
                TBART:{
                    cellpadding:"0",
                    cellspacing:"0",
                    width:'100%',
                    border:'0',
                    tagName:'table',
                    className:'uibar-t',
                    TBARTR:{
                        tagName:'tr',
                        TBARTDL:{
                            tagName:'td',
                            className:'uibar-tdl'
                        },
                        TBARTDM:{
                            $order:1,
                            width:'100%',
                            tagName:'td',
                            className:'uibar-tdm'
                        },
                        TBARTDR:{
                            $order:2,
                            tagName:'td',
                            className:'uibar-tdr'
                        }
                    }
                },
                BARCMDL:{
                    tagName: 'div',
                    className:'uibar-cmdl',
                    ICON:{
                        $order:0,
                        className:'ui-icon {imageClass}',
                        style:'{backgroundImage} {backgroundPosition} {imageDisplay}'
                    },
                    CAPTION:{
                        $order:1,
                        text:'{caption}'
                    }
                },
                BARCMDR:{
                    tagName: 'div',
                    className:'uibar-cmdr',
                    onselectstart:'return false',
                    unselectable:'on',
                    OPT:{
                        className:'uicmd-opt',
                        style:'{optDisplay}',
                        $order:1
                    },
                    PIN:{
                        $order:2,
                        className:'uicmd-pin',
                        style:'{pinDisplay}'
                    },
                    LAND:{
                        $order:3,
                        className:'uicmd-land',
                        style:'{landDisplay}'
                    },
                    
                    MIN:{
                        $order:4,
                        className:'uicmd-min',
                        style:'{minDisplay}'
                    },
                    RESTORE:{
                        $order:5,
                        className:'uicmd-restore',
                        style:'display:none;'
                    },
                    MAX:{
                        $order:6,
                        className:'uicmd-max',
                        style:'{maxDisplay}'
                    },
                    CLOSE:{
                        $order:7,
                        className:'uicmd-close ',
                        style:'{closeDisplay}'
                    }
                }
            },
            MAIN:{
                $order:2,
                tagName:'div',
                className:'uicon-main',
                MAINI:{
                    tagName:'div',
                    className:'uicon-maini',
                    PANEL:{
                        tagName:'div',
                        text:'{html}'+linb.UI.$childTag
                    }
                }
            },
            BBAR:{
                $order:3,
                tagName:'div',
                className:'uibar-bottom',
                BBART:{
                    cellpadding:"0",
                    cellspacing:"0",
                    width:'100%',
                    border:'0',
                    tagName:'table',
                    className:'uibar-t',
                    BBARTR:{
                        tagName:'tr',
                        BBARTDL:{
                            tagName:'td',
                            className:'uibar-tdl'
                        },
                        BBARTDM:{
                            $order:1,
                            width:'100%',
                            tagName:'td',
                            className:'uibar-tdm'
                        },
                        BBARTDR:{
                            $order:2,
                            tagName:'td',
                            className:'uibar-tdr'
                        }
                    }
                }
            }
        },'all');
        ns.setTemplate(t);
        
        linb.alert=ns.alert;
        linb.confirm=ns.confirm;
        linb.pop=ns.pop;
        linb.prompt=ns.prompt;
    },
    Static:{
        Appearances:{
            KEY:{
                overflow:'visible'
            },
            PANEL:{
                position:'relative',
                overflow:'auto',
                'font-size':'12px',
                'line-height':'14px'
            },
            CAPTION:{
                'font-size':'12px',
                display:'inline',
                'vertical-align':'middle'
            },
            BORDER:{
                position:'relative',
                'font-size':0,
                'line-height':0
            }
        },
        Behaviors:{
            DropableKeys:['PANEL'],
            DragableKeys:['LAND'],
            HoverEffected:{OPT:'OPT', PIN:'PIN',MIN:'MIN',MAX:'MAX',RESTORE:'RESTORE',CLOSE:'CLOSE',LAND:'LAND'},
            ClickEffected:{OPT:'OPT', PIN:'PIN',MIN:'MIN',MAX:'MAX',RESTORE:'RESTORE',CLOSE:'CLOSE',LAND:'LAND'},
            onMousedown:function(profile, e){
                profile.box._active(profile);
            },

            onDragstop:function(profile){
                var pos = profile.getRoot().cssPos(),p=profile.properties;
                p.left = pos.left;
                p.top = pos.top;
            },
            TBAR:{
                onMousedown:function(profile, e, src){
                    if(profile.getKey(linb.Event.getSrc(e).parentNode.id)==profile.keys.BARCMDR)return;

                    if(profile.properties.movable && !profile._locked){
                        profile.box._active(profile);
                        profile.getRoot().startDrag(e, {
                            dragDefer:1,
                            maxTopOffset:profile.getRoot().top(),
                            maxLeftOffset:profile.getRoot().left(),
                            targetOffsetParent:profile.getRoot().parent()
                        });
                    }
                },
                onDblclick:function(profile, e, src){
                    if(profile.getKey(linb.Event.getSrc(e).parentNode.id)==profile.keys.BARCMDR)return;
                    if(!profile.properties.maxBtn)return;
                    if(profile.properties.status=='max')
                        profile.box._restore(profile);
                    else
                        profile.box._max(profile);
                }
            },
            PIN:{
                onClick:function(profile, e, src){
                    var key=profile.keys.PIN, t=profile.properties;
                    //set pinned status
                    t.pinned = !t.pinned;
                    //set appea
                    profile.getSubNode('PIN').tagClass('-checked', t.pinned);
                    //set lock flag for not movable
                    profile._locked = t.pinned;

                    // add/remove resize
                    if(t.resizer){
                        if(!t.pinned){
                            // if not in min mode
                            if(t.status != 'min' && profile.$resizer)
                                profile.$resizer.show();
                        }else
                            if(profile.$resizer)
                                //profile.boxing().setResizer(false);
                                profile.$resizer.hide();
                    }
                }
            },
            MIN:{
                onClick:function(profile, e, src){
                    profile.box._min(profile);
                }
            },
            MAX:{
                onClick:function(profile, e, src){
                    profile.box._max(profile);
                }
            },
            RESTORE:{
                onClick:function(profile, e, src){
                    profile.box._restore(profile);
                }
            },
            OPT:{
                onClick:function(profile, e, src){
                    profile.boxing().onShowOptions(profile, e, src);
                }
            },
            CLOSE:{
                onClick:function(profile, e, src){
                    profile.boxing().close();
                }
            }
        },
        DataModel:{
            tips:null,
            border:null,
            disabled:null,
            dock:{
                hidden:true
            },
            html:{
                action:function(v){
                    this.getSubNode('PANEL').html(v);
                }
            },
            // setCaption and getCaption
            caption:{
                ini:undefined,
                // ui update function when setCaption
                action: function(value){
                    this.getSubNode('CAPTION').get(0).innerHTML = value;
                }
            },
            image:{
                action: function(value){
                    this.getSubNode('ICON')
                        .css('display',value?'':'none')
                        .css('backgroundImage','url('+(value||'')+')');
                }
            },
            imagePos:{
                action: function(value){
                    this.getSubNode('ICON')
                        .css('backgroundPosition', value);
                }
            },
            // setCaption and getCaption
            shadow: true,
            resizer:true,
            movable: true ,

            minBtn:{
                ini:true,
                action:function(v){
                    var o = this.getSubNode('MIN');
                    if(v)
                        o.setInlineBlock();
                    else
                        o.css('display','none');
                }
            },
            maxBtn:{
                ini:true,
                action:function(v){
                    var o = this.getSubNode('MAX');
                    if(v)
                        o.setInlineBlock();
                    else
                        o.css('display','none');
                }
            },
            optBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('OPT').css('display',v?'':'none');
                }
            },
            closeBtn:{
                ini:true,
                action:function(v){
                    var o = this.getSubNode('CLOSE');
                    if(v)
                        o.setInlineBlock();
                    else
                        o.css('display','none');
                }
            },
            pinBtn:{
                ini:true,
                action:function(v){
                    var o = this.getSubNode('PIN');
                    if(v)
                        o.setInlineBlock();
                    else
                        o.css('display','none');
                }
            },
            landBtn:{
                ini:false,
                action:function(v){
                    var o = this.getSubNode('LAND');
                    if(v)
                        o.setInlineBlock();
                    else
                        o.css('display','none');
                }
            },
            width:300,
            height:300,
            minWidth : 200,
            minHeight : 100,

            position:'absolute',
            fromRegion:{
                hidden:true,
                ini:null
            },
            status:{
                ini:'normal',
                listbox:['normal','min','max'],
                action:function(v,o){
                    var self=this, b=self.box;
                    if(v=='min')b._min(self,o);
                    else if(v=='max')b._max(self,o);
                    else b._restore(self,o);
                }
            }
        },
        EventHandlers:{
            onShow:function(profile){},
            beforeClose:function(profile){},
            onShowOptions:function(profile, e, src){}
        },
        RenderTrigger:function(){
            this.destroyTrigger = function(){
                var s=this;
                if(s.$inModal)s.box._unModal(s);
            };
        },
        LayoutTrigger:function(){
            var self=this, t=self.properties, b=self.box;
            if(t.status=='min')
                b._min(self);
            else if(t.status=='max')
                b._max(self);
            else
                linb.UI.$tryResize(self, t.width, t.height);
        },
        _prepareData:function(profile){
            var data = arguments.callee.upper.call(this, profile),
                nodisplay='display:none';
            data.minDisplay = data.minBtn?'':nodisplay;
            data.maxDisplay = data.maxBtn?'':nodisplay;
            data.optDisplay = data.optBtn?'':nodisplay;
            data.closeDisplay = data.closeBtn?'':nodisplay;
            data.pinDisplay = data.pinBtn?'':nodisplay;
            data.landDisplay = data.landBtn?'':nodisplay;
            data.statusDisplay = data.statusDisplay?'':nodisplay;
            data.statusHeight = 'height:'+data.statusHeight+'px';
            var status=profile.properties.status;
            if(status=='min'||status=='max')
                profile.$noR=profile.$noS=1;
            return data;
        },

        //ov from design mode
        _min:function(profile,status){
            var o=profile.getRoot(),
                box=profile.box,
                p=o.parent(),
                t=profile.properties;
            if(!status)status=t.status;
            // unMax
            if(status=='max')
                box._unMax(profile);
            // keep restore values
            else
                box._refreshRegion(profile);

            // hide those
            profile.getSubNodes(['PANEL','STATUS']).css('display','none');

            if(t.minBtn){
                // show restore button
                profile.getSubNode('RESTORE').setInlineBlock();
                // hide min button
                profile.getSubNode('MIN').css('display','none');
            }

            // lockResize function
            if(t.resizer && profile.$resizer)
                profile.$resizer.hide();


            if(t.shadow)
                profile.boxing()._unShadow(false);

            //set it before resize
            t.status='min';

            var h1=o.height(),
                h2=profile.getSubNode('BORDER').height(),
                h=profile.getSubNode('TBAR').height();
            // resize
            o.cssSize({ width :t.minWidth, height :h+h1-h2},true);
        },
        _max:function(profile,status){
            var o=profile.getRoot(),
                box=profile.box,
                ins=profile.boxing(),
                p=o.parent(),
                t=profile.properties;
            if(!status)status=t.status;
            // if from normal status
            if(status=='min')
                //unset min
                box._unMin(profile);
            else
                box._refreshRegion(profile);

            // hide pin button
            if(t.pinBtn)
                profile.getSubNode('PIN').css('display','none');
            if(t.maxBtn){
                // hide max button
                profile.getSubNode('MAX').css('display','none');
                // show restore button
                profile.getSubNode('RESTORE').setInlineBlock();
            }

            // set not movable
            profile.old_m = t.movable;
            t.movable=false;

            if(t.resizer && profile.$resizer)
                profile.$resizer.hide();

            if(t.shadow)
                //ins.setShadow(false);
                ins._unShadow(false);

            t.status='max';

            ins.setDock('fill');
        },
        _restore:function(profile,status){
            var o=profile.getRoot(),
                box=profile.box,
                t=profile.properties;
            if(!status)status=t.status;
            // if from max
            if(status=='max')box._unMax(profile);
            if(status=='min')box._unMin(profile);

            // hide restore button
            profile.getSubNode('RESTORE').css('display','none');

            t.status='normal';
        },
        _unMax:function(profile){
            var t=profile.properties,
                ins=profile.boxing();
            profile.getSubNode('MAX').setInlineBlock();
            if(t.pinBtn)
                profile.getSubNode('PIN').setInlineBlock();

            t.movable=profile.old_m;

            if(t.shadow)
                ins._shadow();

            if(t.resizer && !t.pinned){
                if(profile.$resizer)
                    profile.$resizer.show();
                else
                    ins._resizer();
            }

            ins.setDock('none');

            // resize
            linb.UI.$tryResize(profile, t.width, t.height,true);
        },
        _unMin:function(profile){
            var t=profile.properties,
            ins=profile.boxing();
            profile.getSubNodes(['PANEL','STATUS']).css('display','block');
            profile.getSubNode('MIN').setInlineBlock();

            if(t.shadow)
                ins._shadow();

            if(t.resizer && !t.pinned){
                if(profile.$resizer)
                    profile.$resizer.show();
                else
                    ins._resizer();
            }

            profile.getRoot().cssSize({width:t.width, height:t.height});
            // resize
            linb.UI.$tryResize(profile, t.width, t.height,true);
        },
        _active:function(profile,flag){
            var self=this;
            if(flag!==false && self.activeWndId==profile.$linbid)return;

            self._deActive();
            if(flag!==false){
                var o=linb(profile.domId),
                    //in ie, .children can't get the same thread added node(modal div,  here)
                    t1=o.topZindex(),
                    t2=o.css('zIndex');
                o.css('zIndex',t1>t2?t1:t2);
    
                profile.getSubNode('TBAR').tagClass('-focus');
                self.activeWndId = profile.$linbid;
            }
        },
        _deActive:function(){
            var profile;
            if(profile=linb.UI._cache['$'+this.activeWndId])
                profile.getSubNode('TBAR').tagClass('-focus',false);
            delete this.activeWndId;
        },
        _modal:function(profile){
            var s=profile.getRoot(),temp,p=s.parent(),cover;
            if(!p.isEmpty()){
                if(!profile.$inModal){
                    if(!profile.$modalDiv)
                        profile.$modalDiv=new linb.UI.Div({
                            position:'absolute'
                        }).setCustomStyle({
                            KEY:'overflow:hidden;display:block;z-index:0;cursor:wait;background-image:url('+linb.ini.path+'bg.gif)'
                        });

                    cover = profile.$modalDiv;
                    p.append(cover);
                    cover.setDock('cover',true);
                    cover=cover.reBoxing();
                    cover.css('display','block').onMousedown(function(){return false}).topZindex(true);
                    s.css('zIndex',(parseInt(cover.css('zIndex'))||0)+1);

                    /*
                    //bak dlg tabzindnex
                    var hash={},a=profile.getRoot().query('*',function(o){return o.tabIndex>0}).get();
                    for(var i=0,o;o=a[i++];){
                        (hash[o.tabIndex] = hash[o.tabIndex]||[]).push(o);
                        o.tabIndex=-1;
                    }
                    //save others tabzindex
                    var h = profile.$focusHash={}, b=linb('body').query('*',function(o){return o.tabIndex>0}).get();
                    for(var i=0,o;o=b[i++];){
                        (h[o.tabIndex] = h[o.tabIndex]||[]).push(o);
                        o.tabIndex=-1;
                    }
                    //restore dlg tabzindnex
                    for(var i in hash){
                        h=hash[i];
                        for(var j in h)
                            h[j].tabIndex=i;
                    }
                    */
                    linb.Event.pushTabOutTrigger(profile.renderId, function(){linb([profile.renderId]).nextFocus()});

                    profile.$inModal=true;
                }
            }
        },
        _unModal:function(profile){
            if(profile.$inModal){
                profile.$modalDiv.setDock('none');
                profile.getRoot().css('zIndex',0);
                profile.getSubNode('BORDER').append(profile.$modalDiv.reBoxing().css('display','none'));

                profile.$inModal=false;
                /*
                var hash=profile.$focusHash,h;
                for(var i in hash){
                    h=hash[i];
                    for(var j in h)
                        h[j].tabIndex=i;
                }
                _.breakO(profile.$focusHash,2);
                */
                linb.Event.popTabOutTrigger();
            }
        },
        _refreshRegion:function(profile){
            if(!profile.renderId) return;
            var pro=profile.properties;
            return _.merge(pro, profile.getRoot().cssRegion(), function(o,i){return pro[i]!='auto'});
        },

        _adjust:function(dialog,caption, content, left, top){
            caption = caption ||'';
            if(!content){
                content = caption;
                caption = "";
            }

            var node = dialog.$div.reBoxing(),
            ID='linb:temp:dialog',
            me=arguments.callee,
            w,h;

            if(!linb.Dom.byId(ID)){
                n2 = me._cache=node.clone(false);
                linb('body').append(n2);
                n2.css({width:'auto',height:'auto',overflow:'visible',position:'absolute',visibility:'visible',left:linb.Dom.HIDE_VALUE})
                .id(ID,true);
            }
            var n2 = me._cache;
            n2.html(content,false);
            var size = n2.cssSize();

            node.html(content);

            if(size.width>500){
                size.width=500;
                n2.width(500);
                size.height = n2.offsetHeight() + 10;
                n2.width('auto');
            }
            if(size.height>400)size.height=400;
            if(size.width<150)size.width=150;
            if(size.height<30)size.height=30;

            node.cssSize(size).css('overflow','auto').show();

            w=size.width + 30;
            h=size.height+90;
            dialog.setCaption(caption).setWidth(w).setHeight(h);
            dialog.$cmd.reBoxing().left((size.width + 30 - dialog.$cmd.reBoxing().width())/2);
            
            linb.UI.$doResize(dialog.get(0), w, h);
        },
        alert:function(title, content, onClose, left, top){
            var me=arguments.callee, dialog;
            if(!(dialog=me.dialog) || (!dialog.get(0).renderId)){
                dialog = me.dialog = new linb.UI.Dialog({
                    minBtn:false,
                    maxBtn:false,
                    pinBtn:false,
                    resizer:false,
                    left:200,
                    top:200
                },{
                    beforeClose:function(){
                        dialog.hide();
                        _.tryF(me.onClose);
                        me.onClose=null;
                        return false;
                    }
                });

                var cmd = dialog.$cmd = new linb.UI.Div({
                    bottom:10,
                    width:60,
                    height:24
                }),

                btn = dialog.$btn = new linb.UI.SButton({
                    caption:'$inline.ok',
                    width: 60,
                    tabindex:1
                },
                {
                    onClick:function(){
                        dialog.hide();
                        _.tryF(me.onClose);
                        me.onClose=null;
                    }
                });
                cmd.append(btn);

                var div = dialog.$div = new linb.UI.Div({
                    left:10,
                    top:10
                });
                dialog.append(cmd).append(div).render();
            }
            me.onClose=onClose;
            linb.UI.Dialog._adjust(dialog,title, content);
            dialog.show(linb('body'),true, left, top);
            _.resetRun("dlg_focus:"+dialog.get(0).$linbid,function(){
                dialog.$btn.activate();
            });
            return dialog;
        },
        confirm:function(title, caption, onYes, onNo, left, top){
            var me=arguments.callee, dialog;

            if(!(dialog=me.dialog) || (!dialog.get(0).renderId)){
                dialog = me.dialog = new linb.UI.Dialog({
                    minBtn:false,
                    maxBtn:false,
                    pinBtn:false,
                    resizer:false,
                    left:200,
                    top:200
                },{
                    beforeClose:function(){
                        dialog.hide();
                        _.tryF(me.onNo);
                        me.onYest=me.onNo=null;
                        return false;
                    }
                });

                var cmd = dialog.$cmd=new linb.UI.Div({
                    bottom:10,
                    width:140,
                    height:24
                }),
                btn = new linb.UI.SButton({
                    caption:'$inline.yes',
                    width: 60,
                    tabindex:1,
                    left:0
                },
                {
                    onClick:function(){
                        dialog.hide();
                        _.tryF(me.onYes);
                        me.onYest=me.onNo=null;
                    }
                });
                cmd.append(btn);

                btn = dialog.$btn=new linb.UI.SButton({
                    caption:'$inline.no',
                    tabindex:1,
                    width: 60,
                    left:80
                },
                {
                    onClick:function(){
                        dialog.hide();
                        _.tryF(me.onNo);
                        me.onYest=me.onNo=null;
                    }
                });
                cmd.append(btn);

                var div = dialog.$div=new linb.UI.Div({
                    left:10,
                    top:10
                });
                dialog.append(cmd).append(div).render();
            }
            me.onYes=onYes;
            me.onNo=onNo;
            linb.UI.Dialog._adjust(dialog, title, caption);
            dialog.show(linb('body'), true, left, top);
            _.resetRun("dlg_focus:"+dialog.get(0).$linbid,function(){
                dialog.$btn.activate();
            });
            return dialog;
        },
        pop:function(title, content, cmdStr, left, top){
            var dialog = new linb.UI.Dialog({
                minBtn:false,
                maxBtn:false,
                pinBtn:false,
                resizer:false,
                left:200 || left,
                top:200 || top
            }),

            cmd = dialog.$cmd = new linb.UI.Div({
                bottom:10,
                width:'auto',
                height:24,
                CS:'text-align:center;'
            })
            .append( dialog.$btn = new linb.UI.SButton({
                caption: cmdStr || '$inline.ok',
                tabindex:1,
                position:'relative'
            },
            {
                onClick:function(){
                    dialog.destroy();
                }
            })),

            div = dialog.$div = new linb.UI.Div({
                left:10,
                top:10,
                width:80
            }).setCustomStyle({
                KEY:'overflow:visible'
            });

            dialog.append(cmd).append(div).render();;

            linb.UI.Dialog._adjust(dialog, title, content);
            dialog.show(linb('body'),false,left, top);

            _.resetRun("dlg_focus:"+dialog.get(0).$linbid,function(){
                dialog.$btn.activate();
            });
            return dialog;
        },
        prompt:function(title, caption, content, onYes, onNo, left, top){
            var dialog,
                me=arguments.callee;
            if(!(dialog=me.dialog) || (!dialog.get(0).renderId)){
                var close=function(){
                    me.$inp.setValue('');
                    me.onYes=me.onNo=null;
                    me.dialog.hide();
                    return false;
                };
                dialog = me.dialog = new linb.UI.Dialog({
                    minBtn:false,
                    maxBtn:false,
                    pinBtn:false,
                    resizer:false,
                    left:200,
                    top:200,
                    width:300,
                    height:130
                },{
                    beforeClose:function(){
                        _.tryF(me.onNo);
                        return close();
                    }
                });
                var con = me.$con = new linb.UI.Div({
                    top:4,
                    left:10,
                    width:270,
                    height:18
                }),
                cmd = new linb.UI.Div({
                    top:65,
                    width:270,
                    height:24
                })
                .setCustomStyle('KEY',"text-align:center;")
                .append(new linb.UI.SButton({
                    caption:'$inline.ok',
                    width: 60,
                    left:70,
                    tabindex:1
                },
                {
                    onClick:function(){
                        _.tryF(me.onYes,[me.$inp.getUIValue()]);
                        return close();
                    }
                }));

                cmd.append(new linb.UI.SButton({
                    caption:'$inline.cancel',
                    tabindex:1,
                    left:140,
                    width: 60
                },
                {
                    onClick:function(){
                        _.tryF(me.onNo);
                        return close();
                    }
                }));
                var inp=me.$inp=new linb.UI.Input({
                    left:10,
                    top:22,
                    width:270,
                    height:36,
                    multiLines:true
                })
                dialog.append(con).append(cmd).append(inp).render();
            }
            dialog.setCaption(title||'Prompt');
            me.$con.setHtml(caption||"");
            me.$inp.setValue(content||"",true);
            me.onYes=onYes;
            me.onNo=onNo;

            dialog.show(linb('body'), true, left, top);
            _.resetRun("dlg_focus:"+dialog.get(0).$linbid,function(){
                me.$inp.activate();
            });
            return dialog;
        },
        //
        _onresize:function(profile,width,height,force){
            var size = arguments.callee.upper.apply(this,arguments),
                isize={},
                v1=profile.getSubNode('TBAR'),
                v2=profile.getSubNode('PANEL'),
                v4=profile.getSubNode('BBAR'),
                v5=profile.getSubNode('MAIN'),
                v6=profile.getSubNode('MAINI'),
                h1,h4,t;
            if(height){
                if(height=='auto'){
                    isize.height=height;
                }else{
                    h1=v1.height(), h4=v4.height();
                    if((t=size.height-h1-h4)>0)
                        isize.height=t;
                }
            }

            if(width)
                isize.width=size.width-(parseInt(v6.css('paddingRight'))||0)-(parseInt(v5.css('paddingLeft'))||0);
            v2.cssSize(isize, true);
        }
    }
});
