/*
jsLinb 4.0
Copyright(c) 2011 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){
        if(typeof obj.Dependency == "string")obj.Dependency=[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
    */
    var cf=function(){if(typeof this.initialize=='function')this.initialize()};
    if(typeof obj.Constructor == 'function'){
        _this = env(obj.Constructor, 'Constructor', key, parent0||cf,'constructor');
        _this.Constructor = String(obj.Constructor);
    }else{
        if(parent0){
            // Constructor is for opera, in opear fun.toString can't get arguments sometime
            var f=cf,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,'constructor');
            _this.Constructor = str;
        }else
            _this = cf;
    }

    //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,'static');
    //  from Instance
    if(t=obj.Instance)
        self._wrap(_this.prototype,t,1,_t.prototype,'instance');
    //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;
    _this.prototype.$linb$ = 1;
    //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);
        s.disalbed=true;
        s.disabled=false;
        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||{}, 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);
    },
    asyHTML:function(content, callback, defer, size){
        var div = document.createElement('div'),
            fragment = document.createDocumentFragment();
        div.innerHTML = content;
        (function(){
            var i=size||10;
            while(--i && div.firstChild)
                fragment.appendChild(div.firstChild);
            if(div.firstChild)
                setTimeout(arguments.callee, defer||0);
            else
                callback(fragment);
        })();
    },
    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.exists=function(k){return this.$cache[k]})&& (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;
    },
    toFixedNumber:function(number,digits) {
        if(!_.isSet(digits))digits=2;
        var m=Math.abs(number),
            s=''+Math.round(m * Math.pow(10, digits)),
            v, t, start, end;
        if(/\D/.test(s)){
          v = ""+m;
        }else{
            while(s.length<1+digits)s='0'+s;
            start=s.substring(0, t=(s.length-digits));
            end=s.substring(t);
            if(end)end="."+end;
            v=start+end;
        }
        return parseFloat((number<0?"-":"")+v);
    },
    /*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) {
            return '\\u' + ((b=a.charCodeAt())<16?'000':b<256?'00':b<4096?'0':'')+b.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)
            if(_.isDefined(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('=');
            try{
                hash[decodeURIComponent(arr[0])]=decodeURIComponent(arr[1]);
            }catch(e){
                hash[arr[0]]=arr[1];
            }
        }
        return key?hash[key]:hash;
    },

    // type detection
    isDefined:function(target)  {return target!==undefined},
    isNull:function(target)  {return target===null},
    isSet:function(target)   {return target!==undefined && 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)},
    isFinite:function(target)  {return (target||target===0) && isFinite(target)},
    isDate:function(target)  {return Object.prototype.toString.call(target)==='[object Date]' && isFinite(+target)},
    isFun:function(target)   {return Object.prototype.toString.call(target)==='[object Function]'},
    isArr:function(target)   {return Object.prototype.toString.call(target)==='[object Array]'},
    _ht:/^\s*function\s+Object\(\s*\)/,
    isHash:function(target)  {return !!target && Object.prototype.toString.call(target)=='[object Object]' && target.constructor && _._ht.test(target.constructor.toString())},
    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 str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, '');
        },
        ltrim:function(str){
            return str.replace(/^[\s\xa0]+/,'');
        },
        rtrim:function(str){
            return str.replace(/[\s\xa0]+$/,'');
        },
/*
        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;
        },
        removeDuplicate:function(arr,subKey){
            var l=arr.length,a=arr.concat();
            arr.length=0;
            for(var i=l-1;i>=0;i--){
                if(subKey? this.subIndexOf(a, subKey, a[i][subKey])===i: this.indexOf(a, a[i])===i)
                    arr.push(a[i]);
            }
            return arr.reverse();
        }
    }
});
_.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},
    // give nodeType to avoid breakO
    _reg2:{'nodeType':1,'constructor':1,'prototype':1,'toString':1,'valueOf':1,'hasOwnProperty':1,'isPrototypeOf':1,'propertyIsEnumerable':1,'toLocaleString':1},

    /*envelop a function by some keys
    */
    _fun:function(fun, name, original, upper, type){
        fun.$name$=name;
        fun.$original$=original;
        if(type)fun.$type$=type;
        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, prtt){
        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],prtt);
        }
        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],prtt);
        }
    },
    __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,{
    $DEFAULTHREF:'javascript:;',
    $IEUNSELECTABLE:function(){return linb.browser.ie?' onselectstart="return false;" ':''},
    SERIALIZEMAXLAYER:99,
    SERIALIZEMAXSIZE:9999,

    $localeKey:'en',
    $localeDomId:'linblid',
    $dateFormat:'',

    Locale:{},
    $cache:{
        thread:{},
        SC:{},
        hookKey:{},
        hookKeyUp:{},
        snipScript:{},
        
        subscribes:{},
        
        //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:{}
    },
    subscribe:function(topic, subscriber, receiver, asy){
        if(topic===null||topic===undefined||subscriber===null||subscriber===undefined||typeof receiver!='function')return;
        var c=linb.$cache.subscribes,i;
        c[topic]=c[topic]||[];
        i=_.arr.subIndexOf(c[topic],"id",subscriber);
        if(i!=-1)_.arr.removeFrom(c[topic],i);
        return c[topic].push({id:subscriber,receiver:receiver,asy:!!asy});
    },
    unsubscribe:function(topic, subscriber){
        var c=linb.$cache.subscribes,i;
        if(!subscriber){
            if(topic===null||topic===undefined)
                c={};
            else
                delete c[topic];
        }else if(c[topic]){
            i=_.arr.subIndexOf(c[topic],"id",subscriber);
            if(i!=-1)_.arr.removeFrom(c[topic],i);
        }
    },
    publish:function(topic, args, scope){
        var c=linb.$cache.subscribes;
        if(topic===null||topic===undefined){
            for(var topic in c){
                _.arr.each(c[topic],function(o){
                    if(o.asy)
                        _.asyRun(o.receiver, 0, args, scope);
                    else
                        return _.tryF(o.receiver, args, scope, true);
                });
            }
        }else if(c[topic]){
            _.arr.each(c[topic],function(o){
                if(o.asy)
                    _.asyRun(o.receiver, 0, args, scope);
                else
                    return _.tryF(o.receiver, args, scope, true);
            });
        }
    },
    getSubscribers:function(topic){
        return (topic===null||topic===undefined)?linb.$cache.subscribes:linb.$cache.subscribes[topic];
    },

    setDateFormat:function(format){linb.$dateFormat=format},
    getDateFormat:function(){return linb.$dateFormat},

    setAppLangKey:function(key){linb.$appLangKey=key},
    getAppLangKey:function(key){return linb.$appLangKey},
    getLang:function(){return linb.$localeKey},
    setLang:function(key,callback){
        var g=linb.getRes,t,v,i,j,f,m,z,a=[];
        linb.$localeKey=key;
        v = linb.browser.ie ? document.all.tags('span') : document.getElementsByTagName('span');
        for(i=0;t=v[i];i++)if(t.id==linb.$localeDomId)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);
    },
    _langParamReg:/\x24(\d+)/g,
    _langscMark:/[$@][\S]+/,
    _langReg:/((\$)([^\w]))|((\$)([\w][\w\.]*[\w]+))|((\@)([\w][\w\.]*[\w]+))/g,
    getRes:function(path){
        var arr,conf,tmp,params=arguments;
        if(typeof path=='string'){
            if(path.indexOf('-')!=-1){
                tmp=path.split('-');
                path=tmp[0];
                params=tmp;
            }
            arr=path.split(".");
        }else{
            arr=path;
        }
        conf=_.get(linb.Locale[linb.$localeKey], arr);
        return (tmp=typeof conf)=='string'
               ? ( params.length>1 ? conf.replace(linb._langParamReg,function(z,id,k){k=params[1+ +id];return (k===null||k===undefined)?z:k}) : conf)
               : tmp=='function'
               ? conf.apply(null,params) :
               conf ? conf : arr[arr.length-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.$localeDomId+'" class="'+s+'" '+linb.$IEUNSELECTABLE()+'>'+r+'</span>';
    },
    adjustRes:function(str, wrap){
        wrap=wrap?linb.wrapRes:linb.getRes;
        return linb._langscMark.test(str) ?  str.replace(linb._langReg, function(a,b,c,d,e,f,g,h,i,j){
            return c=='$' ? d : f=='$' ? wrap(g) : i=='@' ? ((j=linb.SC.get(j)) || (_.isSet(j)?j:"")) : a;
            }): str;
    },
    request:function(uri, query, onSuccess, onFail, threadid, options){
        return (
        // specify
        (options&&options.proxyType) ? (options.proxyType.toLowerCase()=="sajax"?linb.SAjax:options.proxyType.toLowerCase()=="iajax"?linb.IAjax:linb.Ajax)
        // include a file => IAjax
        :(typeof query=='object' && ((function(d){if(!_.isHash(d))return 0; for(var i in d)if(d[i]&&d[i].nodeType==1)return 1})(query))) ? linb.IAjax
        // post: crossdomain => IAjax, else Ajax
        : (options&&options.method&&options.method.toLowerCase()=='post') ?  linb.absIO.isCrossDomain(uri) ? linb.IAjax  : linb.Ajax
        // get : crossdomain => SAjax, else Ajax
        : linb.absIO.isCrossDomain(uri) ? linb.SAjax : linb.Ajax

        ).apply(null, arguments).start()
    },
    include:function(id,path,onSuccess,onFail,sync){
        if(id&&linb.SC.get(id))
            _.tryF(onSuccess);
        else{
            if(!sync)
                linb.SAjax(path,'',onSuccess,onFail,0,{rspType:'script',checkKey:id}).start()
            else
                linb.Ajax(path,'',function(rsp){
                    try{_.exec(rsp)}
                    catch(e){_.tryF(onFail,[e.name + ": " + e.message])}
                    _.tryF(onSuccess);
                },onFail,0,{asy:!sync}).start();
        }
    },
    require:function(cls,sync,onSuccess,onFail){
        linb.include(cls,linb.getPath(cls,".js","js"),onSuccess,onFail,sync);
    },
    /*
    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 + '/';
        }
        if(pre.slice(-1)!="/")
            pre+="/";
        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||'') : '';
    },
    getNode:function(linbid){
        return linb.use(linbid).get(0);
    },
    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=linb.browser.ie ? node.all : 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, dm=d.documentMode, 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),

        isStrict:d.compatMode=="CSS1Compat",
        isWebKit:/webkit/.test(u),
        isChrome:/chrome/.test(u),
        isSafari:(!/chrome/.test(u)) && /safari/.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])};

    linb.$secureUrl=b.isSecure&&b.ie?'javascript:""':'about:blank';

    _.filter(b,function(o){return !!o});
    if(b.ie){
        if(_.isNumb(dm))
            b["ie"+(b.ver=dm)]=true;
        else
            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',/.+\//)]=true;
    else if(b.opr)
        b[v('opr','opera/')]=true;
    else if(b.kde){
        b[v('kde','webkit/')]=true;
        if(b.isSafari){
           if(/applewebkit\/4/.test(u))
                b["safari"+(b.ver=2)]=true;
           else
                b[v('safari','version/')]=true;
        }else if(b.isChrome)
            b[v('chrome','chrome/')]=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(/[^\\\/]+$/,''),
        img_bg: ini.path+'bg.gif',
        img_busy: ini.path+'busy.gif',
        img_blank:b.ie&&b.ver<=7?(ini.path+'bg.gif'):"data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==",
        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)})()
};
// for loction url info
new function(){
    linb._uriReg=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/;
    linb._localReg=/^(?:about|app|app\-storage|.+\-extension|file|widget):$/;
    linb._curHref=(function(a){
        try{return location.href;}catch(e){
            a=document.createElement("a");
            a.href="";
            return a.href;
        }})(),
    linb._localParts=linb._uriReg.exec(linb._curHref.toLowerCase())||[];
};

/*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){
        if(arguments.callee.upper)arguments.callee.upper.call(this);
        //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:"ini",
            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;

            // maybe abort or no task
            if(!p||!p.status||!p.tasks)
                return;
            // reset the asy flag
            p._asy=-1;

            var t={}, value=p.tasks[p.index],r,i,type=typeof value;

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

            //default callback
            if(typeof t.callback!='function')
                t.callback=p.callback

            if(typeof t.task=='function'){
                t.args=t.args||[];
                //last arg is threadid
                t.args.push(p.id);                
            }

            // to next pointer
            p.index++;
            p.time=_();

            // the real task
            if(typeof t.task=='function')
                r = _.tryF(t.task, t.args || [p.id], t.scope||self, null);

            // maybe abort called in abover task
            if(!p.status)
                return;

            // cache return value
            if(t.id)
                p.cache[t.id] = r;

            // if callback return false, stop.
            if(t.callback && false===_.tryF(t.callback, [p.id], self, true))
                return self.abort();

            // if set suspend at t.task or t.callback , stop continue running
            if(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.status!="run")
                p.status="run";

            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 : (task && typeof task.delay=='number') ? task.delay : p.delay;
            p._left= (time || time===0)?time:delay;

            // clear the mistake trigger task
            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=-1;
            if(index==-1){
                Array.prototype.push.apply(o, arr);
            }else{
                if(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];
        },
        getStatus:function(){
            return this.profile.status;
        }
    },
    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:{
        $asFunction:1,
        $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,[null],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){
        if(arguments.callee.upper)arguments.callee.upper.call(this);
        //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||'',
            username:options.username||undefined,
            password:options.password||undefined,
            query : options.query||'',
            contentType : options.contentType||'',
            Accept : options.Accept||'',
            header : options.header||null,
            asy : options.asy!==false,
            method : 'POST'==(options.method||con.method).toUpperCase()?'POST':'GET'
        },'all');
        var a='retry,timeout,reqType,rspType,optimized,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]];
            if(typeof options[a[i]]=="string")
                options[a[i]]=options[a[i]].toLowerCase();
        }

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

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

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

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

        // remove all undifiend item
        if(typeof self.query=='object' && self.reqType!="xml")
            self.query=_.clone(self.query, function(o){return o!==undefined});

        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:false,
        _txtresponse:'',
        _retryNo:0,

        _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{
                if(false!==_.tryF(self.onTimeout,[],self))
                    self._onError(new Error("Request timeout"));
            }
        },
        _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,[e.name + ": " + e.message, self.rspType, self.threadid], self);
            self._onEnd();
        },
        isAlive:function(){
            return !this._end;
        },
        abort:function(){
            this._onEnd();
        }
    },
    Static:{
        $abstract:true,
        _id:1,
        method:'GET',
        retry:0,
        timeout:60000,
        //form, xml, or json
        reqType:'form',
        //json, text or xml
        rspType:'json',

        optimized:false,

        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 ie8=linb.browser.ie && parseInt(linb.browser.ver)<9,
                scr=ie8
                    ? ("<iframe "+(id?("name='"+"linb_IAajax_"+id+"'"):"")+(onLoad?(" onload='linb.IAjax._o(\""+id+"\")'"):"")+">")
                    : "iframe";
            var n=doc.createElement(scr),w;
            if(id)n.id=n.name="linb_IAajax_"+id;
            if(!ie8 && 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){
            var a=linb._uriReg.exec((uri||'').toLowerCase()),
                b=linb._localParts;
            return !!( a&&(
                    a[1]!==b[1]||
                    a[2]!==b[2]||
                    (a[3]||(a[1]==="http:"?80:443))!==(b[3]||(b[1]==="http:"?80:443)) 
                )
            );
        },
        //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,
        _header:function(n,v){
            if(this._XML)this._XML.setRequestHeader(n,v);
        },
        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;
                    }
                    if(username&&password)
                        self._XML.open(method, uri, asy, username, password);
                    else
                        self._XML.open(method, uri, asy);

                    self._header("Accept", Accept ? Accept :
                        (rspType=='xml' ? "text/xml; " : rspType=='json' ? "application/json; " : "default; ")
                    );
                    self._header("Content-type", contentType ? contentType : (
                        (reqType=='xml' ? "text/xml; " : reqType=='json' ? "application/json; " : method=="POST" ? "application/x-www-form-urlencoded; ":"")
                         + "charset=" + (self.charset||"UTF-8")
                    ));
                    self._header("X-Requested-With", "XMLHttpRequest");
                    if(optimized){
                        try {
                            self._header("User-Agent", null);
                            self._header("Accept-Language", null);
                            self._header("Connection", "keep-alive");
                            self._header("Keep-Alive", null);
                            self._header("Cookie", null);
                            self._header("Cookie", "");
                        } catch(e) {}
                    }
                    try {
                        if(_.isHash(header))
                            _.each(header,function(o,i){
                                self._header(i, o);
                            });
                    } catch(e) {}

                    if(false===_.tryF(self.beforeSend,[self._XML],self)){
                        self._onEnd();
                        return;
                    }

                    //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,obj,status = ns._XML.status;
                _txtresponse = rspType=='xml'?ns._XML.responseXML:ns._XML.responseText;
                // try to get js object, or the original
                _response=rspType=="json"?((obj=_.unserialize(_txtresponse))===false?_txtresponse:obj):_txtresponse;
                // crack for some local case
                if(!status && linb._localReg.test(linb._localParts[1]) && !linb.absIO.isCrossDomain(uri))
                    status=ns._XML.responseText?200:404;
                // for IE7
                if(status==1223)status=204;
                // offline or other Network problems
                if(status===undefined || status<10 )
                    _onError(new Error('Network problems--' +status));
                else if(status===undefined || status===0 || status==304 || (status >= 200 && status < 300 ))
                    _onResponse();
                else
                    _onError(new Error('XMLHTTP returns--' +status));
            }
        }
    },
    Static:{
        $asFunction:1
    }
});
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];

            c.No["_"+id]=function(rsp){
                c.$response(rsp,id);
            };

            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");

            var uri = self.uri;
            if(self.query)
                uri = uri.split("?")[0]  + "?" + self.query;

            n.src = uri;
            n.type= 'text/javascript';
            n.charset=self.charset||'UTF-8';
            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,id=self.id,_pool=c._pool;
            if(_pool[id]){
                _pool[id].length=0;
                delete _pool[id];
            }
            delete c.No["_"+id];

            if(n){
                self.node=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='';if(_.isEmpty(_pool))c._id=1;_pool=c=n=div=null;});
                else{
                    _.asyRun(function(){
                        div.innerHTML='';
                        n=div=null;
                        if(_.isEmpty(_pool))c._id=1;
                    });
                }
            }else{
                if(_.isEmpty(_pool))c._id=1;
            }
        },
        _loaded:function(){
            var self=this;
            _.asyRun(function(){
                if(self.id && self.constructor._pool[self.id])
                    self._onError(new Error("SAjax return script doesn't match"));
            },500);
        }
    },
    Static : {
        $asFunction:1,
        _pool:{},
        "No":{},
        $response:function(obj,id) {
            var self=this;
            try{
                if(obj && (o = self._pool[id])){
                    for(var i=0,l=o.length;i<l;i++){
                        o[i]._response=obj;
                        o[i]._onResponse();
                    }
                }else
                    self._onError(new Error("SAjax return value formatting error--"+obj));
            }catch(e){
                linb.Debugger && linb.Debugger.trace(e);
            }
        },
        customQS:function(obj){
            var c=this.constructor,  b=c.callback,nr=(this.rspType!='script');
            if(typeof obj=='string')
                return (obj||"") + (nr?("&" + b + '=linb.SAjax.No._'+this.id):'');
            else{
                if(nr){
                    obj[b]="linb.SAjax.No._"+this.id;
                }
                return obj;
            }
        }
    }
});
Class('linb.IAjax','linb.absIO',{
    Instance:{
        _useForm:true,
        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.
                if(self.OK)return;
                //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){}
                self.OK=1;

                w.location.replace(c._getDummy()+'#'+linb.ini.dummy_tag);
                // for in firefox3, we have to asyRun to get the window.name
                _.asyRun(function(){
                    // "w.name" cant throw exception in chrome
                    if(linb.browser.kde && w.name===undefined){
                        _.asyRun(arguments.callee);
                        return;
                    }else{
                        // for in firefox3, we have to asyRun to get the window.name
                        try{w.name}catch(e){
                            _.asyRun(arguments.callee);
                            return;
                        }
                    }
                    var data;
                    if(("linb_IAajax_"+self.id)==w.name){
                        //clear first
                        self._clear();
                        self._onError(new Error('IAjax no return value'));
                        return;
                    }else
                        data=w.name;

                    if(data && (o=_.unserialize(data)) && (t=c._pool[self.id]) ){
                        for(var i=0,l=t.length;i<l;i++){
                            t[i]._response=o;
                            t[i]._onResponse();
                        }
                    }else{
                        //clear first
                        self._clear();
                        self._onError(new Error("IAjax return value formatting error, or no matched 'id'-- "+data));
                    }
                });
            };

            //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';

            var uri=self.uri;
            if(self.method!='POST')
                uri = uri.split("?")[0];

            form.action=self.uri;
            form.method=self.method;
            form.target="linb_IAajax_"+id;

            k=self.query||{};
            for(i in k){
                if(k[i] && k[i].nodeType==1){
                    k[i].id=k[i].name=i;
                    form.appendChild(k[i]);
                    b=true;
                }else{
                    if(_.isDefined(k[i])){
                        t=document.createElement('textarea');
                        t.id=t.name=i;
                        t.value= typeof k[i]=='string'?k[i]:_.serialize(k[i],function(o){return o!==undefined});
                        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'),id=self.id,_pool=c._pool;
            if(_pool[id]){
                _pool[id].length=0;
                delete _pool[id];
            }
            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;
            if(n)div.appendChild(n.parentNode.removeChild(n));
            if(f)div.appendChild(f.parentNode.removeChild(f));
            div.innerHTML='';
            if(_.isEmpty(_pool))c._id=1;
            f=div=null;
        }
    },
    Static : {
        $asFunction:1,
        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(!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.img_bg;
                    o.style.display='none';
                    d.body.appendChild(o);
                    o=null;
                }
            }
            if(o=d.getElementById('linb:img:bg')){
                return ns.dummy=o.src.split('#')[0];
            }else{
                arr=d.getElementsByTagName("img");
                for(var i=0,j=arr.length; i<j; i++){
                    o = arr[i];
                    if(o.src && !f(o.src))
                        return ns.dummy=o.src.split('#')[0];
                }
                
                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];
                    }
                }
            }
            //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.callback;
            obj[t]='window.name';
            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){
        if(arguments.callee.upper)arguments.callee.upper.call(this);
        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:{
        $asFunction:1,
        __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(e.name + ": " + e.message+ " " + 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, {rand:_()}, 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 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
    M ={
        '\b': '\\b',
        '\t': '\\t',
        '\n': '\\n',
        '\f': '\\f',
        '\r': '\\r',
        '\"' : '\\"',
        '\\': '\\\\',
        '/': '\\/',
        '\x0B': '\\u000b'
    },
    H={'@window':'window','@this':'this'},
    A=/\uffff/.test('\uffff') ? /[\\\"\x00-\x1f\x7f-\uffff]/g : /[\\\"\x00-\x1f\x7f-\xff]/g,
    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,p){
        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' && t[i] && (t[i].constructor===Object || t[i].constructor===Array)) 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={},
    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.length==1?'0':'')+a+'00'})();
    T['undefined']=function(){return 'null'};
    T[L]=function(x){return String(x)};
    T[N]=function(x){return ((x||x===0)&&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;
                return '\\u' + ((b=a.charCodeAt())<16?'000':b<256?'00':b<4096?'0':'')+b.toString(16)
            })
            :
            x
            )
            + '"'
    };
    T[O]=function(x,filter,dateformat,deep,max){
        var me=arguments.callee, map = me.map || (me.map={prototype:1,constructor:1,toString:1,valueOf:1});
        deep=deep||1;
        max=max||0;
        if(deep>linb.SERIALIZEMAXLAYER||max>linb.SERIALIZEMAXSIZE)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,max))==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,max))==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){
        return T[typeof obj](obj,filter,dateformat||(linb&&linb.$dateFormat))||'';
    };
    _.stringify = function(obj,filter,dateformat){
        return _.fromUTF8(_.serialize(obj,filter,dateformat));
    };
    //unserialize string to object
    _.unserialize = function(str, dateformat){
        try{
            str=eval('({_:'+str+'})');
            if(dateformat||(linb&&linb.$dateFormat))E(str);
            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){
            i = (i||i===0)?i:b.length-1;
            var m,k,l;
            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('');
        }
    }
};

//linb.absBox
Class('linb.absBox',null, {
    Constructor:function(){
        if(arguments.callee.upper)arguments.callee.upper.call(this);
        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)return linb.UI.pack([]);
            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;
        }
    }
});

Class('linb.absProfile',null,{
    Constructor:function(){
        if(arguments.callee.upper)arguments.callee.upper.call(this);
        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
    }
});

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?_.copy(properties):(self.properties||{});
        self.events=events?_.copy(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(key, value){
            var evs=this.box.$EventHandlers;
            if(_.isHash(key)){
                return _.merge(this,key,'all',function(o,i){return evs[i]});
            }else{
                if(evs[key])
                    this[key]=value;
            }
        },
        getEvents:function(key){
            if(key){
                return this[key];
            }else{
                var self=this, t,hash={};
                _.each(self.box.$EventHandlers,function(o,i){
                    if(self[i])hash[i]=self[i];
                });
                return hash;
            }
        },
        getProperties:function(key){
            var prop=this.properties;
            return key?prop[key]:_.copy(prop);
        },
        setProperties:function(key, value){
            if(_.isHash(key))
                this.properties=key;
            else
                this.properties[key]=value;
        },
        _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;
            //for destroyed UIProfile
            if(!self.box)return null;
            if(!((t=self._cacheInstance) && t.get(0)==self && t._nodes.length==1))
                t = self._cacheInstance = 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);
        }
    }
});

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=self.$nameTag||('ctl_'+(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 $set!='function' && 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,null,'instance');
                    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 $get!='function' && typeof m=='function') ? m : Class._fun(function(){
                        if(typeof $get=='function')
                            return $get.call(this.get(0));
                        else
                            return this.get(0).properties[i];
                    },n,self.KEY,null,'instance');
                    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;
                    f.$name$=i;
                    f.$type$='event';
                    self.plugIn(i,f);
                }
            });
            return self;
        },
        unserialize:function(target,keepSerialId){
            if(typeof target=='string')target=_.unserialize(target);
            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);
        }
    },
    Instance:{
        clone:function(){
            var arr=[],clrItems=arguments,f=function(p){
                //remove those
                delete p.alias;
                for(var i=0;i<clrItems.length;i++)
                    delete p[clrItems[i]];
                if(p.children)
                    for(var i=0,c;c=p.children[i];i++)
                        f(c[0]);
            };
            this.each(function(o){
                o=o.serialize(false,true);
                f(o);
                arr.push(o);
            });
            return this.constructor.unserialize(arr);
        },
        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)+")";
        },
        setAlias:function(str){
            var self=this,prf=this.get(0),old;
            if(old=prf.alias){
                if(prf.host && prf.host!==prf){
                    try{delete prf.host[old]}catch(e){prf.host[old]=undefined}
                    if(prf.host._ctrlpool)
                        delete prf.host._ctrlpool[old];
                }
                delete self.constructor._namePool[old];
            }
            self.constructor._namePool[prf.alias=str]=1;
            if(prf.host && prf.host!==prf){
                prf.host[str]=self;
                if(prf.host._ctrlpool)
                    prf.host._ctrlpool[str]=self.get(0);
            }
            return self;
        },
        getAlias:function(){
            return this.get(0).alias;
        },
        getProperties:function(key){
            var h={},prf=this.get(0),prop=prf.properties,funName;
            if(key===true)
                return _.copy(prop);
            else if(typeof key=='string')
                return prop[key];
            else{
                for(var k in prop){
                    funName="get"+_.str.initial(k);
                    if(typeof this[funName]=='function')
                        h[k]=this[funName].call(this);
                }
                return h;
            }
        },
        setProperties:function(key, value){
            if(typeof key=="string"){
                var h={};
                h[key]=value;
                key=h;
            }
            return this.each(function(o){
                _.each(key, function(v,k){
                    var funName="set"+_.str.initial(k),ins=o.boxing();
                    if(typeof ins[funName]=='function')
                        ins[funName].call(ins, v);
                });
            });
        },
        getEvents:function(key){
            return this.get(0).getEvents(key);
        },
        setEvents:function(key, value){
            if(typeof key=="string"){
                var h={};
                h[key]=value;
                key=h;
            }
            return this.each(function(o){
                var ins=o.boxing();
                _.each(key, function(v,k){
                    if(typeof ins[k]=='function')
                        ins[k].call(ins, v);
                });
            });
        },
        alias:function(value){
            return value?this.setAlias(value):this.getAlias();
        },
        host:function(value, alias){
            return value?this.setHost(value, alias):this.getHost();
        },
        setHost:function(host, alias){
            var self=this;
            self.get(0).host=host;
            if(alias)
                self.setAlias(alias);
            return self;
        },
        getHost:function(){
            return this.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}
    }
});Class("linb.DataBinder","linb.absObj",{
    Instance:{
        _ini:function(properties, events, host){
            var self=this,
                c=self.constructor,
                profile,
                options,
                np=c._namePool,
                alias,temp;
            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||[];

            for(var i in (temp=c.$DataStruct))
                if(!(i in profile.properties))
                    profile.properties[i]=typeof temp[i]=='object'?_.copy(temp[i]):temp[i];

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

            if(!profile.name)profile.boxing().setName(alias);

            self._nodes.push(profile);
            profile._cacheInstance=self;

            return self;
        },
        destroy:function(){
            this.each(function(profile){
                var box=profile.box,name=profile.properties.name;
                //unlink
                _.arr.each(profile._n, function(v){if(v)box._unBind(name,v)});
                //delete from pool
                delete box._pool[name];
                //free profile
                profile.__gc();
            });
        },

        // for UI Controls
        getUI:function(key){
            var r;
            if(!key)
                r=linb.UI.pack(this.get(0)._n,false);
            else
                _.arr.each(this.get(0)._n,function(profile){
                    if(profile.properties.dataField==key){
                        r=profile.boxing();
                        return false;
                    }
                });
            return r;
        },
        checkValid:function(){
            return linb.absValue.pack(this.get(0)._n,false).checkValid();
        },
        getDirtied:function(withCaption){
            var ns=this,
                prf=ns.get(0),
                hash={};
            _.arr.each(prf._n,function(profile){
                var p=profile.properties,
                    b = profile.boxing(),
                    // maybe return array
                    v = b.getValue(),
                    uv = b.getUIValue();
                // v and uv can be object(Date,Number)
                if((uv+" ")!==(v+" ")){
                    if(withCaption && b.getCaption){
                        hash[p.dataField]={value:uv,caption:b.getCaption()};
                    }else{
                        hash[p.dataField]=uv;
                    }
                }
            });
            return hash;
        },
        updateValue:function(){
            linb.absValue.pack(this.get(0)._n,false).updateValue();
            return this;
        },
        updateDataFromUI:function(updateUIValue,withCaption,returnArr,adjustData){
            var ns=this,
                prf=ns.get(0),
                hash={},mapb;
            _.arr.each(prf._n,function(profile){
                var p=profile.properties,
                    b = profile.boxing(),
                    // maybe return array
                    v = b.getValue(_.isBool(returnArr)?returnArr:profile.__returnArray),
                    uv = b.getUIValue(_.isBool(returnArr)?returnArr:profile.__returnArray);
                // v and uv can be object(Date,Number)
                if(withCaption && b.getCaption){
                    hash[p.dataField]={value:uv,caption:b.getCaption()};
                }else{
                    hash[p.dataField]=uv;
                }
                if(updateUIValue!==false && profile.renderId){
                    b.updateValue();
                }
            });

            // adjust UI data
            if(adjustData)
                hash = _.tryF(adjustData,[hash, prf],this);

            if(prf.afterUpdateDataFromUI){
                mapb = this.afterUpdateDataFromUI(prf, hash);
                if(_.isHash(mapb))hash=mapb;
                mapb=null;
            }


            _.merge(prf.properties.data,hash,'all');

            return ns;
        },
        updateDataToUI:function(adjustData){
            var t,p,v,c,b,
                ns=this,
                prf=ns.get(0),
                prop=prf.properties,
                map={},mapb,
                vs={};

            _.merge(map,prop.data);

            if(adjustData)
                map = _.tryF(adjustData,[map, prf],ns);

            if(prf.beforeUpdateDataToUI){
                mapb = ns.beforeUpdateDataToUI(prf, map);
                if(_.isHash(mapb))map=mapb;
                mapb=null;
            }

            _.arr.each(prf._n,function(profile){
                p=profile.properties;
                t=p.dataField;
                // need reset?
                // #45
                v=(map && t in map)?map[t]:'';
                // collect real values for UI controls
                vs[t]=v;
                c=null;
                b=profile.boxing();
                if(_.isHash(v)){
                    // catch caption at first
                    c=_.isSet(v.caption)?v.caption:null;
                    // reset v at last
                    v=v.value;
                }
                // set value
                b.resetValue(v);
                profile.__returnArray=_.isArr(v);
                // set caption
                if(!_.isSet(p.caption) && b.setCaption)
                    _.tryF(b.setCaption,[c,true],b);
            });
            _.merge(prop.data,vs,'all');

            return ns;
        },

        setHost:function(value, alias){
            var self=this;
            if(value && alias)
                self.setName(alias);
            return arguments.callee.upper.apply(self,arguments);
        },

        invoke:function(onSuccess, onFail, onStart, onEnd, mode, threadid, options){
            var ns=this,
                con=ns.constructor,
                prf=ns.get(0),
                prop=prf.properties,
                dsType=prop.dataSourceType,
                responseType=prop.responseType,
                requestType=prop.requestType,
                hashModel=_.isSet(prop.queryModel) && prop.queryModel!=="",
                queryURL=(hashModel?(((prop.queryURL.lastIndexOf("/")!=prop.queryURL.length-1)?(prop.queryURL+"/"):prop.queryURL)+prop.queryModel):prop.queryURL),
                queryUserName=prop.queryUserName;
                queryPasswrod=prop.queryPasswrod;
                queryArgs=_.copy(prop.queryArgs),
                queryOptions=_.copy(prop.queryOptions);
            if(dsType!="remoting")return;

            // Normally, Gives a change to modify "queryArgs" for XML
            if(prf.beforeInvoke && false===prf.boxing().beforeInvoke(prf))
                return;

            // for auto adjusting options
            var proxyType,rMap={};
            if(responseType=='SOAP'||requestType=='SOAP'){
                // for wsdl
                if(!con.WDSLCache)con.WDSLCache={};
                if(!con.WDSLCache[queryURL]){
                    var wsdl=linb.SOAP.getWsdl(queryURL,function(rspData){
                       if(prf.afterInvoke)
                            prf.boxing().afterInvoke(prf, rspData);
                        _.tryF(onFail,arguments,this);
                        _.tryF(onEnd,arguments,this);
                    });
                    if(wsdl)
                        con.WDSLCache[queryURL] = wsdl;
                    else
                        // stop the further call
                        return;
                }
            }
            switch(responseType){
                case "JSON":
                    rMap.rspType="json";
                break;
                case "XML":
                    proxyType="ajax";
                    rMap.rspType="xml";
                break;
                case "SOAP":
                    proxyType="ajax";
                    rMap.rspType="xml";
                    var namespace=linb.SOAP.getNameSpace(con.WDSLCache[queryURL]),
                        action = ((namespace.lastIndexOf("/")!=namespace.length-1)?namespace+"/":namespace)+(queryArgs.methodName||"");
                    rMap.header=rMap.header||{};
                    rMap.header["SOAPAction"]=action;
                break;
            }
            switch(requestType){
                case "HTTP":
                    // ensure object
                    queryArgs = typeof queryArgs=='string'?_.unserialize(queryArgs):queryArgs;
                break;
                case "JSON":
                    rMap.reqType="json";

                    if(prop.queryMethod=="auto")
                        rMap.method="POST";
                    // ensure string
                    queryArgs = typeof queryArgs=='string'?queryArgs:_.serialize(queryArgs);
                break;
                case "XML":
                    rMap.reqType="xml";
                    proxyType="ajax";
                    rMap.method="POST";
                    if(queryUserName && queryPassword){
                        rMap.username=queryUserName;
                        rMap.password=queryPassword;
                        rMap.header=rMap.header||{};
                        rMap.header["Authorization"]="Basic "+con._toBase64(queryUserName+":"+queryPassword);
                    }
                    // ensure string
                    queryArgs = typeof queryArgs=='string'?queryArgs:linb.XMLRPC.wrapRequest(queryArgs);
                break;
                case "SOAP":
                    rMap.reqType="xml";
                    proxyType="ajax";
                    rMap.method="POST";
                    if(queryUserName && queryPassword){
                        rMap.username=queryUserName;
                        rMap.password=queryPassword;
                        rMap.header=rMap.header||{};
                        rMap.header["Authorization"]="Basic "+con._toBase64(queryUserName+":"+queryPassword);
                    }
                    // ensure string
                    queryArgs = typeof queryArgs=='string'?queryArgs:linb.SOAP.wrapRequest(queryArgs, con.WDSLCache[queryURL]);
                break;
            }

            // Ajax/SAjax/IAjax
            if(!proxyType && prop.proxyType!="auto")
                proxyType = prop.proxyType;
            if(proxyType!="ajax")
                rMap.asy=true;
            if(proxyType=="sajax")
                rMap.method="GET";
            if(proxyType)
                proxyType=proxyType.toLowerCase();

            options=options||{};
            if(!("asy" in options))
                options.asy=!!prop.queryAsync;
            if(!("method" in options)&&prop.queryMethod!="auto")
                options.method=prop.queryMethod;
            if(!("onEnd" in options))
                options.onEnd=onEnd;
            if(!("onStart" in options))
                options.onStart=onStart;
            _.merge(options, queryOptions);

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

            var ajax=(
                // specify
                proxyType ? (proxyType=="sajax"?linb.SAjax:proxyType=="iajax"?linb.IAjax:linb.Ajax)
                // include a file => IAjax
                :((function(d){if(!_.isHash(d))return 0; for(var i in d)if(d[i]&&d[i].nodeType==1)return 1})(queryArgs)) ? linb.IAjax
                // post: crossdomain => IAjax, else Ajax
                : (options&&options.method&&options.method.toLowerCase()=='post') ?  linb.absIO.isCrossDomain(queryURL) ? linb.IAjax  : linb.Ajax
                // get : crossdomain => SAjax, else Ajax
                : linb.absIO.isCrossDomain(queryURL) ? linb.SAjax : linb.Ajax
             ).apply(null, [
                queryURL,
                queryArgs,
                function(rspData){
                    var mapb;

                    // Normally, Gives a change to modify the "rspData" format for XML
                    if(prf.afterInvoke){
                        mapb = prf.boxing().afterInvoke(prf, rspData);
                        if(_.isSet(mapb))rspData=mapb;
                        mapb=null;
                    }
                    // ensure to json
                    if(dsType=='remoting' && !_.isHash(rspData) && !_.isStr(rspData)){
                        if(responseType=="XML")
                            rspData=linb.XMLRPC.parseResponse(rspData);
                        else if(responseType=="SOAP")
                            rspData=linb.SOAP.parseResponse(rspData, queryArgs.methodName, con.WDSLCache[queryURL]);
                    }

                    _.tryF(onSuccess,arguments,this);
                },
                function(rspData){
                   if(prf.afterInvoke)
                        prf.boxing().afterInvoke(prf, rspData);
                    _.tryF(onFail,arguments,this);
                },
                threadid,
                options]
            );
            if(mode=="busy")
                _.observableRun(function(threadid){
                    ajax.start();
                });
            else if(mode=="return")
                return ajax;
            else
                ajax.start();
        },
        "read":function(onSuccess, onFail, onStart, onEnd, mode, threadid, options, adjustData){
            var ns=this,prf=ns.get(0),
                prop=prf.properties,
                dsType=prop.dataSourceType;
            if(dsType=='none'||dsType=='memory')return;

            if(prf.beforeRead && false===prf.boxing().beforeRead(prf))
                return;

            return ns.invoke(function(rspData){
                var mapb;
                // Normally, Gives a change to modify the "rspData" format to suitable key/value maps
                if(prf.afterRead){
                    mapb = prf.boxing().afterRead(prf, rspData);
                    if(_.isSet(mapb))rspData=mapb;
                    mapb=null;
                }

                if(_.isHash(rspData))
                    // auto setData ,and reset values to UI
                    prf.boxing().setData(rspData).updateDataToUI(adjustData);

                _.tryF(onSuccess,arguments,this);

            }, onFail, onStart, onEnd, mode, threadid, options);
        },
        "write":function(onSuccess, onFail, onStart, onEnd, mode, threadid, options){
            var ns=this,prf=ns.get(0),dsType=prf.properties.dataSourceType;
            if(dsType=='none'||dsType=='memory')return;

            if(prf.beforeWrite && false===prf.boxing().beforeWrite(prf))
                return;

            return ns.invoke(function(rspData){
               var mapb;
               if(prf.afterWrite){
                    mapb = prf.boxing().afterWrite(prf, rspData);
                    if(_.isSet(mapb))rspData=mapb;
                    mapb=null;
                }
                _.tryF(onSuccess,arguments,this);
            }, onFail, onStart, onEnd, mode, threadid, options);
        },
        getData:function(key){
            var prf=this.get(0),
                data=prf.properties.data;
            return _.isSet(key)?data[key]:data;
        },
        setData:function(key,value){
            var prop=this.get(0).properties;

            if(!_.isSet(key))
                prop.data={};
            else if(_.isHash(key))
                prop.data=key;
            else
                prop.data[key]=value;

            return this;
        }
    },
    Static:{
        WDSLCache:{},
        $nameTag:"databinder_",
        _pool:{},
        destroyAll:function(){
            this.pack(this._pool,false).destroy();
            this._pool={};
        },
        getFromName:function(name){
            var o=this._pool[name];
            return o && o.boxing();
        },
        _toBase64:function(str){
            var keyStr="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
                arr=[],
                i=0,
                c1,c2,c3,e1,e2,e3,e4;
            do {
                c1=str.charCodeAt(i++);
                c2=str.charCodeAt(i++);
                c3=str.charCodeAt(i++);
                e1=c1>>2;
                e2=((c1&3)<<4)|(c2>>4);
                e3=((c2&15)<<2)|(c3>>6);
                e4=c3&63;
                if (isNaN(c2))e3=e4=64;
                else if(isNaN(c3))e4=64;
                arr.push(keyStr.charAt(e1)+keyStr.charAt(e2)+keyStr.charAt(e3)+keyStr.charAt(e4));
            }while(i<str.length);
            return arr.join('');
        },
        _bind:function(name, profile){
            var t,v,o=this._pool[name];
            if(!o){
                o=new linb.DataBinder();
                o.setName(name);
                o=o.get(0);
            }
            var map=o.properties.data;
            if(profile){
                if(_.arr.indexOf(o._n,profile)==-1)
                    //use link for 'destroy UIProfile' trigger 'auto unbind function '
                    profile.link(o._n, 'databinder.'+name);
                var p=profile.properties,c,b;
                // set control value 1
                if(t=p.dataField){
                    // #45
                    v=(map && t in map)?map[t]:(p.value||'');
                    // reset real value
                    map[t]=v;
                    c=null;
                    b=profile.boxing();
                    if(_.isHash(v)){
                        // catch caption at first
                        c=_.isSet(v.caption)?v.caption:null;
                        // reset v at last
                        v=v.value;
                    }
                    // set value
                    b.resetValue(v);
                    // set caption
                    if(!_.isSet(p.caption) && b.setCaption)
                        _.tryF(b.setCaption,[c,true],b);
                }
            }
        },
        _unBind:function(name, profile){
            if(profile && profile.box && this._pool[name])
                profile.unLink('databinder.'+name);
        },
        _beforeSerialized:function(profile){
            var o={};
            _.merge(o, profile, 'all');
            var p = o.properties = _.copy(profile.properties);
            if(p.dataSourceType!='memory'){
                delete p.data;
            }
            if(p.dataSourceType=='none' && p.dataSourceType=='memory'){
                delete p.queryURL;
                delete p.queryUserName;
                delete p.queryPassword;
                delete p.queryModel;
                delete p.queryArgs;
                delete p.queryOptions;
                delete p.proxyType;
                delete p.queryAsync;
                delete p.queryMethod;
                delete p.requestType;
                delete p.responseType;
            }
            if(p.data && _.isEmpty(p.data))
                delete p.data;
            if(p.queryArgs && _.isEmpty(p.queryArgs))
                delete p.queryArgs;
            if(p.queryOptions && _.isEmpty(p.queryOptions))
                delete p.queryOptions;
            return o;
        },
        DataModel:{
            "data":{
                ini:{}
            },
            dataSourceType:{
                ini:"none",
                listbox:["none","memory","remoting"]
            },
            queryURL:{
                ini:""
            },
            queryUserName:{
                ini:""
            },
            queryPassword:{
                ini:""
            },
            queryModel:"",
            queryMethod:{
                ini:"auto",
                listbox:["auto","GET","POST"]
            },
            queryAsync:true,
            requestType:{
                ini:"HTTP",
                listbox:["HTTP","JSON","XML","SOAP"]
            },
            responseType:{
                ini:"JSON",
                listbox:["JSON","XML","SOAP"]
            },
            queryArgs:{
                ini:{}
            },
            queryOptions:{
                ini:{}
            },
            proxyType:{
                ini:"auto",
                listbox:["auto","Ajax","SAjax","IAjax"]
            },
            "name":{
                set:function(value,ovalue){
                    var o=this,
                        c=linb.DataBinder,
                        _p=c._pool,
                        to=_p[ovalue],
                        t=_p[value],
                        ui;

                    //if it exists, overwrite it dir
                    //if(to && t)
                    //    throw new Error(value+' exists!');

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

                }
            },
            proxyInvoker:{
                inner:true,
                trigger:function(){
                    this.read(null,null,null,null,true);
                }
            }
        },
        EventHandlers:{
            beforeUpdateDataToUI:function(profile, dataToUI){},
            afterUpdateDataFromUI:function(profile, dataFromUI){},
            beforeInvoke:function(profile){},
            afterInvoke:function(profile,rspData){},
            beforeRead:function(profile){},
            afterRead:function(profile,rspData){},
            beforeWrite:function(profile){},
            afterWrite:function(profile,rspData){}
        }
    }
});(linb.Locale.en||(linb.Locale.en={})).inline={
    ok:'O K',
    cancel:'Cancel',
    set:'SET',
    today:'Today',
    now:'Now',
    yes:'Yes',
    no:'No',
    noFlash:'No Flash PlugIn!'
};
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.length==1?'0':'')+a+":"+(b.length==1?'0':'')+b},
    DHN:function(n,a,b,c){return a +'th '+ (b.length==1?'0':'')+b + ":" +(c.length==1?'0':'')+c },
    MDHN:function(n,a,b,c,d){return b+ 'th ' + linb.getRes('date.MONTHS.'+a) + " " + (c.length==1?'0':'')+c + ":" + (d.length==1?'0':'')+d},
    HNS:function(n,a,b,c){return (a.length==1?'0':'')+a+":"+(b.length==1?'0':'')+b+":"+(c.length==1?'0':'')+c},
    HNSMS:function(n,a,b,c,d){return (a.length==1?'0':'')+a+":"+(b.length==1?'0':'')+b+":"+(c.length==1?'0':'')+c+ ' ' +(d.length==1?'00':d.length==2?'0':'')+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 a+'-'+(b.length==1?'0':'')+b+'-'+(c.length==1?'0':'')+c},
    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 a+'-'+(b.length==1?'0':'')+b+'-'+(c.length==1?'0':'')+c + ' ' +(d.length==1?'0':'')+d+':00'},
    YMDHN:function(n,a,b,c,d,e){return a+'-'+(b.length==1?'0':'')+b+'-'+(c.length==1?'0':'')+c + ' ' +(d.length==1?'0':'')+d+":"+(e.length==1?'0':'')+e},
    YMDHNS:function(n,a,b,c,d,e,f){return a+'-'+(b.length==1?'0':'')+b+'-'+(c.length==1?'0':'')+c + ' ' +(d.length==1?'0':'')+d+":"+(e.length==1?'0':'')+e+":"+(f.length==1?'0':'')+f},
    ALL:function(n,a,b,c,d,e,f,g){return a+'-'+(b.length==1?'0':'')+b+'-'+(c.length==1?'0':'')+c + ' ' +(d.length==1?'0':'')+d+":"+(e.length==1?'0':'')+e+":"+(f.length==1?'0':'')+f +" " +(g.length==1?'00':g.length==2?'0':'')+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 droppable
            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)){
            if(type=="DOMMouseScroll")
                type="mousewheel";
            //for setBlurTrigger
            if(type=='mousedown' || type=="mousewheel")
                _.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 droppable node to child droppable 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 droppable node, 'dragdrop._dropElement' will be set to null in beforeMouseover
                //set _preDroppable flag, for parent node is droppable too
                if('mouseout'==type && !dragdrop._dropElement && pre && pre==src.$linbid){
                    self._preDroppable=id;
                    _.asyRun(function(){delete linb.Event._preDroppable});
                }

                //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)},
        $eventhandler3:function(){return linb.Event(arguments[0],linb.Event.getSrc(arguments[0]||window.event))},
        //collection
        _events : ("mouseover,mouseout,mousedown,mouseup,mousemove,mousewheel,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,tabindex=node.tabIndex;
            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],tabindex],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 droppable node, if the parent node is droppable return true;
            if(dd && event.type=='mouseover' &&this._preDroppable)
                try{
                    do{
                        if(node && node.id && node.id==this._preDroppable){
                            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('');

            // use keydown char
            res[0]=res[0];
            res.key=res[0];
            res.type=type;
            res.ctrlKey=!!res[1];
            res.shiftKey=!!res[2];
            res.altKey=!!res[3];

            if(type=='keypress'){
                if(this.$keydownchar && this.$keydownchar.length>1)
                    res.key=this.$keydownchar;
            
            }
            // keep the prev keydown char
            else if(type=='keydown'){
                if(res[0].length>1)
                    this.$keydownchar=res[0];
                else if(this.$keydownchar)
                    this.$keydownchar=null;
            }
            // clear it
            else if(type=='keyup'){
                if(this.$keydownchar)
                    this.$keydownchar=null;
            }

            return res;
        },
        getEventPara:function(event, mousePos){
            if(!mousePos)mousePos=linb.Event.getPos(event);
            var keys = this.getKey(event), h={
                pageX:mousePos&&mousePos.left,
                pageY:mousePos&&mousePos.top,
                keyCode:keys.key,
                ctrlKey:keys.ctrlKey,
                shiftKey:keys.shiftKey,
                altKey:keys[3].altKey
            };
            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;
        },
        keyboardHookUp:function(key, ctrl, shift, alt, fun,args,scope){
            if(key){
                var p = linb.$cache.hookKeyUp, k = (key||'').toLowerCase() + ":"  + (ctrl?'1':'') + ":"  +(shift?'1':'')+ ":" + (alt?'1':'');
                if(typeof fun!='function')delete p[k];
                else p[k]=[fun,args,scope];
             }
            return this;
        },
        getWheelDelta:function(e){
            return e.wheelDelta
            // ie/opr/kde
            ?e.wheelDelta/120
            // gek
            :-e.detail/3
        }
    },
    Initialize:function(){
        var ns=this;
        var m1={
                move:null,
                size:null,
    
                drag:null,
                dragstop:null,
                dragover:null,

                mousewheel: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;

        if (window.addEventListener)
            window.addEventListener('DOMMouseScroll', ns.$eventhandler3, false);

        document.onmousewheel=window.onmousewheel =ns.$eventhandler3;
    }
});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,w,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,w,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,w){return linb.Date._fix(d.getMilliseconds(),3)+ (w?"":linb.wrapRes('date.MS'))},
            s:function(d,w){return d.getSeconds()+ (w?"":linb.wrapRes('date.S'))},
            ss:function(d,w){return linb.Date._fix(d.getSeconds())+ (w?"":linb.wrapRes('date.S'))},
            n:function(d,w){return d.getMinutes()+ (w?"":linb.wrapRes('date.N'))},
            nn:function(d,w){return linb.Date._fix(d.getMinutes())+ (w?"":linb.wrapRes('date.N'))},
            h :function(d,w){return d.getHours()+ (w?"":linb.wrapRes('date.H'))},
            hh :function(d,w){return linb.Date._fix(d.getHours())+ (w?"":linb.wrapRes('date.H'))},
            d:function(d,w){return d.getDate()+ (w?"":linb.wrapRes('date.D'))},
            dd:function(d,w){return linb.Date._fix(d.getDate())+ (w?"":linb.wrapRes('date.D'))},
            w : function(d,w,firstDayOfWeek){var a=(d.getDay() - firstDayOfWeek +7)%7; return w?a:linb.wrapRes('date.WEEKS.'+a)},
            ww : function(d,w,firstDayOfWeek){return linb.Date.getWeek(d, firstDayOfWeek) + (w?"":linb.wrapRes('date.W'))},
            m:function(d,w){return (d.getMonth()+1) + (w?"":linb.wrapRes('date.M'))},
            mm:function(d,w){return linb.Date._fix(d.getMonth()+1) + (w?"":linb.wrapRes('date.M'))},
            q : function(d,w){return (parseInt((d.getMonth()+3)/3-1) + 1) + (w?"":linb.wrapRes('date.Q'))},
            y :function(d,w){return d.getYear() + (w?"":linb.wrapRes('date.Y'))},
            yyyy :function(d,w){return d.getFullYear() + (w?"":linb.wrapRes('date.Y'))},
            de:function(d,w){return parseInt(d.getFullYear()/10) + (w?"":linb.wrapRes('date.DE'))},
            c:function(d,w){return parseInt(d.getFullYear()/100) + (w?"":linb.wrapRes('date.C'))},

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

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

            ym :   function(d,w){return linb.wrapRes('date.YM-'+d.getFullYear()+"-"+(d.getMonth()+1))},
            md :  function(d,w){return linb.wrapRes('date.MD-'+(d.getMonth()+1)+"-"+d.getDate())},
            ymd :  function(d,w){return linb.wrapRes('date.YMD-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate())},
            ymd2 :  function(d,w){return linb.wrapRes('date.YMD2-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate())},
            ymdh:  function(d,w){return linb.wrapRes('date.YMDH-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate()+"-"+d.getHours())},
            ymdhn: function(d,w){return linb.wrapRes('date.YMDHN-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate()+"-"+d.getHours()+"-"+d.getMinutes())},
            ymdhns:function(d,w){return linb.wrapRes('date.YMDHNS-'+d.getFullYear()+"-"+(d.getMonth()+1)+"-"+d.getDate()+"-"+d.getHours()+"-"+d.getMinutes()+"-"+d.getSeconds())},
            'all' :  function(d,w){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 : ((value || value===0)&&isFinite(value)) ? new Date(parseInt(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, targetTimeZone, back){
            var self=this;
            date=self._date(date);
            return new Date(date.getTime() + (back?-1:1)*(targetTimeZone - 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, format){
            var rtn;
            if(_.isDate(str)){
                rtn=str;
            }else{
                // avoid null
                str+="";
                if(isFinite(str)){
                    rtn=new Date(parseInt(str));
                }else{
                    if(typeof format=='string'){
                        var a=format.split(/[^ymdhns]+/),
                            b=str.split(/[^0-9]+/),
                            n={y:0,m:0,d:0,h:0,n:0,s:0,ms:0};
                        if(a.length && a.length===b.length){
                            for(var i=0;i<a.length;i++)
                                if(a[i].length)
                                    n[a[i]=='ms'?'ms':a[i].charAt(0)]=parseInt(b[i].replace(/^0*/,''));
                            rtn=new Date(n.y,n.m-1,n.d,n.h,n.n,n.s,n.ms);
                        }else
                            rtn=null;
                    }else{

                        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]])
                                    rtn=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);
                            }
                            rtn=date;
                        }else{
                            if(/^((-\d+|\d{4,})(-(\d{1,2})(-(\d{1,2}))))/.test(str))
                                str = str.replace(/-/g,'/');
                            var r=Date.parse(str);
                            rtn=r?date.setTime(r) && date:null;
                        }
                    }
                }
            }
            return rtn===null?null:isFinite(+rtn)?rtn:null;
        },
        getText:function(date, datepart, firstDayOfWeek){
            var self=this, map=self.$TEXTFORMAT;
            date = self._date(date);
            firstDayOfWeek = self._numb(firstDayOfWeek);
            return map[datepart]?map[datepart](date, false, firstDayOfWeek):datepart;
        },
        format:function(date, format, firstDayOfWeek){
            var self=this, map=self.$TEXTFORMAT;
            date = self._date(date);
            firstDayOfWeek = self._numb(firstDayOfWeek);
            return format.replace(/(utciso|iso|yyyy|mm|ww|dd|hh|nn|ss|ms|de|c|y|q|m|w|d|h|n|s)/g, function(a,b){
                return map[b]?map[b](date,true,firstDayOfWeek):b;
            });
        }
    }
});/* 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;
        },
        resetCSS:function(){
            var b=linb.browser,
            css="html{color:#000;background:#FFF;}"+
                "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;}"+
                "fieldset,img{border:0;}"+
                "address,caption,cite,code,dfn,em,strong,th,ar{font-style:normal;font-weight:normal;}"+
                "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;}"+
                "input,textarea,select{*font-size:100%;}"+
                "legend{color:#000;}"+
                "span{outline-offset:-1px;"+
                 (b.gek
                    ? parseFloat(b.ver)<3 
                        ? ((parseInt(b.ver)<3?"-moz-outline-offset:-1px !important;":"") + "display:-moz-inline-block;display:-moz-inline-box;display:inline-block;")
                        :"display:inline-block;"
                    : b.ie6
                        ?"display:inline-box;display:inline;"
                    :"display:inline-block;")+
                (b.ie?"zoom:1;":"")+
                "}";
            this.addStyleSheet(css,"linb.CSSreset");
        }
    },
    Initialize:function(){
        var b=linb.browser,
// cross browser reset 
            css=".linb-node{margin:0;padding:0;line-height:1.22em;}"+
            ".linb-wrapper{color:#000;font-family:arial,helvetica,clean,sans-serif;font-style:normal;font-weight:normal;font-size:12px;vertical-align:middle;}"+
            ".linb-node-table{border-collapse:collapse;border-spacing:0;empty-cells:show;font-size:inherit;"+(b.ie?"font:100%;":"")+"}"+
            ".linb-node-fieldset,.linb-node-img{border:0;}"+
            ".linb-node-ol,.linb-node-ul,.linb-node-li{list-style:none;}"+
            ".linb-node-caption,.linb-node-th{text-align:left;}"+
            ".linb-node-th{font-weight:normal;}"+
            ".linb-node-q:before,.linb-node-q:after{content:'';}"+
            ".linb-node-abbr,.linb-node-acronym{border:0;font-variant:normal;}"+
            ".linb-node-sup{vertical-align:text-top;}"+
            ".linb-node-sub{vertical-align:text-bottom;}"+
            ".linb-node-input,.linb-node-textarea,.linb-node-select{cursor:text;font-family:inherit;font-size:inherit;font-weight:inherit;"+(b.ie?"font-size:100%;":"")+"}"+
            ".linb-node-del,.linb-node-ins{text-decoration:none;}"+
            ".linb-node-pre,.linb-node-code,.linb-node-kbd,.linb-node-samp,.linb-node-tt{font-family:monospace;"+(b.ie?"font-size:108%;":"")+"line-height:100%;}"+
            ".linb-node-select,.linb-node-input,.linb-node-button,.linb-node-textarea{font:99% arial,helvetica,clean,sans-serif;border-width:1px;}"+
// base setting
            ".linb-node-a{cursor:pointer;color:#0000ee;text-decoration:none;}"+
            ".linb-node-a:hover{color:red}"+
            (b.gek? (".linb-node-a:focus{outline-offset:-1px;"+ (parseInt(b.ver)<3?"-moz-outline-offset:-1px !important":"") +"}" ):"")+
            ".linb-node-span, .linb-node-div{border:0;font-size:12px;}"+
            ".linb-node-span, .linb-wrapper span{outline-offset:-1px;"+
            (b.gek
                ? parseFloat(b.ver)<3 
                    ? ((parseInt(b.ver)<3?"-moz-outline-offset:-1px !important;":"") + "display:-moz-inline-block;display:-moz-inline-box;display:inline-block;")
                    :"display:inline-block;"
                : b.ie6
                    ?"display:inline-box;display:inline;"
                :"display:inline-block;")+
            (b.ie?"zoom:1;":"")+
            "}"+
            ".linb-node-h1,.linb-node-h2,.linb-node-h3,.linb-node-h4,.linb-node-h5,.linb-node-h6{font-size:100%;font-weight:normal;}"+
            ".linb-node-h1{font-size:138.5%;}"+
            ".linb-node-h2{font-size:123.1%;}"+
            ".linb-node-h3{font-size:108%;}"+
            ".linb-node-h1,.linb-node-h2,.linb-node-h3{margin:1em 0;}"+
            ".linb-node-h1,.linb-node-h2,.linb-node-h3,.linb-node-h4,.linb-node-h5,.linb-node-h6,.linb-node-strong{font-weight:bold;}"+
            ".linb-node-em{font-style:italic;}"+
            ".linb-node-legend{color:#000;}"+
            (b.ie6?("#"+linb.$localeDomId+"{vertical-align:baseline;}"):"");

        this.addStyleSheet(css, 'linb.CSS');
    }   
});
Class('linb.DomProfile', 'linb.absProfile', {
    Constructor:function(domId){
        if(arguments.callee.upper)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.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("','")+"'])";
        },
        linbid:function(){
            return linb.getId(this.get(0));
        },
        //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.previousSibling!=node){
                    if(this.firstChild) this.insertBefore(node, this.firstChild);
                    else this.appendChild(node);
                }
            },target,reversed);
        },
        append:function(target,reversed){
            return this.$add(function(node){
                if(this.lastChild!=node){
                    this.appendChild(node);
                }
            },target,reversed);
        },
        addPrev:function(target,reversed){
            return this.$add(function(node){
                if(this.firstChild!=node)
                    this.parentNode.insertBefore(node,this);
            },target,reversed);
        },
        addNext:function(target,reversed){
            return this.$add(function(node){
                if(this.nextSibling!=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){
            if(_.isHash(target) || _.isStr(target))
                target=linb.create(target);
            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);

            if(_.isHash(target) || _.isStr(target))
                target=linb.create(target);
            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,loadScripts){
            var s='',t,o=this.get(0);triggerGC=triggerGC!==false;
            if(content!==undefined){
                if(o){
                    if(o.nodeType==3)
                        o.nodeValue=content;
                    else{
                         if(!o.firstChild && content==="")return this;
                         // innerHTML='' in IE, will clear it's childNodes innerHTML
                         // only asy purgeChildren need this line
                         // if(!triggerGC && linb.browser.ie)while(t=o.firstChild)o.removeChild(t);
                         //clear first
                         if(triggerGC)
                            linb.$purgeChildren(o);
                            
                         if(loadScripts){
                                var reg1=/(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
                                reg2=/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
                                reg3 = /\ssrc=([\'\"])(.*?)\1/i,
                                matched, attr,src;
                            while((matched = reg1.exec(content))){
                                attr = matched[1];
                                src = attr ? attr.match(reg3) : false;
                                if(src && src[2]){
                                   linb.include(null,src[2]);
                                }else if(matched[2] && matched[2].length > 0){
                                    _.exec(matched[2]);
                                }
                            }
                            content=content.replace(reg2, '');
                         }
                        
                         o.innerHTML=content;
                        //if(triggerGC)
                        //    linb.UI.$addEventsHanlder(o);

                    }
                    o=null;
                }
                return this;
            }else{
                if(o){
                    s = (o.nodeType==3)?o.nodeValue:o.innerHTML;
                    o=null;
                }
                return s;
            }
        },
        loadHtml:function(options, onStart, onEnd){
            var ns=this;
            if(typeof options=='string')options={url:options};
            _.tryF(onStart);
            linb.Ajax(options.url, options.query, function(rsp){
                var n=linb.create("div");
                n.html(rsp,false,true);
                ns.append(n.children());
                _.tryF(onEnd);
            }, function(err){
                ns.append("<div>"+err+"</div>");
                _.tryF(onEnd);
            }, null, options.options).start();
        },
        loadIframe:function(options){
            if(typeof options=='string')options={url:options};
            var id="aiframe_"+_(),
                e=linb.browser.ie && parseInt(linb.browser.ver)<9,
                ifr=document.createElement(e?"<iframe name='"+id+"'>":"iframe");
            ifr.id=ifr.name=id;
            ifr.src=options.url;
            ifr.frameBorder='0';
            ifr.marginWidth='0';
            ifr.marginHeight='0';
            ifr.vspace='0';
            ifr.hspace='0';
            ifr.allowTransparency='true';
            ifr.width='100%';
            ifr.height='100%';
            this.append(ifr);
            linb.Dom.submit(options.url, options.query, options.method, ifr.name, options.enctype);
        },
        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.toLowerCase(), type=typeof begin,ie=linb.browser.ie, pos;
            if(!/^(input|textarea)$/i.test(tn))return;
            if(tn=="input" && input.type.toLowerCase()!='text'&& input.type.toLowerCase()!='password')return;
            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(linb.Event && (c=linb.Event._getProfile(id)) && 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(linb.Event && (c=linb.Event._getProfile(id)) && 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;
                if('blur'==type || 'focus'==type){
                    try{o[type]()}catch(e){}
                }else{
	                  hash=_.copy(args);
	                  _.merge(hash,{
	                    type: type,
	                    target: o,
	                    button : 1,
	                    $e:true,
	                    $name:name,
	                    preventDefault:f1,
	                    stopPropagation:f2
	                  },'all');                	
                    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,cls;
            this.removeClass("linb-ui-selectable").removeClass("linb-ui-unselectable");
            this.addClass(value?"linb-ui-selectable":"linb-ui-unselectable");
            return this.each(function(o){
                if(linb.browser.ie)
                    o._onlinbsel=value?"true":"false";
            })
        },
        setInlineBlock:function(){
            var ns=this;
            if(linb.browser.gek){
                if(parseFloat(linb.browser.ver)<3)
                    ns.css('display','-moz-inline-block').css('display','-moz-inline-box').css('display','inline-block');
                else
                    ns.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(linb.browser.ie && (p.tagName+"").toUpperCase()=="HTML"){
                p=linb("body").get(0);
            }
            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=(parent.get(0)===document.body || parent.get(0)===document || parent.get(0)===window)?linb.win:parent, 
                box = {};

            //ensure show target on the top of the other elements with the same zindex
            //parent.get(0).appendChild(target.get(0));
            target.cssPos(pos).css({visibility:'hidden',display:'block'});
            parent.append(target);
            
            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'});

            return this;
        },
        //for remove obj when blur
        setBlurTrigger : function(id, trigger, group, checkChild, triggerNext){
            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,
                        srcN=linb.Event.getSrc(e),
                        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;
                        var isChild=function(){
                            var nds=v.target.get();
                            while (srcN && srcN.tagName && srcN.tagName!="BODY" && srcN.tagName!="HTML"){
                                if(_.arr.indexOf(nds,srcN)!=-1)
                                    return true;
                                srcN = srcN.parentNode;
                            }
                        };
                        
                        if(!v.checkChild || isChild()){
                            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,[p,e],v.target);
                            _.arr.removeValue(arr,i);
                            delete arr[i];
                        }else if(v.stopNext){
                            //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,
                    checkChild:!!checkChild,
                    stopNext:!triggerNext
                };
                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 a1=this.get(),a2=[],l=a1.length;
                _.asyRun(function(){
                    for(var i=0;i<l;i++){
                        if((a2[i]=a1[i].style.WordWrap)=='break-word')
                            a1[i].style.WordWrap='normal';
                        else
                            a1[i].style.WordWrap='break-word';
                    }
                });
                _.asyRun(function(){
                    for(var i=0;i<l;i++)
                        a1[i].style.WordWrap=a2[i];
                    a1.length=a2.length=0;
                });
            }
            return this;
        },
        //for ie6
        fixPng:function(type){
            if(linb.browser.ie6){
                type=type||"crop";
                return this.each(function(n){
                    if(n.tagName=='IMG' && /\.png$/i.test(n.src)){
                        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.img_bg;
                    }
                    var bgimg = n.currentStyle.backgroundImage || n.style.backgroundImage,
                        bgmatch = bgimg.match(/^url[("']+(.*\.png[^\)"']*)[\)"']+[^\)]*$/i);
                    if(bgmatch){
                        n.style.backgroundImage = 'url(' + linb.ini.img_bg + ')';
                        n.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, src=" + bgmatch[1] + ", sizingMethod="+type+")";
                    }
                });
            }
        }
        /*,
        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=='string' || (t['linb.DomProfile'] && (t=t.domId)))
                                ? t.charAt(0)=='!'
                                    ?  t
                                    : this._getTag( map[t] ? document.getElementsByTagName(t)[0] : document.getElementById(t))
                            : ((t=arr[i])['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);
        },
        _scrollBarSize:0,
        getScrollBarSize: function(force){
            var ns=this;
            if(force||!ns._scrollBarSize){
                var div;
                linb('body').append(div=linb.create('<div style="width:50px;height:50px;visibility:hidden;position:absolute;margin:0;padding:0;left:-10000px;overflow:scroll;"></div>'));
                ns._scrollBarSize=50-div.get(0).clientWidth+2;
                div.remove();
            }
            return ns._scrollBarSize;
        },
        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.img_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:'progress'});
                    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:{};
            data=_.clone(data, function(o){return o!==undefined});

            method=method||'get';
            action=action||'';
            target=target||'_blank';
            var _t=[];
            if(!_.isEmpty(data)){
                if(method.toLowerCase()=='get'){
                    window.open(action + "?" + _.urlEncode(data),target);
                }else{
                    _.each(data,function(o,i){
                        if(_.isDefined(o))
                            _t.push('<textarea name="'+i+'">'+(typeof o=='object'?_.serialize(o):o)+'</textarea>');
                    });
                    _t.push('<input type="hidden" name="rnd" value="'+_()+'">');
                    _t=_.str.toDom('<form target="'+target+'" action="'+action+'" method="'+method  + (enctype?'" enctype="' +enctype:'') +  '">'+_t.join('')+'</form>');
                    linb.Dom.getEmptyDiv().append(_t);
                    _t.get(0).submit();
                    _t.remove();
                    _t=null;
                }
            }else{
                window.open(action,target);
            }
        },
        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?Math.max(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
            ? parseFloat(linb.browser.ver)<3 
                ? ['-moz-inline-block', '-moz-inline-box','inline-block']  
                : 'inline-block'
            : linb.browser.ie6
                ? ['inline-block', 'inline'] 
                : 'inline-block',
        //hot keys
        linb.doc.onKeydown(function(p,e,s){
            linb.Event.$keyboard=linb.Event.getKey(e);
            
            var event=linb.Event,set,
                ks=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;

            var event=linb.Event,set,
                ks=event.getKey(e);
            if(ks){
                if(ks[0].length==1)ks[0]=ks[0].toLowerCase();
                set = linb.$cache.hookKeyUp[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");

        //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).shiftKey && t.getBtn(e)=='left' && (o.href.indexOf(s+'#')==0||o.href.indexOf('#')==0)){
                        linb.History.setFI(o.href.replace(s,''));
                        return false;
                    }
                }
            },'hookA',0);

        if(linb.browser.ie && document.body)
            document.body.onselectstart=function(n){
                n=event.srcElement;
                while(n&&n.tagName&&n.tagName!="BODY"&&n.tagName!="HTML"){
                    if('_onlinbsel' in n)
                        return n._onlinbsel!='false';
                    n=n.parentNode;
                }
                return true;
            };
        //free memory
        linb.win.afterUnload(function(){
            window.onresize=null;

            if(window.removeEventListener)
                window.removeEventListener('DOMMouseScroll', linb.Event.$eventhandler3, false);
            document.onmousewheel=window.onmousewheel=null;

            if(linb.browser.ie && document.body)
                document.body.onselectstart=null;

            //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()
    }
});/*
    initialize
beforeCreated
onCreated
onLoadBaseClass
onLoadReqiredClass
onIniResource
    iniResource (asy)
beforeIniComponents
    iniComponents (asy)
afterIniComponents
    iniExComs (asy)
onReady
onRender
onDestroy
*/

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

        self.$linbid=self.constructor._ctrlId.next();

        self.properties = properties || (self.properties?_.clone(self.properties):{});
        //copy those from class setting
        self.events = _.copy(self.events) || {};
        if(events)
            _.merge(self.events, events, 'all');
        self._ctrlpool={};
        
        self._innerCall('initialize');
    },
    Instance:{
        autoDestroy:true,
        dataBindLoadType:"sync", // "async", "none"
        _toDomElems:function(){
            var ns=this;
            if(!ns.created)
                // create synchronously
                ns.create(null,false)
            ns.render();
            return ns.getUIComponents()._toDomElems();
        },
        setAlias:function(str){
            var self=this,old=self.alias;
            if(old && self.host && self.host!==self)
                try{delete self.host[old]}catch(e){self.host[old]=undefined}
            if(self.host && self.host!==self)
                self.host[str]=self;
            return self;
        },
        getAlias:function(){
            return this.alias;
        },
        setHost:function(host, alias){
            var self=this;
            self.host=host;
            if(alias)
                self.setAlias(alias);
            return self;
        },
        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;
        },
        // for outter events
        fireEvent:function(name, args, host){
            var t, self=this;
            if(self.events && (t=self.events[name])){
                if(typeof t=='string')t=self[t];
                if(typeof t=='function')
                    return t.apply(host || self.host||self, args||[]);
            }
        },
        // for inner events
        _fireEvent:function(name, args){
            var t, self=this;
            if(self.events && (t=self.events[name])){
                if(typeof t=='string')t=self[t];
                self.$lastEvent=name;
                if(typeof t=='function'){
                    args=args||[];
                    args.splice(0,0,self,self.threadid);
                    return t.apply(self.host||self, args);
                }
            }
        },
        _innerCall:function(name){
            var self=this;
            return _.tryF(self[name],[self, self.threadid],self);
        },
        customAppend:function(parent,subId,left,top,threadid){
            return false;
        },
        show:function(onEnd,parent,subId,threadid,left,top){
            var self=this,f=function(){
                // no UI control in com
                if(self.getUIComponents().isEmpty()){
                    _.tryF(onEnd,[self, threadid],self.host);
                }else{
                    // if parent is an ui object without rendered, dont render the com
                    if(!(parent && parent['linb.UI'] && !parent.get(0).renderId))
                        self.render();

                    if(false===_.tryF(self.customAppend,[parent,subId,left,top,threadid], self))
                        (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);
            return self;
        },
        render:function(triggerLayout){
            var self=this;
            if(self.renderId!='ok'){
                self.getUIComponents().render(triggerLayout);
                self._fireEvent('onRender');
                self.renderId='ok';
            }
            return self;
        },
        create:function(onEnd, threadid){
            //get paras
            var self=this;

            if(self.created){
                _.tryF(onEnd,[self, threadid],self.host);
                return;
            }

            var  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){
                if(threadid)
                    self.threadid=threadid;
                self._fireEvent('onCreated');
            });

            //databinder
            if(self.dataBindLoadType!="none"){
                var bds=self.getDataBinders();
                if(bds && bds.length){
                    var dbf=function(threadid){
                        var hash={};
                        _.arr.each(bds,function(bd, i){
                            var ajax=bd.boxing().read(null,null,null,null,"return");
                            if(ajax)hash[i]=ajax;
                        });
                        if(!_.isEmpty(hash))
                            linb.absIO.groupCall(hash, null, null, null, threadid);
                        bds.length=0;
                        hash=bds=null;
                    };
                    if(self.dataBindLoadType=="sync")
                        funs.push(dbf);
                    else
                        dbf();
                }
            }

            //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 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(){
                    self._createInnerComs();
                });
            //load resource here
            if(self.iniResource)
                funs.push(function(){
                    self._fireEvent('onIniResource');
                    self._innerCall('iniResource');
                });
            //Outter components
            if(self.iniExComs)
                funs.push(function(){
                    self._innerCall('iniExComs');
                });
            //core
            funs.push(function(threadid){
                //lazy load
                if(self.background)
                    linb.SC.runInBG(self.background);
                self._fireEvent('onReady');
            });
            funs.push(function(threadid){
                self.created=true;
                _.tryF(onEnd,[self, threadid],self.host);
            });
            if(threadid===false){
                _.arr.each(funs,function(fun){
                    fun.call();
                });
            }else{
                //use asyUI to insert tasks
                linb.Thread.observableRun(funs,null,threadid);
            }

            return self;
        },
        _createInnerComs:function(){
            var self=this;
            if(self._innerComsCreated)
                return;
            if(false===self._fireEvent('beforeIniComponents'))return;
            Array.prototype.push.apply(self._nodes, self._innerCall('iniComponents')||[]);
            // attach destroy to the first UI control
            if(self.autoDestroy)
                _.arr.each(self._nodes,function(o){
                    if(o.box && o.box["linb.UI"] && !o.box.$noDomRoot){
                        o.$afterdestory=function(){
                            if(!self.destroyed)
                                self.destroy();
                            self=null;
                        };
                        return false;
                    }
                });
            self._fireEvent('afterIniComponents');
            self._innerComsCreated=true;
        },
        iniComponents:function(){},
        getAllComponents:function(){
            if(!this._innerComsCreated)
                this._createInnerComs();

            var arr=[];
            _.each(this._ctrlpool,function(o){
                arr.push(o);
            });
            return linb.absObj.pack(arr,false);
        },
        getDataBinders:function(){
            if(!this._innerComsCreated)
                this._createInnerComs();
            var nodes = _.copy(this._nodes),t,k='linb.DataBinder';
            _.filter(nodes,function(o){
                return !!(o.box[k]);
            });
            return nodes;
        },
        getUIComponents:function(){
            if(!this._innerComsCreated)
                this._createInnerComs();
            var nodes = _.copy(this._nodes),t,k='linb.UI';
            _.filter(nodes,function(o){
                return !!(o.box[k]);
            });
            return linb.UI.pack(nodes, false);
        },
        getComponents:function(){
            if(!this._innerComsCreated)
                this._createInnerComs();
            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){
                // set host
                o.boxing().setHost(self, o.alias);
            });
            return self;
        },
        AddComponents:function(obj){
            var self=this,ns=self._nodes;
            _.arr.each(obj.get(),function(o){
                o.boxing().setHost(self, o.alias);
                self._nodes.push(o);
            });
            return self;
        },
        destroy:function(threadid){
            var self=this,ns=self._nodes;
            self.threadid=threadid;
            self._fireEvent('onDestroy');
            //set once
            self.destroyed=true;
            if(ns && ns.length)
                _.arr.each(ns, function(o){
                    if(o && o.box)
                        o.boxing().destroy();
                },null,true);
            if(ns && ns.length)
                self._nodes.length=0;
            self._ctrlpool=null;
            _.breakO(self);
            //set again
            self.destroyed=true;
        }
    },
    Static:{
        _ctrlId : new _.id(),
        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){},
            onDestroy:function(com){}
        }
    }
});
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);
        },
        clear:function(){
            _.arr.each(document.cookie.split(";"),function(o){
                linb.Cookies.remove(_.str.trim(o.split("=")[0]));
            });
        }
    }
});Class("linb.MessageService",null,{
    Instance:{
        initialize:function(){
            this.$subscribers={};
        },
        subscribe:function(topic, subscriber, receiver, asy){
            if(topic===null||topic===undefined||subscriber===null||subscriber===undefined||typeof receiver!='function')return;
            var c=this.$subscribers,i;
            c[topic]=c[topic]||[];
            i=_.arr.subIndexOf(c[topic],"id",subscriber);
            if(i!=-1)_.arr.removeFrom(c[topic],i);
            return c[topic].push({id:subscriber,receiver:receiver,asy:!!asy});
        },
        unsubscribe:function(topic, subscriber){
            var c=this.$subscribers,i;
            if(!subscriber){
                if(topic===null||topic===undefined)
                    c={};
                else
                    delete c[topic];
            }else if(c[topic]){
                i=_.arr.subIndexOf(c[topic],"id",subscriber);
                if(i!=-1)_.arr.removeFrom(c[topic],i);
            }
        },
        publish:function(topic, args, scope){
            var c=this.$subscribers;
            if(topic===null||topic===undefined){
                for(var topic in c){
                    _.arr.each(c[topic],function(o){
                        if(o.asy)
                            _.asyRun(o.receiver, 0, args, scope);
                        else
                            return _.tryF(o.receiver, args, scope, true);
                    });
                }
            }else if(c[topic]){
                _.arr.each(c[topic],function(o){
                    if(o.asy)
                        _.asyRun(o.receiver, 0, args, scope);
                    else
                        return _.tryF(o.receiver, args, scope, true);
                });
            }
        },
        getSubscribers:function(topic){
            return (topic===null||topic===undefined)?this.$subscribers:this.$subscribers[topic];
        }
    }
});Class('linb.XML',null,{
    Static:{
        //return xml text (for post data)
        json2xml:function(jsonObj, kf, vf){
           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("<"+(kf?kf(key):key)+">"+"__[]__"+"</"+(kf?kf(key):key)+">");
                    }else{
                        var b;
                        arr.push("<"+(kf?kf(key):key));
                        for(var i in value) {
                            if(i.charAt(0)=="@")
                                arr.push(" "+i.substr(1)+'="'+(vf?vf(value[i]):value[i])+'"');
                            else
                                b=1;
                        }
                        arr.push(b?">":"/>");
                        if(b){
                            for(var i in value) {
                                if(i=="#text")
                                    arr.push((vf?vf(value[i]):value[i]));
                                else if(i=="#cdata")
                                    arr.push("<![CDATA["+(vf?vf(value[i]):value[i])+"]]>");
                                else if (i.charAt(0)!="@")
                                    arr.push(_f(i,value[i],arr));
                            }
                            arr.push("</"+(kf?kf(key):key)+">");
                        }
                    }
                }else
                    arr.push("<"+(kf?kf(key):key)+">"+(vf?vf(value):value)+"</"+(kf?kf(key):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;
        }
    }
});Class('linb.XMLRPC',null,{
    Static:{
        //wrapRequest(hash)
        // or wrapRequest(string, hash)
        wrapRequest:function(methodName,params){
            if(typeof methodName=="object"){
                params=methodName.params;
                methodName=methodName.methodName;
            }

            if(!methodName)return null;
            if(params && !params instanceof Array)return null;

            var ns=this,
                xml = ['<?xml version="1.0"?><methodCall><methodName>'+ methodName+'</methodName>'];
            if(params){
                xml.push('<params>');
                for(var i=0,j=params.length;i<j;i++)
                    xml.push('<param>'+ns._wrapParam(params[i])+'</param>');
                xml.push('</params>');
            }
            xml.push('</methodCall>');
            return xml.join('');
        },
        parseResponse:function(xmlObj){
            if(!xmlObj || !xmlObj.documentElement)return null;
            var doc=xmlObj.documentElement;
            if(doc.nodeName!='methodResponse')return null;
            var ns=this,
                json={},
                err,elem;
       
            elem = doc.getElementsByTagName('value')[0];
            if(elem.parentNode.nodeName=='param'&&elem.parentNode.parentNode.nodeName=='params'){
                json.result=ns._parseElem(elem);
            }
            else if(elem.parentNode.nodeName=='fault'){
                err=ns._parseElem(elem);
                json.error = {
                    code:err.faultCode,
                    message:err.faultString
                };
            }
            else return null;

            if(!json.result && !json.error)
                return null;
            return json;
        },
        _dateMatcher:/^(?:(\d\d\d\d)-(\d\d)(?:-(\d\d)(?:T(\d\d)(?::(\d\d)(?::(\d\d)(?:\.(\d+))?)?)?)?)?)$/,
        _parseElem:function(elem){
            var ns=this, 
                nodes=elem.childNodes,
                typeElem, dateElem, name, value, tmp;
            if(nodes.length==1&&nodes.item(0).nodeType==3)
                return nodes.item(0).nodeValue;

            for(var i=0,l=nodes.length;i<l;i++){
                if(nodes.item(i).nodeType==1){
                    typeElem=nodes.item(i);
                    switch(typeElem.nodeName.toLowerCase()){
                        case 'i4':
                        case 'int':
                            value=parseInt(typeElem.firstChild.nodeValue);
                            return isNaN(value)?null:value;
                        case 'double':
                            value=parseFloat(typeElem.firstChild.nodeValue);
                            return isNaN(value)?null:value;
                        case 'boolean':
                            return Boolean(parseInt(typeElem.firstChild.nodeValue)!==0);
                        case 'string':
                            return typeElem.firstChild?typeElem.firstChild.nodeValue:"";
                        case 'datetime.iso8601':
                            if(tmp=typeElem.firstChild.nodeValue.match(ns._dateMatcher)){
                                value = new Date;
                                if(tmp[1]) value.setUTCFullYear(parseInt(tmp[1]));
                                if(tmp[2]) value.setUTCMonth(parseInt(tmp[2]-1));
                                if(tmp[3]) value.setUTCDate(parseInt(tmp[3]));
                                if(tmp[4]) value.setUTCHours(parseInt(tmp[4]));
                                if(tmp[5]) value.setUTCMinutes(parseInt(tmp[5]));
                                if(tmp[6]) value.setUTCSeconds(parseInt(tmp[6]));
                                if(tmp[7]) value.setUTCMilliseconds(parseInt(tmp[7]));
                                return value;
                            }
                            return null;
                        case 'base64':
                            return null;
                        case 'nil':
                            return null;
                        case 'struct':
                            value = {};
                            for(var mElem,j=0;mElem=typeElem.childNodes.item(j);j++){
                                if(mElem.nodeType==1&&mElem.nodeName=='member'){
                                    name='';
                                    elem=null;
                                    for(var child,k=0;child=mElem.childNodes.item(k);k++){
                                        if(child.nodeType==1){
                                            if(child.nodeName=='name')
                                                name=child.firstChild.nodeValue;
                                            else if(child.nodeName=='value')
                                                elem = child;
                                        }
                                    }
                                    if(name&&elem)
                                       value[name] = ns._parseElem(elem);
                                }
                            }
                            return value;
                        case 'array':
                                value = [];
                                dateElem=typeElem.firstChild;
                                while(dateElem&&(dateElem.nodeType!=1||dateElem.nodeName!='data'))
                                    dateElem = dateElem.nextSibling;
                                if(!dateElem)
                                    return null;
                                elem=dateElem.firstChild;
                                while(elem){
                                    if(elem.nodeType==1)
                                        value.push(elem.nodeName=='value'?ns._parseElem(elem):null);
                                    elem=elem.nextSibling;
                                }
                                return value;
                        default:
                                return null;
                    }
                }
            }
            return null;
        },
        _map:{
            "<":"&lt;",
            ">":"&gt;",
            "&":"&amp;",
            '"':"&quot;",
            "'":"&apos;"
        },
        _date2utc:function(d){
            var ns=this,r=this._zeroPad;
            return d.getUTCFullYear()+'-'+
               r(d.getUTCMonth()+1)+'-'+
               r(d.getUTCDate())+'T'+
               r(d.getUTCHours())+':'+
               r(d.getUTCMinutes())+':'+
               r(d.getUTCSeconds())+'.'+
               r(d.getUTCMilliseconds(), 3);
        },
        _zeroPad:function(v,w){
            if(!w)w=2;
            v=((!v&&v!==0)?'':(''+v));
            while(v.length<w)v='0'+v;
            return v;
        },
        _wrapParam:function(value){
            var ns=this,
                map=ns._map,
                xml=['<value>'],sign;
            switch(typeof value){
                case 'number':
                    xml.push(!isFinite(value)?'<nil/>':
                        parseInt(value)===Math.ceil(value)?('<int>'+value+'</int>'):
                        ('<double>'+value+'</double>')
                    );
                    break;
                case 'boolean':
                    xml.push('<boolean>'+(value?'1':'0')+'</boolean>');
                    break;
                case 'string':
                    xml.push('<string>'+value.replace(/[<>&"']/g, function(a){return map[a]})+'</string>');
                    break;
                case 'undefined':
                    xml.push('<nil/>');
                case 'function':
                    xml.push('<string>'+(""+value).replace(/[<>&"']/g, function(a){return map[a]})+'</string>');
                case 'object':
                    sign=Object.prototype.toString.call(value);
                    if(value===null)
                        xml.push('<nil/>');
                    else if(sign==='[object Array]'){
                        xml.push('<array><data>');
                        for(var i=0,j=value.length;i<j;i++)
                            xml.push(ns._wrapParam(value[i]));
                        xml.push('</data></array>');
                    }
                    else if(sign==='[object Date]' && isFinite(+value)){
                        xml.push('<dateTime.iso8601>' + ns._date2utc(value) + '</dateTime.iso8601>');
                    }
                    else {
                        xml.push('<struct>');
                        for(var key in value)
                            if(value.hasOwnProperty(key))
                                xml.push('<member>'+'<name>'+key+'</name>'+ns._wrapParam(value[key])+'</member>');
                        xml.push('</struct>');
                    }
                    break;
            }
            xml.push('</value>');
            return xml.join('');
        }
    }
});Class('linb.SOAP',null,{
    Static:{
        RESULT_NODE_NAME:"return",

        getNameSpace:function(wsdl){
            var ns=wsdl.documentElement.attributes["targetNamespace"];
            return ns===undefined?wsdl.documentElement.attributes.getNamedItem("targetNamespace").nodeValue:ns.value;
        },
        getWsdl:function(queryURL,onFail){
            var rst=false;

            // sync call for wsdl
            linb.Ajax(queryURL+'?wsdl',null,function(rspData){
                rst=rspData;
            },function(rspData){
                _.tryF(onFail,[rspData],this);
            },null,{
                method:'GET',
                rspType:'xml',
                asy:false
            }).start();

            return rst;
        },
        wrapRequest:function(methodName, params, wsdl){
            if(typeof methodName=="object"){
                wsdl=params;
                params=methodName.params;
                methodName=methodName.methodName;
            }
            var ns=this, namespace=ns.getNameSpace(wsdl);
            //return "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
            return  "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" +
                    "<soap:Body>" +
                    "<" + methodName + " xmlns=\""+namespace+"\">" +
                    ns._wrapParams(params) +
                    "</"+methodName+"></soap:Body></soap:Envelope>";
        },
        parseResponse:function(xmlObj, methodName, wsdl){
            if(typeof methodName=="object"){
                methodName=methodName.methodName;
            }
            var ns=this,
                hash={},
                nd=xmlObj.getElementsByTagName(methodName+"Result");
            if(!nd.length)
                nd=xmlObj.getElementsByTagName(ns.RESULT_NODE_NAME);
            if(!nd.length){
                hash.fault={
                    faultcode:xmlObj.getElementsByTagName("faultcode")[0].childNodes[0].nodeValue,
                    faultstring:xmlObj.getElementsByTagName("faultstring")[0].childNodes[0].nodeValue
                };
            }else{
                hash.result=ns._rsp2Obj(nd[0],wsdl);
            }
            return hash;
        },
        _rsp2Obj:function(xmlNode, wsdl){
            var ns=this,
                types=ns._getTypesFromWsdl(wsdl);
            return ns._node2obj(xmlNode,types);
        },
        _getTypesFromWsdl:function(wsdl){
            var types=[],
                ell,useNamedItem;

            ell=wsdl.getElementsByTagName("s:element");
            if(ell.length){
                useNamedItem=true;
            }else{
                ell=wsdl.getElementsByTagName("element");
                useNamedItem=false;
            }
            for(var i=0,l=ell.length;i<l;i++){
                if(useNamedItem){
                    if(ell[i].attributes.getNamedItem("name") != null && ell[i].attributes.getNamedItem("type") != null)
                        types[ell[i].attributes.getNamedItem("name").nodeValue] = ell[i].attributes.getNamedItem("type").nodeValue;
                }else{
                    if(ell[i].attributes["name"] != null && ell[i].attributes["type"] != null)
                        types[ell[i].attributes["name"].value] = ell[i].attributes["type"].value;
                }
            }
            return types;
        },
        _getTypeFromWsdl:function(elems, types){
            return types[elems]==undefined?"":types[elems];
        },
        _node2obj:function(xmlNode, types){
            if(xmlNode==null)return null;
            var ns=this,value,tmp;
            if(xmlNode.nodeType==3||xmlNode.nodeType==4){
                value=xmlNode.nodeValue;
                switch(ns._getTypeFromWsdl(xmlNode.parentNode.nodeName, types).toLowerCase()){
                    case "s:boolean":
                        return value+""=="true";
                    case "s:int":
                    case "s:long":
                        return value===null?0:parseInt(value+"", 10);
                    case "s:double":
                        return value===null?0:parseFloat(value+"");
                    case "s:datetime":
                        if(value == null)
                            return null;
                        else{
                            if(tmp=value.match(ns._dateMatcher)){
                                var d = new Date;
                                if(tmp[1]) d.setUTCFullYear(parseInt(tmp[1]));
                                if(tmp[2]) d.setUTCMonth(parseInt(tmp[2]-1));
                                if(tmp[3]) d.setUTCDate(parseInt(tmp[3]));
                                if(tmp[4]) d.setUTCHours(parseInt(tmp[4]));
                                if(tmp[5]) d.setUTCMinutes(parseInt(tmp[5]));
                                if(tmp[6]) d.setUTCSeconds(parseInt(tmp[6]));
                                if(tmp[7]) d.setUTCMilliseconds(parseInt(tmp[7]));
                                return d;
                            }
                            return null;
                        }
                    //case "s:string":
                    default:
                        return value===null?"":(value+"");
                }
            }else if(xmlNode.childNodes.length==1&&(xmlNode.childNodes[0].nodeType==3||xmlNode.childNodes[0].nodeType==4))
                return ns._node2obj(xmlNode.childNodes[0], types);
            else{
                if(ns._getTypeFromWsdl(xmlNode.nodeName, types).toLowerCase().indexOf("arrayof") == -1){
                    var obj=xmlNode.hasChildNodes()?{}:null;
                    for(var i=0,l=xmlNode.childNodes.length;i<l;i++)
                        obj[xmlNode.childNodes[i].nodeName]=ns._node2obj(xmlNode.childNodes[i], types);
                    return obj;
                }else{
                    var arr =[];
                    for(var i=0,l=xmlNode.childNodes.length;i<l;i++)
                        arr.push(ns._node2obj(xmlNode.childNodes[i], types));
                    return arr;
                }
            }
            return null;
        },
         _wrapParams:function(params){
            var ns=this,arr=[];
            for(var p in params){
                switch(typeof(params[p])){
                    case "string":
                    case "number":
                    case "boolean":
                    case "object":
                        arr.push("<" + p + ">" + ns._wrapParam(params[p]) + "</" + p + ">");
                        break;
                    default:
                        break;
                }

            }
            return arr.join('');
        },
        _map:{
            "<":"&lt;",
            ">":"&gt;",
            "&":"&amp;",
            '"':"&quot;",
            "'":"&apos;"
        },
        _wrapParam:function(param){
            var ns=this,
                s="",
                map=ns._map,
                sign,sign2,type,value;
            switch(typeof(param)){
                case "string":
                    s += param.replace(/[<>&"']/g, function(a){return map[a]});
                    break;
                case "number":
                case "boolean":
                    s += param+"";
                    break;
                case "object":
                    sign=Object.prototype.toString.call(param);
                    // Date
                    if(sign==='[object Date]' && isFinite(+param)){
                        s += ns._date2utc(param);
                    }else if(sign==='[object Array]'){
                        for(var p in param){
                            value=param[p];
                            switch(typeof value){
                                case 'number':
                                    type=parseInt(value)===Math.ceil(value)?'int':'double';
                                    break;
                                case 'boolean':
                                    type='bool';
                                    break;
                                case 'string':
                                    type='string';
                                    break;
                                case 'object':
                                    sign2=Object.prototype.toString.call(value);
                                    if(sign2==='[object Array]'){
                                        type="Array";
                                    }else if(sign2==='[object Date]' && isFinite(+value)){
                                        type="DateTime";
                                    }else
                                        type="object";
                                    break;
                            }
                            s += "<"+type+">"+ns._wrapParam(param[p])+"</"+type+">";
                        }
                    }else{
                        for(var p in param)
                            if(param.hasOwnProperty(p))
                                s += "<"+p+">"+ns._wrapParam(param[p])+"</"+p+">";
                    }
                    break;
            }
            return s;
        },
        _date2utc:function(d){
            var ns=this,r=this._zeroPad;
            return d.getUTCFullYear()+'-'+
               r(d.getUTCMonth()+1)+'-'+
               r(d.getUTCDate())+'T'+
               r(d.getUTCHours())+':'+
               r(d.getUTCMinutes())+':'+
               r(d.getUTCSeconds())+'.'+
               r(d.getUTCMilliseconds(), 3);
        },
        _zeroPad:function(v,w){
            if(!w)w=2;
            v=((!v&&v!==0)?'':(''+v));
            while(v.length<w)v='0'+v;
            return v;
        }
    }
});/*
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);
                    linb.setNodeData(d._proxy.get(0),'zIndexIgnore', 1);
                }
            }

        },
        _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={
                // the unqiue id for dd
                $id:_()+"",

                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,
                targetCallback:NULL,
                tagVar: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._preDroppable at the begining of drag, for a dd from a child in a droppable node
                if(linb.Event && (t=d._source.get(0))){
                    linb.Event._preDroppable= 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 && doc.selection.empty)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'){
                    linb.setNodeData(region.get(0),'zIndexIgnore', 1);
                    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 droppable 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;background:url('+linb.ini.img_bg+') repeat;"><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);
            linb.setNodeData(t.get(0),'zIndexIgnore', 1);

            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',margin:'0',left:'0',top:'0',right:'',bottom:'',cursor:p.dragCursor,'cssFloat':'none'})
                        .cssSize(size)
                        .id('',true)
                        .css('opacity',0.8);

                    if(p.targetCallback)
                        p.targetCallback(n);

                    n.query('*').id('',true);
                    if(p.targetCSS)
                        n.css(p.targetCSS);
                    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" class="linb-node linb-node-table"><tr><td valign="top"><span class="linb-node linb-node-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:'',bottom:''});
                        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;
            },
            draggable: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;
            },
            droppable: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.$localeDomId) && 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(_from.properties.disableTips){
                    node=null;
                    return false;
                }

                //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.$localeDomId) && 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-node linb-node-div linb-tips"><div class="linb-node linb-node-div linb-tips-i"></div></div>');
                        _ruler = self._ruler = linb.create('<div class="linb-node linb-node-div linb-tips" style="position:absolute;visibility:hidden;left:-10000px;"><div class="linb-node linb-node-div 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 class="linb-node linb-node-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';

                        if(pos===true){
                            style.visibility='visible';
                        }else{
                            //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 class="linb-node linb-node-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;
        },
        setTips:function(s){
            if(this._curTips && this._tpl&& this._Node){
                this._tpl.show(s, true);
            }
        },
        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 = '#';
    
                    if(parseInt(linb.browser.ver)<9) {
                        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{
            		    location.hash = hash;
            		}
        		}else if(linb.browser.kde && !linb.browser.isChrome) {
        			// 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,hash;
    	    if(typeof self._callback!='function'){
    	        clearInterval(self._itimer);
    	        return;
    	    }

    		if(linb.browser.ie) {
		        if(parseInt(linb.browser.ver)<9) {
        		    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{
		            hash=location.hash;
        			if(hash != self._lastFI) {
        				self._lastFI = hash;
        				self._callback(hash.replace(/^#/, ''));
        			}
		        }    			
    		}else if(linb.browser.kde && !linb.browser.isChrome) {
    			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
    			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) {
    		    if(parseInt(linb.browser.ver)<9) {
        			var ihistory = document.getElementById(self._fid), iframe = ihistory.contentWindow.document;
                    iframe.open();
        			iframe.close();
        			iframe.location.hash = location.hash = self._lastFI = '#' + fi;
    		    }else{
    		        location.hash=self._lastFI = '#' + fi;
        		}
    		}else if(linb.browser.kde && !linb.browser.isChrome) {
    			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, properties, events){
            singleton=singleton!==false;
            var c=this._cache,
                p=this._pro,
                config,
                clsPath;

            if(singleton && c[id]){
                _.tryF(onEnd, [threadid,c[id]], c[id]);
                return c[id];
            }else{
                // if no configure
                if(!(config=p[id])){
                    config={
                        cls:id,
                        singleton:singleton,
                        properties:properties,
                        events:events
                    };
                    clsPath=id;
                }else
                    clsPath=config.cls || config;

                var self=arguments.callee, 
                    me=this,
                    task=function(cls,config,threadid){
                        var o = new cls();

                        if(config.properties)
                            _.merge(o.properties,config.properties,'all');
                        if(config.events)
                            _.merge(o.events,config.events,'all');
                        if(config.singleton!==false)
                            linb.ComFactory.setCom(id, o);

                        var args = [function(com){
                            var arr = com.getUIComponents().get(),
                                fun=function(arr,subcfg,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 && subcfg && subcfg[cid])
                                                self.apply(me, [subcfg[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, subcfg);
                                        }
                                    });
                                };
                            //handle tag sub from com
                            fun(arr,config.children,1);
                        }];
                        args.push(threadid||null);

                        //insert first
                        if(onEnd)
                            linb.Thread(threadid).insert({
                                task:onEnd,
                                args:[threadid,o],
                                scope:o
                            });
                        //latter
                        _.tryF(o[config.iniMethod ||'create'], 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, config,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, properties, events){
            return this.getCom(cls, onEnd, threadid, false, properties, events);
        },
        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);
                }
            }
        },
        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-node linb-node-div linb-wrapper linb-dbg-frm"><div class="linb-node linb-node-div linb-dbg-box"><div id='+self._id4+' class="linb-node linb-node-div linb-dbg-header">&nbsp;&nbsp;:&nbsp;)&nbsp;&nbsp;jsLINB Monitor window <span class="linb-node linb-node-span linb-dbg-cmds"><a class="linb-node linb-node-a" href="javascript:;" onclick="linb(\''+self._id2+'\').empty();">Clear</a><a class="linb-node linb-node-a" href="javascript:;" onclick="linb(\''+self._id1+'\').remove();"> &Chi; </a></span></div><div id='+self._id2+' class="linb-node linb-node-div linb-dbg-content"></div><div class="linb-node linb-node-div linb-dbg-tail"><table class="linb-node linb-node-table"><tr><td style="font-family:serif;">&nbsp;>>>&nbsp;</td><td style="width:100%"><input class="linb-node linb-node-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(ns.addShadow)ns.addShadow();

                if(linb.browser.ie6){
                    ns.height(ns.offsetHeight());
                    ns.width(299);
                    _.asyRun(function(){ns.width(300);})
                }
                var bak='',temp;
                linb(self._id3).onKeydown(function(p,e,s){
                    var k=linb.Event.getKey(e).key;
                    s=linb.use(s).get(0);
                    if(k=='enter'){
                        switch(s.value){
                            case '?':
                            case 'help':
                                self.$con.append(linb.create("<div class='linb-node linb-node-div linb-dbg-con3'><p class='linb-node linb-node-p'><strong  class='linb-node linb-node-strong'>vailable commands:</strong></p><ul  class='linb-node linb-node-ul'><li  class='linb-node linb-node-li'> -- <strong  class='linb-node linb-node-strong'>[clr]</strong> or <strong>[clear]</strong> : clears the message</li><li  class='linb-node linb-node-li'> -- <strong  class='linb-node linb-node-strong'>[?]</strong> or <strong  class='linb-node linb-node-strong'>[help]</strong> : shows this message</li><li  class='linb-node linb-node-li'> -- <strong class='linb-node linb-node-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-node linb-node-div 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;width:298px;}'+
            '.linb-dbg-con2{padding-left:6px;border-bottom:dashed 1px #CCC;width:292px;}'+
            '.linb-dbg-con3{padding-left:6px;border-bottom:dashed 1px #CCC;background:#EEE;color:#0000ff;width:292px;}'+
            '.linb-dbg-con4{padding-left:6px;border-bottom:dashed 1px #CCC;background:#EEE;color:#ff0000;width:292px;}'+
            '.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=[]),
           allmsg=me.allmsg||(me.allmsg=[]),
           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="linb-node linb-node-div linb-wrapper linb-uibg-bar linb-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 class="linb-node linb-node-div" style="font-size:14px;overflow:hidden;font-weight:bold;padding:2px;"></div>'+
                   '<div class="linb-node linb-node-div" style="font-size:12px;padding:5px;overflow:hidden;"></div>'+
               '</div>';
               div = linb.create(div);
               if(div.addBorder)div.addBorder();
               linb('body').append(div);
               allmsg.push(div);
            }
            div.__hide=0;

            div.css({left:left+'px', width:width+'px', visibility:'visible'})
            .first().html(head||'').css('display',head?'':'none')
            .next().html(body||'');

            if(linb.browser.id)
                div.ieRemedy();

            if(me.last && div!=me.last){
                var last=me.last;
                var l=last.left();
                if(last._thread&&last._thread.id&&last._thread.isAlive())last._thread.abort();
                last._thread=last.animate({left:[l,l+(last.width+width)/2+20]},function(){
                    last.left(l);
                },function(){
                    last.left(l+(last.width+width)/2+20);
                },100,5).start();
                
                var lh=last.offsetHeight();
               _.filter(allmsg,function(ind){
                    if(ind.isEmpty())
                        return false;
                   if(!ind.__hide && ind!=div && ind!=last){
                       if(ind._thread.id&&ind._thread.isAlive())
                            ind._thread.abort();
                       ind.topBy(lh);
                    }
               });

            }
            me.last = div;
            me.last.width = width;

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

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

            if(div._thread&&div._thread.id&&div._thread.isAlive())div._thread.abort();
            div._thread=div.animate({top:[st-h-20,st+20]},function(){
                div.top(st-h-20);
            },function(){
                div.top(st+20);
            },100,5,'expoOut').start();

            _.asyRun(function(){
                if(div._thread&&div._thread.id&&div._thread.isAlive())div._thread.abort();
                div._thread=div.animate({top:[div.top(), height+20]},null,function(){
                     stack.push(div); 
                     div.hide();
                     div.__hide=1;
                },100,10).start();
            }, time||5000);
        };
    }
});//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.rendered=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);
                _.tryF(ns.$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.properties.lazyAppend){
                if(ns.children)
                    for(var i=0,v;v=ns.children[i++];)
                        if(v[0]._render)
                            v[0]._render(true);

                if(ns.$attached){
                    for(var i=0,v;v=ns.$attached[i++];)
                        if(v._render)
                            v._render(true);
                    delete ns.$attached;
                }
                if(ns.exchildren){
                    var arr=[];
                    for(var i=0,v;v=ns.exchildren[i++];)
                        ns.boxing().append(v[0],v[1]);
                    delete ns.exchildren;
                }
                if(ns.excoms){
                    var arr=[];
                    for(var i=0,v;v=ns.excoms[i++];)
                        v[0].show(null, ns.boxing(), v[1], false);
                    delete ns.excoms;
                }
            }
        },
        __gc:function(){
            var ns=this, t;
            if(ns.destroyed)return;
            // special one
            if(ns.$beforeDestroy){
                _.tryF(ns.$beforeDestroy,[],ns);
                delete ns.$beforeDestroy;
            }
            _.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;
            }

            //set once
            ns.destroyed=true;
            //afterDestroy
            _.tryF(ns.$afterdestory,[],ns);
            if(ns.afterDestroy)ns.boxing().afterDestroy(ns);
            _.breakO([ns.properties,ns.events, ns.CF, ns.CB, ns.CC, ns.CS, ns],2);
            //set again
            ns.destroyed=true;
        },
        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?[this.renderId]:[],false);
        },
        getContainer:function(subId){
            if(subId=typeof subId=='string'?subId:null)subId=this.getSubIdByItemId(subId);
            return this.box._CONTAINERKEY?this.getSubNode(this.box._CONTAINERKEY, subId):this.keys.PANEL?this.getSubNode(this.keys.PANEL, subId):this.getRoot();
        },
        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:/<!--\x03([^>^\s]*)\x04-->/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((!self.properties.lazyAppend||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, addEventHandler){
            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,''), addEventHandler);
        },
        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;
            }
            if(typeof o.theme=="string")
              r.theme=o.theme;

            //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.CB)) r.CB=_.copy(o.CB);
            if(!_.isEmpty(o.CC)) r.CC=_.copy(o.CC);
            if(!_.isEmpty(o.CF)) r.CF=_.copy(o.CF);
            if(!_.isEmpty(o.CS)) r.CS=_.copy(o.CS);
            if(typeof o.theme == "string") r.theme=o.theme;

            //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
                });
            }
            if(o.exchildren && o.exchildren.length){
                r.exchildren=o.exchildren;
            }
            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]=_.isSet(subId)?(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;

            // destroyed already
            if(!self.renderId)return linb();

            var key=self.keys[key] || key,
                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(!_.isSet(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(!_.isSet(subId))h[key]=r;
            }
            return r;
        },
        getSubNodes:function(arr,subId){
            if(!subId)subId=true;
            var a=[],s1=typeof arr=='string',s2=typeof subId=='string'||subId===true,o,v;
            if(s1){
                if(s2)
                    Array.prototype.push.apply(a,this.getSubNode(arr,subId).get());
                else
                    for(var j=0;v=subId[j++];)
                        Array.prototype.push.apply(a,this.getSubNode(arr,v).get());
            }else
                for(var i=0;o=arr[i++];){
                    if(s2)
                        Array.prototype.push.apply(a,this.getSubNode(o,subId).get());
                    else
                        for(var j=0;v=subId[j++];)
                            Array.prototype.push.apply(a,this.getSubNode(o,v).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, flag, 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, flag, r);
                    });
                });
            f(items, fun, deep, single, flag, 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:{
        setTheme:function(key){
            if(typeof key!="string" || !key)key=null;
            var k,arr=[];
            this.each(function(o){
                if(key!=o.theme){
                    if(key===null)
                        delete o.theme;
                    else
                        o.theme=key;
                    arr.push(o);
                }
            });
            linb.UI.pack(arr,false).refresh();
            return this;
        },
        getTheme:function(){
            return this.get(0) && this.get(0).theme;
        },
        destroy:function(){
            this.each(function(o){
                if(o.destroyed)return;
                // special one
                if(o.$beforeDestroy){
                    _.tryF(o.$beforeDestroy,[],o);
                    delete o.$beforeDestroy;
                }
                if(o.beforeDestroy && false===o.boxing().beforeDestroy())return;
                if(o.renderId)o.getRoot().remove();
                else o.__gc();
            });
            this._nodes.length=0;
        },
        isDestroyed:function(){
            return !!(this.get(0)?this.get(0).destroyed:1);
        },
        _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, theme, 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?_.copy(CS):(profile.CS||{});
            profile.CB = CB?_.copy(CB):(profile.CB||{});
            profile.CC = CC?_.copy(CC):(profile.CC||{});
            profile.CF = CF?_.copy(CF):(profile.CF||{});
            if(typeof theme =="string")profile.theme = theme;

            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);
            profile._cacheInstance=self;

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

                    if(!profile.$busy||profile.$busy.isEmpty()){
                        node=profile.$busy=linb.create('<div style="left:0;top:0;z-index:10;position:absolute;background-color:#DDD;width:100%;height:100%;"></div><div style="left:0;top:0;z-index:20;text-align:center;position:absolute;width:100%;height:100%;"><div>'+html+'</div></div>');
                        linb([node.get(0)]).css({opacity:0.5});
                    }
                    node=profile.$busy;

                    linb([node.get(1).firstChild]).html(html,false).css('paddingTop',(parentNode.offsetHeight()||0)/2+'px');

                    parentNode.append(node);
                },50,[profile,key,subId]);
            });
        },
        free:function(){
            return this.each(function(profile){
                _.resetRun(profile.$linbid+':busy');
                if(profile.$busy){
                    profile.$busy.remove();
                    delete profile.$busy;
                }
            });
        },
        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'){
                    o.boxing().adjustDock(force);
                }else{
                    if(force){
                        o._resize_h=-1;
                        o._resize_w=-1;
                    }
                    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.setHost(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(){
            return arguments.callee.upper.apply(this,["domId"]);
        },
        refresh:function(remedy){
            var para,node,b,p,s,$linbid,serialId,fun,box,children,uiv;
            return this.each(function(o){
                if(!o.renderId)return;

                box=o.box;

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

                var ar=o.$afterRefresh;

                if(typeof o.boxing().getUIValue=='function'){
                    uiv=o.boxing().getUIValue();
                    if((o.boxing().getValue() + " ")==(uiv+" "))
                        uiv=null;
                }

                //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
                //for example: if use getGhostDiv, upload input cant show file name
                node=remedy?linb.Dom.getEmptyDiv():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.$refreshTrigger;

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

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

                // keep cache refrence
                var _c=o._cacheInstance;
                o.boxing().destroy();

                //set back
                _.merge(o,s,'all');
                // notice: remove destroyed here
                delete o.destroyed;
                o.$linbid=$linbid;
                o.serialId=serialId;

                //create
                o=new box(o).render();
                
                // set cache refrence
                if(_c){
                    _.merge(_c,o,'all');
                    o.get(0)._cacheInstance=_c;
                }

                //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;

                if(uiv)
                    o.setUIValue(uiv,true);
                    
                if(ar){
                    o.get(0).$afterRefresh=ar;
                    ar(o.get(0));
                }
            });
        },
        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(target['linb.Com']){
                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);
                }
                else{
                    (pro.excoms||(pro.excoms=[])).push([target,subId]);
                }
            }else{
                if(subId!==false){
                    if(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);
                }else{
                    if(!target['linb.UI']){
                        if(!pro.exchildren)
                            pro.exchildren=[];
                        pro.exchildren.push([target,subId]);
                    }
                }
            }

            if(pro.afterAppend)
                this.afterAppend(pro,target);
            return this;
        },
        getParent:function(){
            var prf=this.get(0);
            if(prf)return prf.parent && prf.parent.boxing();
        },
        getChildrenId:function(){
            var prf=this.get(0);
            if(prf)return prf.childrenId;
        },
        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===true?1: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();                    }
                });
            });
        },
        draggable:function(dragKey, dragData, key, options){
            return this.each(function(o){
                o.getSubNode(o.keys[key] || 'KEY', true)
                .beforeMousedown(dragKey?function(pro,e,src){
                    if(linb.Event.getBtn(e)!="left")return;
                    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();
            });
        },
        adjustDock:function(force){
            return this.each(function(o){
                if(o.properties.dock && o.properties.dock!='none' && o.renderId){
                    var n=o.getRootNode();
                    // ensure display
                    if(n.clientHeight){
                        if(force){
                            // ensure force 1
                            n.style.width=0;
                            n.style.height=0;
                            // ensure force 2
                            o._resize_h=-1;
                            o._resize_w=-1;
                        }
                        linb.UI.$dock(o,true,true);
                    }
                }
            });
        }
    },
    Initialize:function(){
        var ns=this.prototype;
        _.arr.each('getSubNode,getDomId,getRootNode,getRoot,getContainer'.split(','),function(o){
            if(!ns[o])
                ns[o]=function(){
                    var p=this.get(0);
                    return p ? p[o].apply(p,arguments) : null;
                };
                ns[o].$original$='linb.UI';
                ns[o].$type$='instance';
                ns[o].$name$=o;
        });

        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;
                    self.getRoot()[o]?self.getRoot()[o](value):linb.Dom._setPxStyle(self.getRootNode(),o,value);
                    if(o=='width'||o=='height'){
                        // for no _onresize widget only
                        if(!self.box._onresize && 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)
                    }

                    if(p.dock!='none'){
                        args={
                            $type:p.dock,
                            $dockid:_.arr.indexOf(['width','height','fill','cover'],p.dock)!=-1?self.$linbid:null
                        };
                        switch(p.dock){
                            case 'middle':
                                if(o!='height'&&o!='top')return;
                                args.top=args.height=1;
                                break;
                            case 'center':
                                if(o!='width'&&o!='left')return;
                                args.left=args.width=1;
                                break;
                            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;
                        }
                        _.tryF(self.$dockFun,[args],self);
                    }
                }
            }
        });
        _.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);
                    // special for resizer
                    if(this.$resizer){
                        if(value=='hidden')
                            this.$resizer.hide();
                        else
                            this.$resizer.show();
                    }

                    linb.setNodeData(this.getRootNode(),'_setVisibility',1);
                }
            },
            display:{
                listbox:['','none','block','inline','inline-block'],
                action:function(value){
                    if(value=='inline-block')
                        this.getRoot().setInlineBlock();
                    else
                        this.getRoot().css('display',value);
                }
            },
            selectable:{
                ini:false,
                action:function(value){
                    this.getRoot().setSelectable(!!value);
                }
            }
        });

        self.setDataModel(hash);

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

            '.linb-uicmd-toggle':{
                $order:1,
                'background-position': '-160px -70px'
            },
            '.linb-uicmd-toggle-mouseover':{
                $order:2,
                'background-position': '-160px -90px'
            },
            '.linb-uicmd-toggle-mousedown':{
                $order:3,
                'background-position': '-160px -110px'
            },
            '.linb-uicmd-toggle-checked':{
                $order:4,
                'background-position': '-180px -70px'
            },
            '.linb-uicmd-toggle-checked-mouseover':{
                $order:5,
                'background-position': '-180px -90px'
            },
            '.linb-uicmd-toggle-checked-mousedown':{
                $order:6,
                'background-position': '-180px -110px'
            },
            '.linb-uicmd-toggle2':{
                $order:1,
                'background-position': '-200px -70px'
            },
            '.linb-uicmd-toggle2-mouseover':{
                $order:2,
                'background-position': '-200px -90px'
            },
            '.linb-uicmd-toggle2-mousedown':{
                $order:3,
                'background-position': '-200px -110px'
            },
            '.linb-uicmd-toggle2-checked':{
                $order:4,
                'background-position': '-220px -70px'
            },
            '.linb-uicmd-toggle2-checked-mouseover':{
                $order:5,
                'background-position': '-220px -90px'
            },
            '.linb-uicmd-toggle2-checked-mousedown':{
                $order:6,
                'background-position': '-220px -110px'
            },
            '.linb-uicmd-none':{
                display:'none'
            },
            '.linb-uicmd-empty':{
                $order:1000,
                width:'16px',
                height:'16px',
                'margin-right':'2px',
                cursor:'default',
                'vertical-align':'middle',
                background:'none'
            },


            '.linb-uibar-top, .linb-uibar-bottom, .linb-uibar-top-s, .linb-uibar-bottom-s':{
                position:'relative',
                //for avoiding extra space after table in IE
                'vertical-align':'baseline',
                'font-size':0,
                'line-height':0
            },
            '.linb-uibar-top td, .linb-uibar-top-s td, .linb-uibar-bottom td, .linb-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*/
            '.linb-uibar-top, .linb-uibar-top .linb-uibar-t':{
                height:'29px'
            },
            '.linb-uibar-top .linb-uibar-tdl':{
                $order:1,
                'padding-left':'4px',
                height:'100%',
                'background-position': '0 0'
            },
            '.linb-uibar-top .linb-uibar-tdm':{
                $order:1,
                'background-position': '0 -30px',
                'background-repeat': 'repeat-x'
            },
            '.linb-uibar-top .linb-uibar-tdr':{
                $order:1,
                'padding-left':'4px',
                'background-position': 'right -60px'
            },
            '.linb-uibar-top-focus .linb-uibar-tdl':{
                $order:2,
                'padding-left':'4px',
                height:'100%',
                'background-position': 'left -90px'
            },
            '.linb-uibar-top-focus .linb-uibar-tdm':{
                $order:2,
                'background-position': 'left -120px',
                'background-repeat': 'repeat-x'
            },
            '.linb-uibar-top-focus .linb-uibar-tdr':{
                $order:2,
                'padding-left':'4px',
                'background-position': 'right -150px'
            },
            '.linb-uibar-top .linb-uibar-cmdl':{
                overflow:'hidden',
                position:'absolute',
                left:0,
                top:'6px',
                width:'92%',
                height:'22px',
                'padding-left':'8px',
                'white-space': 'nowrap'
            },
            '.linb-uibar-top .linb-uibar-cmdr':{
                position:'absolute',
                top:'6px',
                right:'8px',
                'text-align':'right'
            },
            '.linb-uicon-main':{
                position:'relative',
                'padding-left':'4px',
                'font-size':0,
                'line-height':0,
                'z-index':1,
                overflow:'visible',
                background: linb.UI.$bg('bar_horizontal.gif', 'repeat-y -595px top', true)
            },
            '.linb-uicon-maini':{
                'padding-right':'4px',
                'font-size':0,
                'line-height':0,
                background: linb.UI.$bg('container_right.gif', '#AAD2FA repeat-y right top', true)
            },
//uibar-bottom
            '.linb-uibar-bottom, .linb-uibar-bottom .linb-uibar-t':{
                height:'12px'
            },
            '.linb-uibar-bottom .linb-uibar-tdl':{
                $order:1,
                'padding-left':'4px',
                height:'100%',
                'background-position': 'left -189px'
            },
            '.linb-uibar-bottom .linb-uibar-tdm':{
                $order:1,
                'background-position': 'left -211px',
                'background-repeat': 'repeat-x'
            },
            '.linb-uibar-bottom .linb-uibar-tdr':{
                $order:1,
                'padding-left':'4px',
                'background-position': 'right -233px'
            },
//uibar-top-s
            '.linb-uibar-top-s, .linb-uibar-top-s .linb-uibar-t':{
                $order:3,
                height:'7px'
            },
            '.linb-uibar-top-s .linb-uibar-tdl':{
                $order:3,
                height:'100%',
                'padding-left':'4px',
                'background-position': 'left -261px'
            },
            '.linb-uibar-top-s .linb-uibar-tdm':{
                $order:3,
                'background-position': 'left -283px',
                'background-repeat': 'repeat-x'
            },
            '.linb-uibar-top-s .linb-uibar-tdr':{
                $order:3,
                'padding-left':'4px',
                'background-position': 'right -305px'
            },
            '.linb-uibar-top-s .linb-uibar-cmdl':{
                $order:3,
                display:'none'
            },
            '.linb-uibar-top-s .linb-uibar-cmdr':{
                $order:3,
                display:'none'
            },
//uibar-bottom-s
            '.linb-uibar-bottom-s, .linb-uibar-bottom-s .linb-uibar-t':{
                $order:3,
                height:'6px'
            },
            '.linb-uibar-bottom-s .linb-uibar-tdl':{
                $order:3,
                height:'100%',
                'padding-left':'4px',
                'background-position': 'left -327px'
            },
            '.linb-uibar-bottom-s .linb-uibar-tdm':{
                $order:3,
                'background-position': 'left -349px',
                'background-repeat': 'repeat-x'
            },
            '.linb-uibar-bottom-s .linb-uibar-tdr':{
                $order:3,
                'padding-left':'4px',
                'background-position': 'right -371px'
            }
        })
        + linb.UI.buildCSSText({
            '.linb-ui-unselectable':{
                $order:0,
                '-moz-user-select': linb.browser.gek?'-moz-none':null,
                '-khtml-user-select': linb.browser.kde?'none':null,
                '-webkit-user-select': linb.browser.kde?'none':null,
                '-o-user-select':linb.browser.opr?'none':null,
                'user-select':'none'
            },
            '.linb-ui-selectable':{
                $order:1,
                '-moz-user-select': linb.browser.gek?'text':null,
                '-khtml-user-select': linb.browser.kde?'text':null,
                '-webkit-user-select': linb.browser.kde?'text':null,
                '-o-user-select':linb.browser.opr?'text':null,
                'user-select':'text'
            },
            '.linb-ui-ctrl':{
                cursor:'default',
                'font-family':'arial,helvetica,clean,sans-serif',
                'font-style':'normal',
                'font-weight':'normal',
                'font-size':'12px',
                'vertical-align':'middle'
            },
            '.linb-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*/
            '.linb-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*/
            '.linb-uiw-border':{
                $order:2,
                display:'block',
                position:'absolute',
                border:0,
                padding:0,
                margin:0,
                left:0,
                top:0,
                width:'100%',
                height:'100%'
            }
        })
        + linb.UI.buildCSSText({
            '.linb-uibg-base':{
                'background-color':'#fff'
            },
            '.linb-uibg-bar':{
                'background-color':'#aad2fa'
            },
            '.linb-uiborder-flat':{
                border:'solid 1px #648cb4'
            },
            '.linb-uiborder-inset':{
                border:'solid 1px',
                'border-color':'#648cb4 #c8e1fa #c8e1fa #648cb4'
            },
            '.linb-uiborder-outset':{
                border:'solid 1px',
                'border-color':'#c8e1fa #648cb4 #648cb4 #c8e1fa'
            }
        });

        linb.UI.$cache_css2 += linb.UI.buildCSSText({
            '.linb-ui-dirty':{
                $order:1,
                'background-image': linb.UI.$bg('icons.gif', '', true),
                'background-repeat': 'no-repeat',
                'background-position':'-390px -290px'
            },
            '.linb-ui-inputdisabled':{
                color:'#808080'
            },
            '.linb-ui-itemreadonly':{
                $order:2,
                color: '#808080'
            },
            '.linb-ui-readonly, .linb-ui-readonly *':{
                $order:2,
                color: '#808080'
            },
            '.linb-ui-itemdisabled':{
                $order:2,
                cursor:'not-allowed',
                color: '#808080'
            },
            '.linb-ui-disabled, .linb-ui-disabled *':{
                $order:2,
                color: '#808080'
            },
            '.linb-ui-invalid, .linb-ui-invalid *':{
                $order:1,
                'background-color': '#FFEBCD'
            }
        });
    },
    $End:function(){
        linb.UI.$cache_css += this.buildCSSText(this.$Appearances);
    },
    Static:{
        $cache_css:'',
        $cache_css2:'',
        $css_tag_dirty: "linb-ui-dirty",
        $css_tag_invalid: "linb-ui-invalid",
        $tag_left:"{",
        $tag_right:"}",
        $tag_subId:"_serialId",


        $x01:/\x01/img,
        $x01r:/ \x01 /img,

        $tag_special:'\x01',
        $ID:"\x01id\x01",
        $DOMID:'\x01domid\x01',
        $CLS:"\x01cls\x01",
        $childTag:"<!--\x03{id}\x04-->",

        $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},
        _objectProp:{tagVar:1},
        $toDom:function(str, addEventHandler){
            if(addEventHandler===false)
                return _.str.toDom(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();
        },
        _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,
                x01=linb.UI.$x01,
                x01r=' \x01 ',
                str='',
                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===undefined || t===null || t===NaN)?str:typeof t=='string'?t.replace(x01,x01r):t;
                                }
                            }else
                                result[result.length]=(a0[i]===undefined || a0[i]===null || a0[i]===NaN)?str: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,
                prop=profile.properties,
                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}),
                map3 = self.map3 ||(self.map3={input:1,textarea:1,pre:1,code: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, tagN,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 || '';
                tagN=template.tagName.toLowerCase();

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

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

            var a=[], b={},
                tagName=template.tagName.toLowerCase(),
                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+' ';

            // add "unselectable" to node
            if(lkey==profile.key){
                // unselectable="on" will kill onBlur
                if(linb.browser.ie)
                    b._onlinbsel="{_selectable}";
            }

            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,
                ui=linb.UI,
                tag=ui.$tag_special,
                r=me._r||(me._r=new RegExp( tag+'([0-9A-Z_]+)_C([SCT])'+tag + '|'+ tag+'([\\w_\\-\\.]*)'+tag, 'img')),
                h1={
                    id:profile.serialId,
                    cls:profile.getClass('KEY'),
                    domid:profile.$domId
                },
                h2={
                    S:profile.CS,
                    C:profile.CC,
                    T:profile._CT
                };
            return temp.replace(r, function(a,b,c,d){return h1[d] || (h2[c]?(h2[c][b]||""):'')}).replace(ui.$x01r,'\x01');
        },
        _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||'');

            //build custom theme hash here
            if(typeof profile.theme == "string"){
                var h=profile._CT={},
                    pre=profile.key.replace(/\./g,'-').toLowerCase().replace('linb-ui','linb')+"-";
                _.each(profile.keys,function(o,i){
                    if(i.charAt(0)!='$')
                        h[i]=pre + profile.theme + "-" + i.toLowerCase();
                });
            }
            //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 || prop.readonly)return;
                        item = profile.SubSerialIdMapItem && profile.SubSerialIdMapItem[cid];
                        if(item && item.disabled)return;
                        if(item && item.readonly)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'){
                                    if(prop.disableHoverEffect)
                                        return;
                                    if(profile.beforeHoverEffect && false === box.beforeHoverEffect(profile, item, e, src, 'mouseover'))
                                        return;
                                }
                                if(type=='mousedown'){
                                    if(prop.disableClickEffect)
                                        return;
                                    if(profile.beforeClickEffect && false === box.beforeClickEffect(profile, item, e, src, 'mousedown'))
                                        return;
                                }

                                //default action
                                nodes.tagClass('-'+type);
                            }else{
                                if(type=='mouseup'){
                                    if(prop.disableClickEffect)
                                        return;
                                    if(profile.beforeClickEffect && false === box.beforeClickEffect(profile, item, e, src, 'mouseup'))
                                        return;
                                    nodes.tagClass('-mousedown', false);
                                }else{
                                    if(prop.disableHoverEffect)
                                        return;
                                    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, keyboard, e, src){},
                        _e3:function(profile, e, shiftKey, src){},
                        _e4:function(profile, e, src, dragKey, dragData, 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
            _.merge(hash,{
                beforeKeydown:function(profile, e, src){
                    if(profile.onHotKeydown)
                        return false !== profile.boxing().onHotKeydown(profile,linb.Event.getKey(e),e, src);
                },
                beforeKeypress:function(profile, e, src){
                    if(profile.onHotKeypress)
                        return false !== profile.boxing().onHotKeypress(profile,linb.Event.getKey(e),e, src);
                },
                beforeKeyup: function(profile, e, src){
                    if(profile.onHotKeyup)
                        return false !== profile.boxing().onHotKeyup(profile,linb.Event.getKey(e),e, src);
                }
            });

            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]={});

                    var 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.key, ctrl=k.ctrlKey, shift=k.shiftKey, alt=k.altKey, b=false, smartnav=profile._smartnav;
                            if(smartnav){
                                var node=linb.use(src).get(0);
                                if(m2[k=node.tagName.toLowerCase()]){
                                    if(key && k=="input" && node.type.toLowerCase()!='text'&& node.type.toLowerCase()!='password'){
                                        b=true;
                                    }else 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;
                                }
                               node=null;
                            }else
                                b=key==='tab';

                            //hanlder focus
                            if(b){
                                //export event
                                if(profile.beforeNextFocus && false === profile.boxing().beforeNextFocus(profile,e,k.shiftKey,src))
                                    return false;

                                if(smartnav){
                                    if(key!='tab')
                                        linb.use(src).nextFocus(('up'==key || 'left'==key)?false:true);
                                }
                            }
                        }
                    }
                });
                hls.beforeNextFocus=src._e3;
            }
            if((t=hash.DroppableKeys) && t.length){
                _.arr.each(t,function(o){
                    self._droppable(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.beforeDrop=hls.onDrop=hls.afterDrop=hls.onDropTest=hls.onDropMarkShow=hls.onDropMarkClear=src._e4;
            }
            if((t=hash.DraggableKeys)&& t.length){
                _.arr.each(t,function(o){
                    self._draggable(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;
            }
            if((t=hash.NoDraggableKeys)&& t.length){
                self.NoDraggableKeys=t;
            }
            if((t=hash.NoDroppableKeys) && t.length){
                self.NoDroppableKeys=t;
            }

            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, refresh, onSucess, onFail){
            key=key||'default';
            var ns=this;
            if(key!=ns.$theme){
                if(refresh!==false){
                    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;
                if(refresh!==false){
                    ns.$CSSCACHE={};
                    var count=0;
                    _.asyRun(function(){
                        if(count>10){
                            if(false!==_.tryF(onFail))
                                throw new Error('errLoadTheme:'+key);
                        }
                        count++;
                        var s;
                        try{
                            s=linb.CSS.$getCSSValue('.setting-uikey','fontFamily');
                        }catch(e){}finally{
                            if(s==key || key=='default'){
                                linb.UI.getAll().reLayout(true);
                                _.tryF(onSucess);
                                count=null;
                            }else
                                _.asyRun(arguments.callee,200*count);
                        }
                    },200);
                }
            }
            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, cache1=self.$cache_css, cache2=self.$cache_css2;
            if(!self.$cssNo){
                self.$cssNo=1;
                var b=linb.browser;
                linb('body').addClass(
                          (b.ie ? ("linb-css-ie linb-css-ie" + b.ver + " ") :
                           b.gek ? ("linb-css-gek linb-css-gek" + b.ver + " ") :
                           b.kde ? ("linb-css-kde linb-css-kde" + b.ver + " ") :
                           b.opr ? ("linb-css-opr linb-css-opr" + b.ver + " ") : "")
                        + (b.isSafari ? "linb-css-safari ": b.isChrome ? "linb-css-chrome " :"")
                        + (b.isMac ? "linb-css-mac": b.isLinux ? "linb-css-linux " :"")
                );
                linb('html').addClass(b.isStrict?"linb-css-base linb-css-strict":"linb-css-base ");
            }
            if(cache1){
                linb.CSS.addStyleSheet(cache1, 'linb.UI-CSS'+(self.$cssNo++));
                linb.UI.$cache_css='';
            }
            if(cache2){
                linb.CSS.addStyleSheet(cache2, 'linb.UI-CSS'+(self.$cssNo++),true);
                linb.UI.$cache_css2='';
            }
        },
        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){
                    if(j.charAt(0)=='$')continue;
                    //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('');
        },
        _droppable: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;

                    // avoid no droppable keys
                    if(profile.behavior.NoDroppableKeys){
                        var sk = profile.getKey(linb.Event.getSrc(e).id || "").split('-')[1];
                        if(sk && _.arr.indexOf(profile.behavior.NoDroppableKeys, sk)!=-1)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.beforeDrop && (false===box.beforeDrop.apply(box,args)))
                        return;

                    if(profile.onDrop && (false===box.onDrop.apply(box,args))){
                        // dont call inner _onDrop
                    }else if(profile.box._onDrop)
                        profile.box._onDrop.apply(profile.host||profile, args);

                    if(profile.afterDrop)
                        box.afterDrop.apply(box,args);
                }
            }, 'all');
            _.merge(ch,{
                onmouseover:h2,
                onmouseout:h2,
                ondrop:h2,
                afterDrop:h2,
                beforeDrop:h2
            });
            return self;
        },
        _draggable: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(linb.Event.getBtn(e)!="left")return;
                    if(profile.properties.disabled)return;
                    // not resizable or drag
                    if(!profile.properties.dragKey)return;

                    // avoid nodraggable keys
                    if(profile.behavior.NoDraggableKeys){
                        var sk = profile.getKey(linb.Event.getSrc(e).id || "").split('-')[1];
                        if(sk && _.arr.indexOf(profile.behavior.NoDraggableKeys, sk)!=-1)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 dm = profile.box.$DataModel,i,o;
            
            for(i in hashIn){
                if(i.charAt(0)=='$')continue;
                if(hashIn.hasOwnProperty(i) &&  !hashOut.hasOwnProperty(i))
                    hashOut[i] = typeof (o=hashIn[i])=='string' ? i=='html' ? o : linb.adjustRes(o,true) : o;
            }

            if('disabled' in dm)
                hashOut.disabled= (_.isSet(hashOut.disabled) && hashOut.disabled) ?'linb-ui-itemdisabled':'';
            if('readonly' in dm)
                hashOut.readonly= (_.isSet(hashOut.readonly) && hashOut.readonly) ?'linb-ui-itemreadonly':'';

            //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+';';
            else if(hashOut.image)
                hashOut.backgroundPosition='background-position:center;';

            if(hashOut.imageRepeat)
                hashOut.backgroundRepeat='background-repeat:'+hashOut.imageRepeat+';';
            else if(hashOut.image)
                hashOut.backgroundRepeat='background-repeat:no-repeat;';
            //must be here
            //Avoid Empty Image src
            if(!hashOut.image)hashOut.image=linb.ini.img_bg;
            
            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 r;
        },

        Behaviors:{
            onContextmenu:function(profile, e, src){
                if(profile.onContextmenu)
                    return profile.boxing().onContextmenu(profile, e, src)!==false;
            }
        },
        DataModel:{
            tag:'',
            tagVar:{
                ini:{}
            },
            "className":{
                ini:"",
                action:function(v,ov){
                    if(ov)
                        this.getRoot().removeClass(ov);
                    this.getRoot().addClass(v);
                }
            },
            disableClickEffect:false,
            disableHoverEffect:false,
            disableTips:false,
            disabled:{
                ini:false,
                action: function(v){
                    var i=this.getRoot();
                    if(v)
                        i.addClass('linb-ui-disabled');
                    else
                        i.removeClass('linb-ui-disabled');
                }
            },
            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){},
            afterDestroy:function(profile){},
            onShowTips:function(profile, node, pos){},
            onContextmenu:function(profile, e, node, item){}
        },
        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._$visibility=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);

                // for have _onresize widget only
                if(profile.onResize)
                    profile.boxing().onResize(profile,w,h);
            }

            //some control will set visible to recover the css class
            if('_$visibility' in profile){
                var node=profile.getRootNode(),
                    style=node.style;
                if(style.visibility!='visible' && !linb.getNodeData(node,'_setVisibility'))
                    style.visibility=profile._$visibility;
                node=style=null;
                clearTimeout(profile._$rs_timer);
                delete profile._$rs_timer;
                delete profile._$rs_args;
                delete profile._$visibility;
            }
        },
        $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;
                w=((w===""||w=='auto')?"auto":parseInt(w))||null
                h=((h===""||h=='auto')?"auto":parseInt(h))||null;

                //if it it has delay resize, overwrite arguments
                if('_$visibility' in profile){
                    var args=profile._$rs_args;
                    // asyrun once only
                    if(!args){
                        args=profile._$rs_args=[profile,null,null];
                        profile._$rs_timer=_.asyRun(function(){
                            if(profile && profile._$rs_args)
                                linb.UI.$doResize.apply(null,profile._$rs_args);
                        });
                    }
                    //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 node = profile.getRoot(),
                p=linb((node.get(0) && node.get(0).parentNode)||profile.$dockParent);
            if(!p.get(0))
                return;
            var prop = profile.properties,
                margin=prop.dockMargin,
                auto = 'auto',
                value = prop.dock || 'none',
                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 || p.get(0)===document || p.get(0)===window){
                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('$dockall');
                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;
                }
                if(node.get(0))
                    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);

                             if(!node.get(0))
                                return;

                             var 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))){
                                                delete o.node;
                                                // for no _onresize widget only
                                                if(!profile.box._onresize && profile.onResize && (o.width!==null||o.height!==null))
                                                    profile.boxing().onResize(profile,o.width,o.height);
                                                if(profile.onDock)profile.boxing().onDock(profile,o);
                                                if(profile.$onDock)profile.$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))){
                                                    delete o.node;
                                                    // for no _onresize widget only
                                                    if(!profile.box._onresize && profile.onResize && (o.width!==null||o.height!==null))
                                                        profile.boxing().onResize(profile,o.width,o.height);
                                                    if(profile.onDock)profile.boxing().onDock(profile,o);
                                                    if(profile.$onDock)profile.$onDock(profile,o);
                                                }
                                            })
                                        }
                                    });
                                }
                                // for those are not in obj.later
                                for(k=0;key=arr[k++];){
                                    target = me[key];
                                    if(target.length){
                                        for(i=0;o=target[i++];){
                                            if(!o.properties.dockIgnore){
                                                if(!obj.later || !obj.later[o.$linbid]){
                                                    if(o.onDock)o.boxing().onDock(o);
                                                    if(o.$onDock)o.$onDock(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.dockall=[];
                        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={}
                                ;
                            if(style.display=='none')
                                return;
                            //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;
                                        temp=_adjust(prop.dockMinW?Math.max(prop.dockMinW,temp):temp);
                                        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;
                                        temp=_adjust(prop.dockMinW?Math.max(prop.dockMinW,temp):temp);
                                        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;
                                        temp=_adjust(prop.dockMinH?Math.max(prop.dockMinH,temp):temp);
                                        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;
                                        temp=_adjust(prop.dockMinH?Math.max(prop.dockMinH,temp):temp);
                                        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);
                    }
                    profile.link(f.dockall, '$dockall');

                    //
                    linb.$cache._resizeTime=1;

                    //set shortuct
                    profile.$dockFun=f;

                }
                if(isWin){
                    var f=linb.win.$getEvent('onSize','dock');
                    if(f && f.dockall && f.dockall.length){
                        linb('html').addClass('linb-css-viewport');
                        if(t=linb('body').get(0))
                            t.scroll='no';
                    }else{
                        linb('html').removeClass('linb-css-viewport');
                        if(t=linb('body').get(0))
                            t.scroll='';
                    }
                }
            }

            //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 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];

            for(var i in profile.box._objectProp)
                if((i in p) && p[i] && _.isEmpty(p[i]))delete 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((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=profile.box.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('className' in dm)
            	data._className=prop.className||"";

            if('readonly' in dm)data.readonly=prop.readonly?"linb-ui-readonly":"";
            if('href' in dm)data.href = prop.href || linb.$DEFAULTHREF;
            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);
            }


            if('selectable' in dm)
                data._selectable=linb.browser.ie
                    ? (prop.selectable?"true":"false")
                    : (prop.selectable?"linb-ui-selectable":"linb-ui-unselectable");

            //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=profile.box.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(!t.host||t.host===t)t.boxing().setHost(profile.host,t.alias);
                    if(!profile.$attached)profile.$attached=[];
                    profile.$attached.push(t);
                }else{
                    dataItem._tabindex=tabindex;
                    if(item.hidden)
                        item.itemDisplay='display:none;';

                    //others
                    ajd(profile, item, dataItem);
                    if(this._prepareItem)
                        this._prepareItem(profile, dataItem, item, pid, i,l,mapCache, serialId);
                }
                result.push(dataItem);
            }

            return result;
        },
        _showTips:function(profile, node, pos){
            if(profile.properties.disableTips)return;
            if(profile.onShowTips)
                return profile.boxing().onShowTips(profile, node, pos);
            //if(!linb.Tips)return;
        }
    }
});
//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);

                    // try to render inner linb.UI
                    if(profile.$attached){
                        for(var i=0,v;v=profile.$attached[i++];)
                            if(v._render)
                                v._render(true);
                        delete profile.$attached;
                    }

                    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){
                    _.arr.insertAny(items,arr2, before?0:-1);
                }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, data, 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]){
                                    data.push(_.copy(profile.SubSerialIdMapItem[serialId]));
                                    // 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,  data, 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,data=[];
                // clear properties
                remove(profile, p.items, arr, data);
                // clear value
                if(v=p.$UIvalue){
                    if((v=(''+v).split(p.valueSeparator)).length>1){
                        _.filter(v,function(o){
                            return _.arr.indexOf(arr,o)==-1;
                        });
                        p.$UIvalue=v.join(p.valueSeparator);
                    }else{
                        if(_.arr.indexOf(arr,p.$UIvalue)!=-1)
                            p.$UIvalue=null;
                    }
                }
                if(b && profile.renderId)
                    profile.boxing()._afterRemoveItems(profile, data);
            });
        },
        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={};

                profile.properties.$UIvalue=null;
                //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),
                nid,item,serialId,arr,node,sub,t;
            if(!_.isHash(options))options={caption:options+''};

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

                // [[modify id
                if(_.isSet(options.id))options.id+="";
                if(options.id && subId!==options.id){
                    nid=options.id;
                    var m2=profile.ItemIdMapSubSerialId, v;
                    if(!m2[nid]){
                        if(v=m2[subId]){
                            m2[nid]=v;
                            delete m2[subId];
                            profile.SubSerialIdMapItem[v].id=nid;
                        }else{
                            item.id=nid;
                        }
                    }
                }
                delete options.id;
                // modify id only
                if(_.isEmpty(options))
                    return self;
                //]]

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

                //in dom already?
                node=profile.getSubNodeByItemId('ITEM',nid || subId);
                if(!node.isEmpty()){
                    //prepared already?
                    serialId=_.get(profile,['ItemIdMapSubSerialId',nid || subId]);
                    arr=box._prepareItems(profile, [item],item._pid,false, serialId);

                    //for the sub node
                    if(options.sub){
                        delete item._created;
                        delete item._checked;
                    }else if(item.sub){
                        sub=profile.getSubNodeByItemId('SUB',nid || subId);
                    }
                    node.replace(profile._buildItems(arguments[2]||'items',arr),false);
                    //keep sub
                    if(sub && !sub.isEmpty()){
                        if(!(t=profile.getSubNodeByItemId('SUB',nid || subId)).isEmpty())
                            t.replace(sub);
                    }
                    if(typeof self.setUIValue=='function'){
                        var uiv=profile.properties.$UIvalue||"", arr=(''+uiv).split(profile.properties.valueSeparator);
                        if(arr.length && _.arr.indexOf(arr, subId)!=-1){
                            if(nid)_.arr.removeValue(arr,subId);
                            self.setUIValue(arr.join(profile.properties.valueSeparator), true);
                        }
                    }
                }
            }
            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(this.constructor._focusNodeKey, 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,null,'instance');
        });
    },
    Static:{
        _focusNodeKey:'ITEM',
        $abstract:true,
        DataModel:{
            listKey:{
                set:function(value){
                    var o=this,
                        t = o.box.getCachedData(value);
                    if(t)
                        o.boxing().setItems(_.clone(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);
                }
            },
            valueSeparator:';'
        },
        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=_.isSet(a[i].id)?(a[i].id+''):_.id();
                }
            });
            return a;
        },
        //
        _showTips:function(profile, node, pos){
            if(profile.properties.disableTips)return;
            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(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(key){
          return this.each(function(profile){
                if(!profile.renderId)return;
                var properties = profile.properties,
                    flag=properties.value !== properties.$UIvalue,
                    o=profile.getSubNode(key||"KEY"),
                    d=linb.UI.$css_tag_dirty;
                if(profile._dirtyFlag!==flag){
                    if(properties.dirtyMark && properties.showDirtyMark){
                        if(profile.beforeDirtyMark && false===profile.boxing().beforeDirtyMark(profile,flag)){}
                        else{
                            if(flag) o.addClass(d);
                            else o.removeClass(d);
                        }
                    }
                    profile._dirtyFlag=flag;
                }
            });
        },
        getValue:function(returnArr){
            var prf=this.get(0),
                prop=prf.properties,
                v=prop.value;
            
            if(prf.box.$valuemode=='multi')
                if(returnArr)
                    if(_.isStr(v))
                        v=v.split(prop.valueSeparator);
            
            if(prf.box.$DataModel.selMode && (prop.selMode=='multi'||prop.selMode=='multibycheckbox') && returnArr){
                if(_.isStr(v))
                    v=v.split(prop.valueSeparator);
                v.sort();
            }
            return v;
        },
        getUIValue:function(returnArr){
            var prf=this.get(0),
                prop=prf.properties;
           
            if(!prf.renderId)
                return prop.value;

            var cv=this._getCtrlValue(),v;
            if(!prf.box._checkValid || false!==prf.box._checkValid(prf,cv))
                prop.$UIvalue=cv;
            v=prop.$UIvalue;
            
            if(prf.box.$valuemode=='multi')
                if(returnArr)
                    if(_.isStr(v))
                        v=v.split(prop.valueSeparator);

            if(prf.box.$DataModel.selMode && (prop.selMode=='multi'||prop.selMode=='multibycheckbox') && returnArr){
                if(_.isStr(v))
                    v=v.split(prop.valueSeparator);
                v.sort();
            }
            return v;
        },
        resetValue:function(value){
            var self=this;
            self.each(function(profile){
                var r,pro=profile.properties;
                if(typeof (r=profile.box._ensureValue)=='function')
                    value=r.call(profile.box, profile, value);
                if(pro.value !== value || pro.$UIvalue!==value){
                    if(profile.box._beforeResetValue)profile.box._beforeResetValue(profile);
                    if(typeof(r=profile.$onValueSet)=='function'){
                        r=r.call(profile,value);
                        if(_.isSet(r))value=r;
                    }

                    // _setCtrlValue maybe use $UIvalue
                    profile.boxing()._setCtrlValue(pro.value = value);
                    // So, maintain $UIvalue during _setCtrlValue call
                    pro.$UIvalue = 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(
                        (profile.box._checkValid && false===profile.box._checkValid(profile, value)) ||
                        (profile.beforeUIValueSet && false===(r=box.beforeUIValueSet(profile, ovalue, value)))
                      )
                        return;

                    //can get return value
                    if(r!==undefined && typeof r!=='boolean')value=r;
                    //before _setCtrlValue
                    if(typeof (r=profile.box._ensureValue)=='function')
                        value = r.call(profile.box, profile, value);
                    
                    if(typeof(r=profile.$onUIValueSet)=='function'){
                        r=r.call(profile,value);
                        if(_.isSet(r))value=r;
                    }

                    //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);
                    if(profile.onChange)box.onChange(profile, ovalue, value);

                    if(!prop.dirtyMark)
                        box.setValue(value);
                }
            });
            return this;
        },
        updateValue:function(){
            return this.each(function(profile){
                var prop = profile.properties;
                if(prop.value!==prop.$UIvalue){
                    var ins=profile.boxing();
                    if(ins.checkValid()){
                        // prop.value = ins.getUIValue();
                        ins.setValue(ins.getUIValue(),true);
                        ins._setDirtyMark();
                    }
                }
            });
        },
        isDirtied:function(){
            var dirtied=false;
            this.each(function(profile){
                var p=profile.properties;

                // inner value is alway string
                dirtied = (p.value+" ") !== (p.$UIvalue+" ");
                if(dirtied)
                    return false;
            });
            return dirtied
        },
        checkValid:function(value){
            var prop,tr,r=true,outv=_.isSet(value);
            this.each(function(profile){
                prop=profile.properties;
                tr=true;
                
                // for checking html ctrl valid, <input> only
                if(profile.box._checkValid2)
                    // r must be at the end
                    r = (tr=profile.box._checkValid2(profile)) && r;
                if(tr && profile.box._checkValid)
                    //r must be at the end
                    r = profile.box._checkValid(profile, outv?value:prop.$UIvalue) && r;

                if(!outv && 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:{
                ini:'',
                set:function(value,ovalue){
                    var profile=this,t,
                        p=profile.properties;
                    p.dataField=value;

                    if(!p.dataBinder)return;
                    // set control value 2
                    var db=linb.DataBinder.getFromName(p.dataBinder);
                    if(db && (t=db.get(0)) && (t=t.properties.data) && _.isSet(t=t[value]))
                        //p.value=t;
                        profile.boxing().setValue(t,true);
                }
            },
            readonly:{
                ini:false,
                action: function(v){
                    var i=this.getRoot();
                    if(v)
                        i.addClass('linb-ui-readonly');
                    else
                        i.removeClass('linb-ui-readonly');
                }
            },
            // 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.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=r.call(profile,nv);
                        if(_.isSet(r))nv=r;
                    }

                    //before value copy
                    if(profile.renderId)box._setCtrlValue(nv);
                    //value copy
                    p.value = p.$UIvalue = nv;

                    if(!profile._inValid)profile._inValid=1;
                    if(profile.renderId)box._setDirtyMark();
                    if(profile.afterValueSet)box.afterValueSet(profile, ovalue, nv);
                }
            },
            dirtyMark:true,
            showDirtyMark:true
        },
        _ensureValue:function(profile,value){
            if(profile.box.$DataModel.selMode && (profile.properties.selMode=='multi'||profile.properties.selMode=='multibycheckbox')){
                if(!_.isArr(value)){
                    value = (value?(''+value):'').split(profile.properties.valueSeparator);
                }
                value.sort();
                return value.join(profile.properties.valueSeparator);
            }else
                return _.isArr(value)?value[0]:value;
        },
        EventHandlers:{
           //real value set
            beforeValueSet:function(profile, oldValue, newValue){},
            afterValueSet:function(profile, oldValue, newValue){},

            //ui value set
            beforeUIValueSet:function(profile, oldValue, newValue){},
            afterUIValueSet:function(profile, oldValue, newValue){},
            onChange:function(profile, oldValue, newValue){},

            beforeDirtyMark:function(profile, dirty){}
        },
        RenderTrigger:function(){
            var self=this, b=self.boxing(),p=self.properties,t;

            if(t=p.dataBinder)b.setDataBinder(t,true);
            if(t=p.dataField)b.setDataField(t);

            if(p.value!==undefined){
                if(typeof (t=self.box._ensureValue)=='function'){
                    p.value = t.call(self.box, self, p.value);
                    if(p.$UIvalue)
                        p.$UIvalue = t.call(self.box, self, p.$UIvalue);
                }
                if(!p.$UIvalue)
                    p.$UIvalue=p.value;
                b._setCtrlValue(p.$UIvalue);
            }            
        }
    }
});

//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:'linb-uiw-shell {_className}',
                style:'{_style}',
                FRAME:{
                    className:'linb-uiw-frame ',
                    BORDER:{
                        style:'width:{bWidth}px;height:{bHeight}px;',
                        className:'linb-uiw-border'
                    }
                }
            },
            Behaviors:{
                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,
                   cursor:'pointer'
                }
            },
            Templates:{
                tagName:'a',
                className:'{_className}',
                style:'{_style}',
                href :"{href}",
                target:'{target}',
                tabindex: '{tabindex}',
                text:'{caption}'
            },
            Behaviors:{
                HoverEffected:{KEY:'KEY'},
                ClickEffected:{KEY:'KEY'},
                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){
                        v=(_.isSet(v)?v:"")+"";
                        this.getRoot().html(linb.adjustRes(v,true));
                    }
                },
                href:{
                    ini:linb.$DEFAULTHREF,
                    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:{
                className:'{_className}',
                style:'{_style};text-align:{hAlign}',
                text:'{caption}'
            },
            Appearances:{
                KEY:{
                   'padding-right':'6px'
                }
            },
            DataModel:{
                selectable:true,
                caption:{
                    ini:undefined,
                    action: function(v){
                        v=(_.isSet(v)?v:"")+"";
                        this.getRoot().html(linb.adjustRes(v,true));
                    }
                },
                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} {_className}',
                style:'{_style}',
                BTN:{
                    className:'linb-ui-btn',
                    BTNI:{
                        className:'linb-ui-btni',
                        BTNC:{
                            className:'linb-ui-btnc',
                            FOCUS:{
                                tabindex: '{tabindex}',
                                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:'pointer',
                    'font-size':'12px',
                    '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);
                },
                onKeydown:function(profile, e, src){
                    var keys=linb.Event.getKey(e), key = keys.key;
                    if(key==' '||key=='enter'){
                        profile.getSubNode('BTN').afterMousedown();
                        profile.__fakeclick=1;
                    }
                },
                onKeyup:function(profile, e, src){
                    var keys=linb.Event.getKey(e), key = keys.key;
                    if(key==' '||key=='enter'){
                        profile.getSubNode('BTN').afterMouseup();
                        if(profile.__fakeclick)
                            linb.use(src).onClick();
                    }
                    delete profile.__fakeclick;
                }
            },
            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(v){
                        v=(_.isSet(v)?v:"")+"";
                        this.getSubNode('FOCUS').html(linb.adjustRes(v,true));
                    }
                },
                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 arguments.callee.upper.apply(this,['CAPTION']);
            }
        },
        Static:{
            Templates:{
                className:'{_clsName} {_className}',
                style:'{_style}',
                FOCUS:{
                    tabindex: '{tabindex}',
                    MARK:{
                        className:'linb-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':'22px'
                },
                CAPTION:{
                    'vertical-align':linb.browser.ie6?'baseline':'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;
                    if(p.readonly)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).key;
                        if(key ==' ' || key=='enter'){
                            profile.getRoot().onClick(true);
                            return false;
                        }
                    }
                }
            },
            DataModel:{
                value:false,
                caption:{
                    ini:undefined,
                    action: function(v){
                        v=(_.isSet(v)?v:"")+"";
                        this.getSubNode('CAPTION').html(linb.adjustRes(v,true));
                    }
                }
            },
            EventHandlers:{
                onChecked:function(profile, e, value){}
            },
            _ensureValue:function(profile, value){
                return !!value;
            }
        }
    });
    Class(u+".Span", u,{
        Static:{
            Templates:{
                className:'{_className}',
                style:'{_style};{_overflow};',
                //for firefox div focus bug: outline:none; tabindex:'-1'
                tabindex:'-1',
                text:'{html}'+linb.UI.$childTag
            },
            DataModel:{
                width:'16',
                height:'16',
                selectable:true,
                html:{
                    action:function(v){
                        this.getRoot().html(v);
                    }
                },
                overflow:{
                    ini:undefined,
                    action:function(v){
                        this.getContainer().css('overflow',v||'');
                    }
                }
            },
            _prepareData:function(profile){
                var data=arguments.callee.upper.call(this, profile);
                if(_.isStr(data.overflow))
                    data._overflow = data.overflow.indexOf(':')!=-1?(data.overflow):("overflow:"+data.overflow);
                return data;
            }
        }
    });

    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.ie && linb.browser.ver<9)?'1':null,
                    background:linb.browser.ie?'url('+linb.ini.img_bg+') no-repeat left top':null
                }
            },
            Templates:{
                tagName:'div',
                className:'{_className}',
                style:'{_style};{_overflow};',
                //for firefox div focus bug: outline:none; tabindex:'-1'
                tabindex:'-1',
                text:'{html}'+linb.UI.$childTag
            },
            DataModel:{
                iframeAutoLoad:"",
                ajaxAutoLoad:"",
                width:'100',
                height:'100',
                selectable:true,
                html:{
                    action:function(v){
                        this.getRoot().html(v);
                    }
                },
                overflow:{
                    ini:undefined,
                    action:function(v){
                        this.getContainer().css('overflow',v||'');
                    }
                }
            },
            RenderTrigger:function(){
                // only div
                var ns=this;
                if(ns.box.KEY=="linb.UI.Div")
                    if(ns.properties.iframeAutoLoad||ns.properties.ajaxAutoLoad)
                        ns.box._applyAutoLoad(this);
            },
            _prepareData:function(profile){
                var data=arguments.callee.upper.call(this, profile);
                if(_.isStr(data.overflow))
                    data._overflow = data.overflow.indexOf(':')!=-1?(data.overflow):("overflow:"+data.overflow);
                return data;
            },
            _applyAutoLoad:function(prf){
                var prop=prf.properties, ins=prf.boxing();
                if(prop.iframeAutoLoad){
                    ins.getContainer().css('overflow','hidden');
                    if(typeof prop.iframeAutoLoad=='string')
                        prop.iframeAutoLoad={url:prop.iframeAutoLoad};
                    var hash=prop.iframeAutoLoad,
                        id="biframe_"+_(),
                        e=linb.browser.ie && parseInt(linb.browser.ver)<9,
                        ifr=document.createElement(e?"<iframe name='"+id+"'>":"iframe");
                    if(!hash.query)hash.query={};
                    hash.query._rand=_();
                    prop.iframeAutoLoad.frameName=ifr.id=ifr.name=id;
                    ifr.src=hash.url;
                    ifr.frameBorder='0';
                    ifr.marginWidth='0';
                    ifr.marginHeight='0';
                    ifr.vspace='0';
                    ifr.hspace='0';
                    ifr.allowTransparency='true';
                    ifr.width='100%';
                    ifr.height='100%';
                    ins.append(ifr);
                    linb.Dom.submit(hash.url, hash.query, hash.method, id, hash.enctype);
                }else if(prop.ajaxAutoLoad){
                    if(typeof prop.ajaxAutoLoad=='string')
                        prop.ajaxAutoLoad={url:prop.ajaxAutoLoad};
                    var hash=prop.ajaxAutoLoad,options={rspType:"text"};
                    if(!hash.query)hash.query={};
                    hash.query._rand=_();
                    _.merge(options, hash.options);
                    ins.busy();
                    linb.Ajax(hash.url, hash.query, function(rsp){
                        var n=linb.create("div");
                        n.html(rsp,false,true);
                        ins.append(n.children());
                        ins.free();
                    }, function(err){
                        ins.append("<div>"+err+"</div>");
                        ins.free();
                    }, null, options).start();
                }
            }
        }
    });
    Class(u+".Tag", u+".Div",{
        Static:{
            Templates:{
                tagName:'div',
                className:'{_className}',
                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(typeof tagProfile.theme =="string")
                    profile.theme=tagProfile.theme;

                //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:{
                DroppableKeys:['KEY'],
                PanelKeys:['KEY']
            },
            RenderTrigger:function(){
                // only div
                var ns=this;
                if(ns.box.KEY=="linb.UI.Pane")
                    if(ns.properties.iframeAutoLoad||ns.properties.ajaxAutoLoad)
                        ns.box._applyAutoLoad(this);
            }
        }
    });
};Class("linb.UI.Image", "linb.UI",{
    Instance:{
        getRate:function(){
            return parseFloat(this.get(0)._rate) || 1;
        }
    },
    Static:{
        Templates:{
            tagName:'image',
            style:'cursor:{cursor};{_style}',
            className:'{_className}',
            border:"0",
            src:linb.ini.img_bg,
            alt:"{alt}"
        },
        Behaviors:{
            HoverEffected:{KEY:'KEY'},
            ClickEffected:{KEY:'KEY'},
            DraggableKeys:["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,prop=profile.properties;
                    size=profile.box._adjust(profile, _.isFinite(prop.width)?prop.width:i.width,_.isFinite(prop.height)?prop.height:i.height);
                profile.boxing().afterLoad(profile, path, size[0], size[1]);
                if(prop.dock!='none')
                    profile.boxing().adjustDock();
            },
            onClick:function(profile, e, src){
                var p=profile.properties;
                if(p.disabled)return false;
                if(profile.onClick)
                    profile.boxing().onClick(profile, e, src);
            },
            onDblclick:function(profile, e, src){
                var p=profile.properties;
                if(p.disabled)return false;
                if(profile.onDblclick)
                    profile.boxing().onDblclick(profile, e, src);
            }
        },
        RenderTrigger:function(){
            var self=this, pro=self.properties, v=pro.src;
            if(v){
                pro.value=pro.$UIvalue='';
                self.boxing().setSrc(v, v!=linb.ini.img_bg);
            }
        },
        EventHandlers:{
            onClick:function(profile, e, src){},
            onDblclick:function(profile, e, src){},
            onError:function(profile){},
            beforeLoad:function(profile){},
            afterLoad:function(profile, path, width, height){}
        },
        _adjust:function(profile,width,height){
            var pro=profile.properties,
                src=profile.getRootNode();
            width=parseInt(width)||0;
            height=parseInt(height)||0;
            src.style.width=src.style.height='';
            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;
                return [src.width=width*r, src.height=height*r];
            }
            return [0,0];
        },
        DataModel:{
            maxWidth:{
                ini:800,
                action:function(v){
                    var src=this.getRootNode(),prop=this.properties;
                    this.box._adjust(this,_.isFinite(prop.width)?prop.width:src.width,_.isFinite(prop.height)?prop.height:src.height);
                }
            },
            maxHeight:{
                ini:600,
                action:function(v){
                    var src=this.getRootNode(),prop=this.properties;
                    this.box._adjust(this,_.isFinite(prop.width)?prop.width:src.width,_.isFinite(prop.height)?prop.height:src.height);
                }
            },
            width:{
                ini:'auto',
                action:function(v){
                    var src=this.getRootNode(),
                        prop=this.properties,
                        i=new Image();
                    i.src=src.src;
                    this.box._adjust(this, _.isFinite(v)?parseInt(v):i.width, _.isFinite(prop.height)?prop.height:i.height);
                }
            },
            height:{
                ini:'auto',
                action:function(v){
                    var src=this.getRootNode(),
                        prop=this.properties,
                        i=new Image();
                    i.src=src.src;
                    this.box._adjust(this,_.isFinite(prop.width)?prop.width:i.width,_.isFinite(v)?parseInt(v):i.height);
                }
            },
            src:{
                ini:linb.ini.img_bg,
                //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:linb.adjustRes(v)})});
                }
            },
            alt:{
                ini:"",
                action:function(v){
                    this.getRoot().attr('alt',v);
                }
            },
            cursor:{
                ini:"default",
                action:function(v){
                    this.getRoot().css('cursor',v);
                }
            }
        }
    }
});Class("linb.UI.Flash", "linb.UI",{
    Instance:{
        refreshFlash:function(){
            var html='', cls=this.constructor;
            return this.each(function(profile){
                _.resetRun(profile.domId,function(){
                    // clear first
                    cls._clearMemory(profile);
    
                    // build and set flash
                    if(profile.properties.src)
                        cls._drawSWF(profile);
                });
            });
        },
        // Return the flash object
        getFlash:function(){
            return this.constructor._getSWF(this.get(0));
        }
    },
    Static:{
        Appearances:{
            KEY:{
                'font-size':linb.browser.ie?0:null,
                'line-height':linb.browser.ie?0:null,
                overflow:'hidden'
            },
            BOX:{
                position:'absolute',
                left:0,
                top:0,
                'z-index':1
            },
            COVER:{
                position:'absolute',
                left:'-1px',
                top:'-1px',
                width:0,
                height:0,
                'z-index':4
            }
        },
        Templates:{
            tagName:'div',
            className:'{_className}',
            style:'{_style}',
            BOX:{
                tagName:'div'
            },
            COVER:{
                tagName:'div'
            }
        },
        Behaviors:{
            onSize:linb.UI.$onSize
        },
        DataModel:{
            selectable:true,
            width:500,
            height:300,
            cover:false,
            src:{
                ini:'',
                action:function(v,o){
                    this.boxing().refreshFlash();
                }
            },
            parameters:{
                ini:{},
                action:function(v,o){
                    this.boxing().refreshFlash();
                }
            },
            flashvars:{
                ini:{},
                action:function(v,o){
                    this.boxing().refreshFlash();
                }
            }
        },
        RenderTrigger:function(){
            this.$beforeDestroy=function(){
                if(this.box)
                    this.box._clearMemory(this);
            }
            // add swf
            this.boxing().refreshFlash();
        },
        getFlashVersion:function(){
          if(linb.browser.ie){
            try {
              var axo = new ActiveXObject('ShockwaveFlash.ShockwaveFlash.6');
              try{axo.AllowScriptAccess='always'}catch(e){return '6,0,0'}
            }catch(e){}finally{
                try{
                    return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable('$version').replace(/\D+/g, ',').match(/^,?(.+),?$/)[1];
                }catch(e){}
            }
          }else{
            try {
              if(navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin){
                return (navigator.plugins["Shockwave Flash 2.0"] || navigator.plugins["Shockwave Flash"]).description.replace(/\D+/g, ",").match(/^,?(.+),?$/)[1];
              }
            }catch(e){}
          }
          return '0,0,0';
        },
        _getSWF:function(profile){
            var id= _.isStr(profile)?profile:(this._idtag + profile.serialId);
            return (linb.browser.ie ? window[id] : ((document.embeds && document.embeds[id])||window.document[id])) || document.getElementById(id);
        }, 
        _clearMemory:function(profile){
            var id=this._idtag + profile.serialId;
            var _e=_.fun(), chart = profile.box._getSWF(profile);
            if(chart){
                chart.style.display = 'none';
                if(linb.browser.ie){
                    for(var x in chart )
                        if(typeof chart[x]=='function')
                            chart[x]=_e;                        
                    if(window[id])
                        window[id]=undefined;
                }else{
                    if(document.embeds && document.embeds[id])
                        document.embeds[id]=undefined;
                    if(window.document[id])
                        window.document[id]=undefined;
                }
               chart=_e=null;
            }
        }, 
        _drawSWF:function(profile){
            var ns=this;
            var prop=profile.properties,
                serialId=profile.serialId,
                src=prop.src,
                parameters=prop.parameters,
                options = _.copy(prop.flashvars),
                xml="";

            options.DOMId = profile.box._idtag + profile.serialId;
            options.chartWidth=prop.width;
            options.chartHeight=prop.height;

            if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){
                xml += '<embed type="application/x-shockwave-flash" src="'+ src +'?'+_.urlEncode(parameters)+'" ';
                xml += 'width="'+prop.width+'" height="'+prop.height+'" ';
                xml += 'id="'+ options.DOMId +'" name="'+ options.DOMId +'" ';
                xml += 'wmode="opaque" ';
                xml += 'flashvars="'+ _.urlEncode(options) +'" ';
                xml +=  '/>';
            }else{
                xml += '<object id="'+ options.DOMId +'" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" '
                xml += 'width="'+prop.width+'" height="'+prop.height+'">';
                xml += '<param name="movie" value="'+ src +'?'+_.urlEncode(parameters)+'" />';
                xml += '<param name="wmode" value="opaque" />';
                xml += '<param name="flashvars" value="'+ _.urlEncode(options) +'" />';
                xml += '</object>';
            }
            profile.getSubNode('BOX').html(xml, false);
        },
        _onresize:function(profile,width,height){
            var size = profile.getSubNode('BOX').cssSize(),prop=profile.properties;
            if( (width && size.width!=width) || (height && size.height!=height) ){
                // reset here
                if(width)prop.width=width;
                if(height)prop.height=height;

                size={width:width,height:height};
                profile.getSubNode('BOX').cssSize(size,true);
                if(profile.$inDesign || prop.cover){
                    profile.getSubNode('COVER').cssSize(size,true);
                }
                profile.boxing().refreshFlash();
            }
        }
    }
});//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:linb.browser.ie6?'inline':null,
                '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(o && o.renderId && o._target)
                        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:linb.browser.ie6?'inline':null,
               'font-size':linb.browser.ie6?0:null,
               'line-height':linb.browser.ie6?0:null
            },
            'B, RB, R':{
                position:'absolute',
                display:'block',
                'font-size':linb.browser.ie?0:null,
                'line-height':linb.browser.ie?0:null,
                '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','');
            });
            if(linb.browser.ie)
                self.reBoxing().ieRemedy();
            return self;
        },
        hide:function(){
            var self=this;
            self.reBoxing().css('display','none');
            return self;
        }
    },
    Initialize:function(){
        this.addTemplateKeys(['HANDLER','HIDDEN','MOVE','CONF','L','R','T','B','LT','RT','LB','RB']);
        _.each({
            // add resizer to linb.Dom plugin
            addResizer:function(properties, onUpdate, onChange){
                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);
                if(onChange) r.onChange(onChange);
                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(),
                            instance=profile.boxing(),
                            prop=profile.properties,
                            t
                        ;
                        if(size){
                            var w=null,h=null,l=null,t=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);

                            // for no _onresize widget only
                            if(!profile.box._onresize && profile.onResize && (w!==null||h!==null))
                                instance.onResize(profile,w,h);
                        }
                        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();
                            }
                            if(profile.onMove && (l!==null||t!==null))
                                instance.onMove(profile,l,t,null,null);
                        }
                        return false;
                    };
                    update.profile = o;

                    o.$resizer = target.addResizer(args, update);

                    o.$resizer.get(0).$parentUIProfile=o;
                    
                    // hide resizer
                    if(d.visibility=='hidden'){
                        o.$resizer.hide();
                    }
                });
            },
            _unResizer:function(){
                return this.each(function(o){
                    var target = o.getSubNode('BORDER');
                    if(!target.$getResizer())return;
                    target.removeResizer();
                    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
            },
            CONF:{
                position:'absolute',
                display:'block',
                'z-index':100,
                visibility: 'visible',
                background: linb.UI.$bg('icons.gif', 'no-repeat -90px -272px', true),
                'font-size':0,
                'line-height':0,
                cursor:'pointer'
            },
            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} );
            },
            onDblclick:function(profile, e, src){
                if(profile.onDblclick)profile.boxing().onDblclick(profile, e, src);
            },
            CONF:{
                onMousedown:function(profile, e, src){
                    return false;
                },
                onClick:function(profile,e,src){
                    if(profile.onConfig)
                        profile.boxing().onConfig(profile,e,src);
                }
            },
            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:'',

            // 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,
            configBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('CONF').css('display',v?'':'none');
                }
            },
//>>

            left: 100,
            top: 100,
            height: 100,
            width: 100,
            position:'absolute',
            display:'block'
        },
        EventHandlers:{
            onDblclick:function(profile, e, src){},
            onUpdate:function(profile, target, size, cssPos){},
            onChange:function(profile, proxy){},
            onConfig:function(profile, e, src){}
        },
        _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;'},
                CONF:{tagName:'div', style:'top:0;left:auto;right:-14px;width:12px;height:12px;{_showCofigBtn};'},
                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;

                template.CONF = map.CONF;

                // 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(typeof t.forceMovable=="boolean")
                t._move=t.forceMovable;

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

            t._showCofigBtn=t.configBtn?'':'display:none';
            return arguments.callee.upper.call(this, profile);
        },
        RenderTrigger:function(){
            var self=this;
            linb.setNodeData(self.renderId,'zIndexIgnore',1)
        },
        _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){
            if(linb.Event.getBtn(e)!="left")return;
            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:2,
                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);
                if(profile.onChange)profile.boxing().onChange(profile,profile.proxy);
            }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(profile.onChange)profile.boxing().onChange(profile,profile.proxy);
            }
            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);
                if(profile.onChange)profile.boxing().onChange(profile,profile.proxy);
            }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(profile.onChange)profile.boxing().onChange(profile,profile.proxy);
            }
            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);
                if(profile.onChange)profile.boxing().onChange(profile,profile.proxy);
            }
        },
        _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};
            }
            if(profile.onUpdate && false===profile.boxing().onUpdate(profile, profile._target, size, pos)){}
            else{
                profile.box._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:'linb-uiw-border {clsBorderType1}',
            PANEL:{
                tagName:'div',
                className:'{clsBorderType2} linb-uibg-bar',
                style:'{background};{_overflow};',
                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:{
            DroppableKeys:['PANEL'],
            PanelKeys:['PANEL']
        },
        DataModel:{
            //delete those properties
            disabled:null,
            tips:null,
            iframeAutoLoad:"",
            ajaxAutoLoad:"",
            selectable:true,
            html:{
                action:function(v){
                    this.getSubNode('PANEL').html(v);
                }
            },
            overflow:{
                ini:undefined,
                action:function(v){
                    this.getSubNode('PANEL').css('overflow',v||'');
                }
            },
            borderType:{
                ini:'outset',
                listbox:['none','flat','inset','outset','groove','ridge'],
                action:function(v){
                    var ns=this,
                        p=ns.properties,
                        n1=ns.getSubNode('BORDER'), n2=ns.getSubNode('PANEL'),
                        reg=/^uiborder-/,
                        flat='linb-uiborder-flat',
                        ins='linb-uiborder-inset',
                        outs='linb-uiborder-outset',
                        root=ns.getRoot();
                    n1.removeClass(reg);
                    n2.removeClass(reg);
                    switch(v){
                        case 'flat':
                        n1.addClass(flat);
                        break;
                        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
        },
        RenderTrigger:function(){
            // only div
            var ns=this;
            if(ns.box.KEY=="linb.UI.Block")
                if(ns.properties.iframeAutoLoad||ns.properties.ajaxAutoLoad)
                    linb.UI.Div._applyAutoLoad(this);
        },
        _setB:function(profile){
            var p=profile.properties,type=p.borderType;
            p.$hborder=p.$vborder=p.$iborder=0;
            if(type=='flat'||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:'';
            if(_.isStr(data.overflow))
                data._overflow = data.overflow.indexOf(':')!=-1?(data.overflow):("overflow:"+data.overflow);
            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:'linb-ui-icon {imageClass}',
                    style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {imageDisplay}'
                },
                SCAPTION:{
                    text : '{caption}',
                    style:'color:#cdcdcd;',
                    $order:1
                }
            },
            BOX:{
                $order:2,
                ICON:{
                    $order:0,
                    className:'linb-ui-icon {imageClass}',
                    style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {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:{
            selectable:true,
            // setCaption and getCaption
            caption:{
                ini:undefined,
                // ui update function when setCaption
                action: function(v){
                    var self=this,p=self.properties,b=self.boxing(),k=self.keys;
                    v=(_.isSet(v)?v:"")+"";
                    self.getSubNodes(['CAPTION','SCAPTION']).html(linb.adjustRes(v,true));
                    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);
                }
            });
        },
        _setDirtyMark:function(){
            return arguments.callee.upper.apply(this,['FOCUS']);
        },
        resetValue:function(value){
            this.each(function(p){
                if(p.properties.type=='drop')
                    p.boxing().setCaption("",true);
            });
            return arguments.callee.upper.apply(this,arguments);
        },
        setUIValue:function(value, force){
            this.each(function(profile){
                var p=profile.properties;
                if(p.$UIvalue!==value && p.type=='drop')
                    profile.boxing().setCaption("",true);
            });
            return arguments.callee.upper.apply(this,arguments);
        }
    },
    Initialize:function(){
        this.addTemplateKeys(['DROP']);
        //modify default template for shell
        var t = this.getTemplate();
        _.merge(t.FRAME,{
            FOCUS:{
                $order:2,
                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:'linb-ui-icon {imageClass}',
                                    style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {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',
                'outline-offset':'-1px',
                '-moz-outline-offset':(linb.browser.gek && parseInt(linb.browser.ver)<3)?'-1px !important':null
            },
            /*span*/
            BOX:{
                display:'inline',
                'white-space':'nowrap'
            },
            CAPTION:{
                cursor:'pointer',
                'vertical-align':linb.browser.ie6?'baseline':'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'){
                    if(p.readonly)return false;
                    
                    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);

            },
            onKeydown:function(profile, e, src){
                var keys=linb.Event.getKey(e), key = keys.key;
                if(key==' '||key=='enter'){
                    profile.getSubNode('KEY').afterMousedown();
                    profile.__fakeclick=1;
                }
            },
            onKeyup:function(profile, e, src){
                var keys=linb.Event.getKey(e), key = keys.key;
                if(key==' '||key=='enter'){
                    profile.getSubNode('KEY').afterMouseup();
                    if(profile.__fakeclick)
                        linb.use(src).onClick();
                }
                delete profile.__fakeclick;
            },
            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(v){
                    v=(_.isSet(v)?v:"")+"";
                    this.getSubNode('CAPTION').html(linb.adjustRes(v,true));
                }
            },
            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);
                }
            },
            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){
            if(profile.properties.type=="status")
                return !!value;
            else
                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 arguments.callee.upper.apply(this,['CAPTION']);
        }
    },
    Initialize:function(){
        //modify default template for shell
        var t = this.getTemplate();
        _.merge(t.FRAME.FOCUS.TB.TR.TD.BOX,{
            MARK:{
                $order:0,
                className:'linb-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%',
                'outline-offset':'-1px',
                '-moz-outline-offset':(linb.browser.gek && parseInt(linb.browser.ver)<3)?'-1px !important':null
            },
            /*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':linb.browser.ie6?'baseline':'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 || p.readonly)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).key;
                    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 arguments.callee.upper.apply(this,['BOX']);
        }
    },
    Static:{
        Templates:{
            style:'{_style}',
            className:'{_className}',
            BOX:{
                tagName:'div',
                className:'{_cls}',
                BG:{
                    tagName:'div'
                },
                RULER:{
                    $order:1,
                    tagName:'div',
                    RULERLEFT:{},
                    RULERRIGHT:{}
                },
                IND:{
                    $order:2,
                    IND1:{
                        style:'{_showD}',
                        tabindex:'{tabindex}'
                    },
                    IND2:{
                        style:'{_showD2}',
                        tabindex:'{tabindex}'
                    }
                },
                DECREASE:{
                    style:'{_showDes}',
                    tabindex:'{tabindex}'
                },
                INCREASE:{
                    style:'{_showIns}',
                    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,
                cursor:'e-resize',
                '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,
                cursor:'n-resize',
                '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;
                    if(p.disabled || p.readonly)return;
                    var 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;
                    if(p.disabled || p.readonly)return;
                    var type=p.type=='vertical',
                        key=linb.Event.getKey(e).key;
                    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){
                    if(linb.Event.getBtn(e)!="left")return;
                    var p=profile.properties;
                    if(p.disabled || p.readonly)return;
                    var 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;
                    if(p.disabled || p.readonly)return;
                    var type=p.type=='vertical',
                        key=linb.Event.getKey(e).key;
                    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){
                    if(linb.Event.getBtn(e)!="left")return;
                    var p=profile.properties;
                    if(p.disabled || p.readonly)return;
                    var 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;
                    if(p.disabled || p.readonly)return;
                    var 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){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    profile.box._auto(profile, false);
                },
                onMouseout:function(profile){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMouseup:function(profile){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    linb.Thread.abort(profile.$linbid+':auto');
                }
            },
            INCREASE:{
                onMousedown:function(profile){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    profile.box._auto(profile, true);
                },
                onMouseout:function(profile){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMouseup:function(profile){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    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 p.isRange?b.join(':'):(b[0]+'');
        },
        _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;
            var ot=profile.tips;
            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.Span'||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');
                }
            }
            if(ot!==profile.tips && linb.Tips && linb.Tips.getTips())linb.Tips.setTips(profile.tips);
        },
        activate:function(){
            var profile = this.get(0);
            if(profile.renderId){
                var node=profile.getSubNode('INPUT').get(0);
                if(node){
                    try{
                        node.focus();
                        if(!node.readOnly && node.select)node.select();
                    }catch(e){}
                }
            }
            return this;
        },
        _setCtrlValue:function(value){
            if(_.isNull(value) || !_.isDefined(value))value='';
            return this.each(function(profile){
                profile.getSubNode('INPUT').attr('value',value+"");
            });
        },
        _getCtrlValue:function(){
            var node=this.getSubNode('INPUT');
            return (node&&!node.isEmpty()) ? this.getSubNode('INPUT').attr('value') : null;
        },
        _setDirtyMark:function(){
            return this.each(function(profile){
                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;
                var ot=profile.tips;
                if(profile._inValid==2){
                    //display tips
                    profile.tips = properties.tipsErr || properties.tips;
                }else{
                    if(profile._inValid==1)
                        profile.tips = properties.tips;
                    else{
                        profile.tips = properties.tipsOK || properties.tips;
                    }
                }
                if(ot!==profile.tips && linb.Tips && linb.Tips.getTips())linb.Tips.setTips(profile.tips);
                
                if(profile._dirtyFlag!==flag){
                    if(properties.dirtyMark && properties.showDirtyMark){
                        if(profile.beforeDirtyMark && false===box.beforeDirtyMark(profile,flag)){}
                        else{
                            if(profile._dirtyFlag=flag) o.addClass(d);
                            else o.removeClass(d);
                        }
                    }
                    profile._dirtyFlag=flag
                }
                
                //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');
                    }
                }
                box._setTB(profile._inValid);
            });
        }
    },
    Initialize:function(){
        //modify default template fro shell
        var t = this.getTemplate();
        _.merge(t.FRAME.BORDER,{
            style:'',
            LABEL:{
                style:'{labelShow};width:{labelSize}px;{labelHAlign}',
                text:'{labelCaption}'
            },
            BOX:{
                WRAP:{
                    tagName : 'div',
                    INPUT:{
                        tagName : 'input',
                        type : '{_type}',
                        maxlength:'{maxlength}',
                        tabindex:'{tabindex}',
                        style:'{_css};{hAlign};'
                    }
                }
            }
        },'all');
        t.FRAME.ERROR = {};
        this.setTemplate(t)
    },
    Static:{
        _maskMap:{
            '~':'[+-]',
    		'1':'[0-9]',
    		'a':'[A-Za-z]',
    		'u':'[A-Z]',
    		'l':'[a-z]',
    		'*':'[A-Za-z0-9]'
        },
        _maskSpace:'_',
        Appearances:{
            KEY:{
                'font-family': '"Verdana", "Helvetica", "sans-serif"',
                position:'relative'
            },
            BORDER:{
                'line-height':'0px',
                'font-size':'0px'
            },
            LABEL:{
               'z-index':1,
               top:0,
               left:0,
               position:'absolute',
               'padding-top':'4px',
               'font-size':'12px'
            },
            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:linb.UI.$bg('inputbg.gif', '#fff repeat-x',"Input"),
                'border':'solid 1px #B5B8C8',
                'z-index':10
            },
            "KEY-readonly input":{
                $order:2,
                color:'#909090',
                cursor:'pointer'
            },
            "KEY-readonly BOX, KEY-inputreadonly BOX":{
                $order:2,
                background:'#eee'
            },
            'BOX-focus, BOX-mouseover':{
                'border-color':'#7EADD9'
            },
            INPUT:{
               //don't change it in custom class or style
               'padding-top':'2px',
               'padding-left':'2px',
               'padding-right':'2px',

               "background-color":"transparent",
               "background-image":linb.browser.ie?'url(.)':null,
               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:'9px',
                height:'9px',
                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},
            LABEL:{
                onClick:function(profile, e, src){
                    if(profile.properties.disabled)return false;
                    if(profile.onLabelClick)
                        profile.boxing().onLabelClick(profile, e, src);
                },
                onDblClick:function(profile, e, src){
                    if(profile.properties.disabled)return false;
                    if(profile.onLabelDblClick)
                        profile.boxing().onLabelDblClick(profile, e, src);
                },
                onMousedown:function(profile, e, src){
                    if(linb.Event.getBtn(e)!='left')return;
                    if(profile.properties.disabled)return false;
                     if(profile.onLabelActive)
                        profile.boxing().onLabelActive(profile, e, src);
                }
            },
            INPUT:{
                onChange:function(profile, e, src){
                    var p=profile.properties,b=profile.box,
                        o=profile._inValid,
                        value=linb.use(src).get(0).value;
                    // trigger events
                    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);
                    if(p.disabled || p.readonly)return;

                    //fire onchange first
                    if(k.key=='enter'&& (!m||k.altKey))
                        linb.use(src).onChange();

                    b._asyCheck(profile);

                    if(p.mask){
                        if(k.key.length>1)profile.$ignore=true;
                        else delete profile.$ignore;
                        switch(k.key){
                            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,
                    k=linb.Event.getKey(e),t,
                    caret=linb.use(src).caret();
                    
                    if(profile.beforeKeypress && false===profile.boxing().beforeKeypress(profile,caret, k,e,src))
                        return false;
                    t=profile.CF.beforeKeypress||profile.$beforeKeypress;
                    if(t && false===t(profile,caret,k,e,src))
                        return false;

                    b._asyCheck(profile);

                    if(p.mask){
                        if(profile.$ignore){
                            delete profile.$ignore;
                            return true;
                        }
                        if(k.ctrlKey||k.altKey)return true;

                        cls._changeMask(profile,linb.use(src).get(0),k.key,true);
                        return false;
                    }
                },
                onKeyup:function(profile, e, src){
                    var p=profile.properties,b=profile.box;
                    // must be key up event
                    if(linb.Event.getKey(e).key=='esc'){
                        profile.boxing().setUIValue(p.value,true);
                        if(profile.onCancel)
                            profile.boxing().onCancel(profile);
                    }

                    if(p.dynCheck){
                        var value=linb.use(src).get(0).value;
                        profile.box._checkValid(profile, 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 || p.readonly)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:{
            selectable:true,
            _customBorder:'BOX',
            border:false,

            tipsErr:'',
            tipsOK:'',

            dynCheck:false,

            labelSize:{
                ini:0,
                action: function(v){
                    this.getSubNode('LABEL').css({display:v?'':'none',width:(v||0)+"px"});
                    linb.UI.$doResize(this,this.properties.width,this.properties.height,true);
                }
            },
            labelPos:{
                ini:"left",
                listbox:['left','top', 'right', 'bottom'],
                action: function(v){
                    linb.UI.$doResize(this,this.properties.width,this.properties.height,true);
                }                
            },
            labelGap:{
                ini:4,
                action: function(v){
                    linb.UI.$doResize(this,this.properties.width,this.properties.height,true);
                }
            },
            labelCaption:{
                ini:undefined,
                action: function(v){
                    v=(_.isSet(v)?v:"")+"";
                    this.getSubNode('LABEL').html(linb.adjustRes(v,true));
                }
            },
            labelHAlign:{
                ini:'right',
                listbox:['','left','center','right'],
                action: function(v){
                    this.getSubNode('LABEL').css('textAlign',v);
                }
            },

            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);
                        var uiv=ns.properties.$UIvalue;
                        uiv=_.isSet(uiv)?(uiv+""):"";
                        //visibility mask string
                        ns.boxing()._setCtrlValue(uiv + ns.$Mask.slice(uiv.length));
                   }else{
                        delete ns.$MaskFormat;
                        delete ns.$Mask;
                   }
                }
            },
            value:'',
            width:120,
            height:22,
            disabled:{
                ini:false,
                action: function(v){
                    var i=this.getSubNode('INPUT');
                    if(v)
                        i.addClass('linb-ui-inputdisabled');
                    else
                        i.removeClass('linb-ui-inputdisabled');
                    if((""+i.get(0).type).toLowerCase()!='button')
                        // use readonly for selection
                        i.attr('readonly'/*'disabled'*/,v);
                }
            },
            hAlign:{
                ini:'',
                listbox:['','left','center','right'],
                action: function(v){
                    this.getSubNode("INPUT").css('textAlign',v);
                }
            },
            readonly:{
                ini:false,
                action: function(v){
                    var n=this.getSubNode('INPUT'),
                        cls=this.getClass('KEY','-readonly');
                    
                    if(v)this.getRoot().addClass(cls);
                    else this.getRoot().removeClass(cls);
                }
            },
            type:{
                ini:'text',
                listbox:['text','password'],
                action: function(value){
                    this.getSubNode('INPUT').attr('type',value);
                }
            },
            maxlength:{
            	ini:'',
            	action: function(value){
                  this.getSubNode('INPUT').attr('maxlength',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){},
            onCancel:function(profile){},
            beforeFormatCheck:function(profile, value){},
            beforeFormatMark:function(profile, formatErr){},
            beforeKeypress:function(profile,caret,keyboard,e,src){},
            
            onLabelClick:function(profile, e, src){},
            onLabelDblClick:function(profile, e, src){},
            onLabelActive:function(profile, e, src){}
        },
        _prepareData:function(profile){
            // give default labelCaption
            if(profile.properties.labelCaption===undefined)
                profile.properties.labelCaption =  profile.alias;

            var d=arguments.callee.upper.call(this, profile);

            d._type = d.type || '';
            if(linb.browser.kde)
                d._css='resize:none;';
            d.hAlign=d.hAlign?("text-align:" + d.hAlign):"";
            
            d.labelHAlign=d.labelHAlign?("text-align:" + d.labelHAlign):"";
            d.labelShow=d.labelSize?"":("display:none");
    
            // adjustRes for labelCaption
            d.labelCaption=linb.adjustRes(d.labelCaption,true);

            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;
        },
        _ensureValue:function(profile, value){
            // ensure return string
            return ""+(_.isSet(value)?value:"");
        },
        RenderTrigger:function(){
            var ns=this,p=ns.properties;
            _.asyRun(function(){
                if(ns.box)
                    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);
                    if(src){
                        src.detachEvent("onpropertychange",f);
                        src.detachEvent("ondrop",f);
                        src=null;
                    }
                }
            }else{
                src.addEventListener("input",f,false);
                src.addEventListener("drop",f,false);
                //Firefox earlier than version 3.5
                if(linb.browser.gek)
                    src.addEventListener("dragdrop",f,false);

                ns.$ondestory=function(){
                    var ns=this,
                        src=ns.getSubNode('INPUT').get(0);
                    if(src){
                        src.removeEventListener("input",f,false);
                        src.removeEventListener("drop",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,
                cc=p.mask.charAt(caret[0]),
                reg = ns._maskMap[cc],
                i,t;

            if(reg && v && v.length==1){
                if(cc=='l')
                    v=v.toLowerCase();
                else if(cc=='u')
                    v=v.toUpperCase();
            }

            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);
            }
        },
        // for checking html <input>
        _checkValid2:function(profile){
            if(!profile.renderId)return true;
            return this._checkValid(profile, profile.getSubNode('INPUT').get(0).value);
        },
        //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(){
                if(!profile.renderId)return;

                var input=profile.getSubNode("INPUT"),
                    src=input.get(0);
                if(!src)return;

                //for onchange event
                if(profile.properties.dynCheck)
                    profile.boxing().setUIValue(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','paddingLeft'),
                    roff=linb.UI.$getCSSValue('linb-input-input','paddingRight');

                var t = profile.properties,
                    o = profile.getSubNode('BOX'),
                    label = profile.getSubNode('LABEL'),
                    labelSize=t.labelSize||0,
                    labelGap=t.labelGap||0,
                    labelPos=t.labelPos || 'left',
                    v1=profile.getSubNode('INPUT'),
                    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();
                }

                o.cssRegion({
                    left:left + (labelPos=='left'?labelSize:0),
                    top:top + (labelPos=='top'?labelSize:0),
                    width:ww===null?null:Math.max(0,(ww - ((labelPos=='left'||labelPos=='right')?labelSize:0))),
                    height:hh===null?null:Math.max(0,(hh - ((labelPos=='top'||labelPos=='bottom')?labelSize:0)))
                });
                
                if(labelSize)
                    label.cssRegion({
                        left:ww===null?null:Math.max(0,labelPos=='right'?(ww-labelSize+labelGap):0),
                        top: height===null?null:Math.max(0,labelPos=='bottom'?(height-labelSize+labelGap):0), 
                        width:ww===null?null:Math.max(0,((labelPos=='left'||labelPos=='right')?(labelSize-labelGap):ww)),
                        height:height===null?null:Math.max(0,((labelPos=='top'||labelPos=='bottom')?(labelSize-labelGap):height))
                    });

                if(ww||hh)
                    v1.cssSize({
                        width:ww?Math.max(0,(ww-loff-roff-((labelPos=='left'||labelPos=='right')?labelSize:0))):null,
                        height:hh?Math.max(0,(hh-toff-((labelPos=='top'||labelPos=='bottom')?labelSize:0))):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(!_.isSet(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}',
            className:'{_className}',
            EDITOR:{
                tagName:'div'
            },
            POOL:{}
        },
        DataModel:{
            selectable:true,
            value:'',
            width:400,
            height:300,
            cmdList:{
                ini:'font1;font2;align;list;font4;font3;insert;clear;html',
                action:function(v){
                    var ns=this;
                    if(!ns.properties.disabled && !ns.properties.readonly)
                        ns.box._iniToolBar(ns);
                }
            },
            disabled:{
                ini:false,
                action: function(disabled){
                    var disabled=this.properties.disabled||this.properties.readonly,
                        doc=this.$doc;
                    if(doc){
                        if (doc.body.contentEditable != undefined && linb.browser.ie)
                           doc.body.contentEditable = disabled?"false":"true";
                        else
                           doc.designMode=disabled?"off":"on";
                        
                        this.box._iniToolBar(this, !disabled);
                    }
                }
            },
            readonly:{
                ini:false,
                action: function(v){
                    this.boxing().setDisabled(v);
                }
            }
        },
        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',
                '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)return;

            if(profile.properties.disabled || profile.properties.readonly)return;

            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;

            if(!self.properties.disabled && !self.properties.readonly)
                self.box._iniToolBar(self);

            if(!self.$inDesign){
                var div=self.getSubNode('EDITOR').get(0),
                    domId=self.$domId,
                    id=div.id;
                // rendered already
                if(!self.$once){
                    self.$once=true;
                    var kprf=this;
                    var iframe=document.createElement("iframe"),
                        //_updateToolbar event
                        event=self._event=function(e){
                            if(kprf && (kprf.properties.disabled||kprf.properties.readonly))return;
    
                            _.resetRun('RichEditor:'+domId, function(){
                                linb.UI.RichEditor._updateToolbar(domId)
                            },100);
    
                            //for BlurTrigger
                            if(e.type=='mousedown')
                                linb.doc.onMousedown(true);
                        },
                        _focus=function(e){
                            if(!kprf)return;
                            if(kprf.properties.disabled||kprf.properties.readonly)return;
                            kprf.box._onchange(kprf);
                        },
                        _blur=function(e){
                            if(!kprf)return;
                            if(kprf.properties.disabled||kprf.properties.readonly)return;
                            
                            _.resetRun('RichEditor:'+domId, function(){
                                linb.UI.RichEditor._updateToolbar(domId, true)
                            },100);

                            if(kprf._onchangethread){
                                clearInterval(kprf._onchangethread);
                                kprf._onchangethread=null;
                            }
                        },
                        gekfix=function(e){
                            // to fix firefox appendChid's bug: refresh iframe's document
                            if(kprf){
                                var ins=kprf.boxing();
                                _.asyRun(function(){
                                    ins.refresh(); 
                                });
                            }
                        },
                        doc,win,
                        checkF = function(){
                            // removed from DOM already
                            if(!frames[id])return false;
                            // not ready
                            if(!frames[id].document)return;
                            
                            if(frames[id].document!=doc || doc.readyState=='complete'){
                                win=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;font-size:12px;}p{margin:0;padding:0;} div{margin:0;padding:0;}</style></head><body>'+(self.properties.$UIvalue||"")+'</body></html>');
                                doc.close();
    
                                try{doc.execCommand("styleWithCSS", 0, false)}catch(e){
                                    try {doc.execCommand("useCSS", 0, true)}catch(e){}
                                }
    
                                var disabled=self.properties.disabled||self.properties.readonly;
    
                                if (doc.body.contentEditable != undefined && linb.browser.ie)
                                   doc.body.contentEditable = disabled?"false":"true";
                                else
                                   doc.designMode=disabled?"off":"on";
                                
                                // ensure toolbar disable
                                if(disabled){
                                    self.box._iniToolBar(self, false);
                                }
    
                                win._gekfix=gekfix;
    
                                if(linb.browser.ie){
                                    doc.attachEvent("unload",gekfix);
    
                                    if(!disabled){
                                        doc.attachEvent("onmousedown",event);
                                        doc.attachEvent("ondblclick",event);
                                        doc.attachEvent("onclick",event);
                                        doc.attachEvent("onkeyup",event);
                                        doc.attachEvent("onkeydown",event);
                                        win.attachEvent("onfocus",_focus);
                                        win.attachEvent("onblur",_blur);
                                        self.$beforeDestroy=function(){
                                            var win=this.$win,
                                                doc=this.$doc,
                                                event=this._event;
                                            if(this._onchangethread){
                                                clearInterval(this._onchangethread);
                                                this._onchangethread=null;
                                            }

                                            // crack for ie7/8 eat focus
                                            // error raise in ie6
                                            try{
                                                var status=doc.designMode;
                                                doc.designMode="off";
                                                doc.designMode="on";
                                                doc.designMode=status;
                                            }catch(e){}

                                            win._gekfix=undefined;

                                            try{doc.detachEvent("unload",win._gekfix);}catch(e){}

                                            if(!this.properties.disabled && !this.properties.readonly){
                                                doc.detachEvent("onmousedown",event);
                                                doc.detachEvent("ondblclick",event);
                                                doc.detachEvent("onclick",event);
                                                doc.detachEvent("onkeyup",event);
                                                doc.detachEvent("onkeydown",event);
                                                win.detachEvent("onfocus",_focus);
                                                win.detachEvent("onblur",_blur);
                                            }
                                            win=doc=event=null;
                                        }
                                    }
                                }else{
                                    var prf=self;
                                    // for opera
                                    if(linb.browser.opr){
                                        prf.$repeatT=linb.Thread.repeat(function(){
                                            if(!frames[id])
                                                return false;
                                            else{
                                                if(!prf.$win.document || !prf.$win.document.defaultView)
                                                    prf.boxing().refresh(); 
                                            }
                                        }, 200);
                                    }else
                                        win.addEventListener("unload",gekfix,false);

                                    if(!disabled){
                                        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("focus",_focus,false);
                                            doc.addEventListener("blur",_blur,false);
                                            doc.addEventListener("keypress",event,false);
                                        }else{
                                            win.addEventListener("focus",_focus,false);
                                            win.addEventListener("blur",_blur,false);
                                            doc.addEventListener("keydown",event,false);
                                        }
                                    }
    
                                    //don't ues $ondestory, opera will set doc to null
                                    self.$beforeDestroy=function(){
                                        var win=this.$win,
                                            doc=this.$doc,
                                            event=this._event;
                                        // for opera
                                        if(linb.browser.opr)
                                            if(prf.$repeatT)prf.$repeatT.abort();

                                        try{win.removeEventListener("unload",win._gekfix,false);}catch(e){}

                                        win._gekfix=undefined;
    
                                        //for firefox
                                        delete frames[this.$frameId];
    
                                        if(!this.properties.disabled && !this.properties.readonly && doc.removeEventListener){
                                            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("focus",_focus,false);
                                                doc.removeEventListener("blur",_blur,false);
                                                doc.removeEventListener("keypress",event,false);
                                            }else{
                                                win.removeEventListener("focus",_focus,false);
                                                win.removeEventListener("blur",_blur,false);
                                                doc.removeEventListener("keydown",event,false);
                                            }
                                        }
                                        prf=gekfix=event=win=doc=null;
                                    }
                                }
    
                                iframe.style.visibility='';
    
                                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;
                }
            }
        },
        _checkc:function(profile){
            if(profile && profile.$doc){
                var doc=profile.$doc, body=doc && (doc.body||doc.documentElement);
                if(!profile.__oldv)
                    profile.__oldv=body.innerHTML;
                if(body.innerHTML!=profile.__oldv){
                    profile.__oldv=body.innerHTML;
                    profile.boxing().onChange(profile);
                }
            }
        },
        _onchange:function(profile){
            if(profile.onChange){
                profile._onchangethread=setInterval(function(){
                    if(profile && profile.box)
                        profile.box._checkc(profile);
                }, 300);
            }
        },
        _clearPool:function(profile){
            profile.getSubNode('POOL').empty();
            profile.$colorPicker=profile.$fontsizeList=profile.$fontnameList=profile.$formatblockList=profile.$htmlEditor=null;
        },
        _iniToolBar:function(profile, flag){
            var self=profile,
                pro=self.properties,
                tbH;
            if(self.$toolbar){
                self.$toolbar.boxing().destroy();
                delete self._$tb;
                delete self.$toolbar;
            }

            if(flag!==false){
                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({selectable:false,handler:false,items:items,disabled:pro.disabled||pro.readonly})
                );
                t.render(true);
                // keep toolbar's height number here
                profile.$_tbH=tbH=t.getRoot().height();

                if(linb.browser.ie)
                    t.getRoot().query('*').attr('unselectable','on');

                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);
            return tbH;
        },
        _toolbarclick:function(profile,item,group,e,src){
            var editor=profile.$hostage;
            if(!editor.$doc)return;

            var pro=editor.properties, first;
            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){
                            first=true;
                            editor.$colorPicker=(new linb.UI.ColorPicker({selectable:false,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]+'" '+linb.$IEUNSELECTABLE()+'>'+o[1]+'</font>'});
                                });
                                first=true;
                                editor.$fontsizeList=(new linb.UI.List({selectable:false,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+'" '+linb.$IEUNSELECTABLE()+'>'+o+'</span>'});
                                });
                                first=true;
                                editor.$fontnameList=(new linb.UI.List({selectable:false,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" '+linb.$IEUNSELECTABLE()+'>'+o[1]+'</'+t+'>'});
                                });
                                first=true;
                                editor.$formatblockList=(new linb.UI.List({selectable:false,height:'auto',items:items2})).render(true);
                            }
                            o=editor.$formatblockList;
                        }
                        break;
                    case 'html':
                        if(!editor.$htmlEditor){
                            first=true;
                            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);

                    if(first && linb.browser.ie)
                        o.getRoot().query('*').attr('unselectable','on');
                    
                    _.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)
            }
        },
        _ensureValue:function(profile, value){
            var p=linb.$getGhostDiv();
            p.innerHTML=(_.isSet(value)?value:'')+"";
            v=p.innerHTML;
            p=null;
            return v;
        },
        _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,
                    tbh=itb.getRoot().height();
                if(tbh)
                    profile.$_tbH=tbh;
                else
                    tbh=profile.$_tbH;
                var _top=(itb?(tbh-1):0);
                if(!height)
                    height=profile.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:{
        _adjustV:function(v){
            var profile=this.get(0);
            if(profile.$isNumber){
                v=(''+v).replace(/[^\d.-]/g,'');
                v=_.isNumb(parseFloat(v))?parseFloat(v):null;
            }else if(profile.properties.type=='datepicker'||profile.properties.type=='date'||profile.properties.type=='datetime'){
                v=_.isDate(v)?v:_.isFinite(v)?new Date(parseInt(v)):null;                
            }
            return v;
        },
        getValue:function(){
            var v = arguments.callee.upper.apply(this,arguments);
            return this._adjustV(v);
        },
        getUIValue:function(){
            var v = arguments.callee.upper.apply(this,arguments);
            return this._adjustV(v);
        },
        _getCtrlValue:function(){
            return this.get(0).properties.$UIvalue;
            //return this._fromEditor(this.getSubNode('INPUT').attr('value'));
        },
        _setCtrlValue:function(value){
            var ns=this,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=profile.$_onedit
                    // for enter/esc key, show editMode value
                    ? ns._toEditor(value)
                    : ns.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'||type=='color')
                    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;

            // try to give default caption
            if(t = profile.CF.getShowValue||profile.$getShowValue)
                v = t(profile, value);
            else{
                //get from items
                if('listbox'==pro.type){
                    var list = (pro.listKey)?linb.UI.getCachedData(pro.listKey):pro.items;
                    if( list && (t=_.arr.subIndexOf(list,'id',value))!=-1){
                      v=list[t].caption;
                      if(v.length>0)
                        v=v.charAt(0)=='$'?linb.getRes(v.slice(1)):v;
                    }else
                        v=null;
                }else
                    v=profile.$showValue;
            }
            if(!_.isSet(v) && (profile.$inputReadonly || pro.inputReadonly))
                v=_.isSet(pro.caption)?pro.caption:null;
            return ""+( _.isSet(v) ? v : _.isSet(value) ? value : "");
        },
        _toEditor:function(value){
            var profile=this.get(0),
                pro=profile.properties,t;
                if(t= profile.CF.toEditor||profile.$toEditor)
                    return t(profile, value);
            return value;
        },
        _fromEditor:function(value){
            var profile=this.get(0),
                pro=profile.properties,t;

                if(t= profile.CF.fromEditor||profile.$fromEditor)
                    return t(profile, value);
            return value;
        },
        _cache:function(){
            var profile=this.get(0), drop=profile.$drop, cached=profile.properties.cachePopWnd;
            if(drop){
                if(!cached){
                    drop.boxing().destroy();
                    delete profile.$drop;
                }else{
                    if(!profile.__tryToHide){
                        profile.__tryToHide= _.asyRun(function(){
                            delete profile.__tryToHide;

                            if(linb.browser.opr)
                                drop.getRoot().css('display','none');
                            if(drop.boxing()._clearMouseOver)drop.boxing()._clearMouseOver();
                            profile.getSubNode('POOL').append(drop.getRoot());
                        });
                    }
                }
            }
            delete profile.$poplink;
            return cached;
        },
        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('FILE').get(0)
                if(!o.value)
                    return null;

                var c=o.cloneNode(false);
                c.value="";
                //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['FILE']];
                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('FILE').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, cacheDrop=pro.cachePopWnd;
                if(pro.disabled||pro.readonly)return;

                if(type=='upload'||type=='none'||type=='spin'||type=='currency'||type=='number')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.beforeComboPop && false===box.beforeComboPop(profile, pos, e, src))||type=='getter'||type=='cmdbox'||type=='popbox')
                    return;

                if(profile.__tryToHide){
                    clearTimeout(profile.__tryToHide);
                    delete profile.__tryToHide;
                }

                //get cache key
                var cachekey;
                if(cacheDrop){
                    switch(type){
                        case 'timepicker':
                        case 'time':
                        case 'datepicker':
                        case 'date':
                        case 'datetime':
                        case 'colorpicker':
                        case 'color':
                            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':
                            o = linb.create('List').render();
                            o.setHost(profile).setDirtyMark(false).setItems(_.copy(pro.items)).setListKey(pro.listKey||'');
                            o.setWidth(pro.dropListWidth || (pro.width-(pro.labelSize||0)));
                            if(pro.dropListHeight)
                                o.setHeight(pro.dropListHeight);
                            else
                                o.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
                                return b2._cache();
                            });
                            break;
                        case 'time':
                        case 'timepicker':
                            o = linb.create('TimePicker').render();
                            o.setHost(profile);
                            o.beforeClose(function(){this.boxing().activate()._cache();return false});
                            o.beforeUIValueSet(function(p, o, v){
                                var b2=this.boxing();
                                //update value
                                b2.setUIValue(v).activate();
                                return b2._cache();
                            });
                            break;
                        case 'date':
                        case 'datepicker':
                        case 'datetime':
                            o = linb.create('DatePicker').render();

                            if(type=='datetime')
                                o.setTimeInput(true);

                            o.setHost(profile);
                            o.beforeClose(function(){this.boxing().activate()._cache();return false});
                            o.beforeUIValueSet(function(p, o, v){
                                var b2=this.boxing();
                                //update value
                                b2.setUIValue(String(v.getTime())).activate();
                                return b2._cache();
                            });

                            break;
                        case 'color':
                        case 'colorpicker':
                            o = linb.create('ColorPicker').render();
                            o.setHost(profile);
                            o.beforeClose(function(){this.boxing().activate()._cache();return false});
                            o.beforeUIValueSet(function(p, o, v){
                                var b2=this.boxing();
                                //update value
                                b2.setUIValue('#'+v).activate();
                                return b2._cache();
                            });
                            break;
                    }
                    if(_.isHash(pro.popCtrlProp) && !_.isEmpty(pro.popCtrlProp))
                        o.setProperties(pro.popCtrlProp);
                    if(_.isHash(pro.popCtrlEvents) && !_.isEmpty(pro.popCtrlEvents))
                        o.setEvents(pro.popCtrlEvents);

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

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

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

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

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

                if(profile.beforePopShow && false===box.beforePopShow(profile, profile.$drop))
                    return;

                //pop
                var node=o.reBoxing();
                node.popToTop(profile.getSubNode('BOX'));

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

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

                //for esc
                linb.Event.keyboardHookUp('esc',0,0,0,function(){
                    profile.$escclosedrop=1;
                    _.asyRun(function(){
                        delete profile.$escclosedrop;
                    });
                    box.activate();
                    //unhook
                    linb.Event.keyboardHook('esc');
                    box._cache();
                });
                
                if(profile.afterPopShow)
                    box.afterPopShow(profile, profile.$drop);

            });
        },
        expand:function(){
            var profile=this.get(0);
            if(profile.renderId)
                profile.boxing()._drop();
        },
        collapse:function(){
            var profile=this.get(0);
            if(profile.renderId && profile.$poplink)
                profile.boxing()._cache();
        },
        getPopWnd:function(force){
            var profile=this.get(0);
            if(profile.$drop && (force||profile.$poplink))
                return profile.$drop.boxing();
        }
    },
    /*Initialize*/
    Initialize:function(){
        this.addTemplateKeys(['FILE','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:10,
                style:"{_saveDisplay}",
                STOP:{},
                SMID:{
                    className:"{_commandCls}"
                }
            }
        },'all');
        t.FRAME.POOL={};
        t.className +=' {typecls}';

        this.setTemplate(t);

        this._adjustItems=linb.absList._adjustItems;
    },
    Static:{
        _beforeResetValue:function(profile){
            profile.properties.caption=undefined;
        },
        _iniType:function(profile){
            var pro=profile.properties, type=pro.type, c=profile.box;
            delete profile.$beforeKeypress;
            delete profile.$inputReadonly;
            delete profile.$isNumber;
            delete profile.$compareValue;
            delete profile.$getShowValue;
            delete profile.$toEditor;
            delete profile.$fromEditor;
            delete profile.$typeOK;

            if(type=='listbox'||type=='upload'||type=='cmdbox')
                profile.$inputReadonly=true;

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

            if(type=='timepicker' || type=='time'){
                var keymap={a:1,c:1,v:1,x:1};
                _.merge(profile,{
                    $beforeKeypress : function(p,c,k){
                        return k.key.length!=1 || /[-0-9:]/.test(k.key)|| (k.ctrlKey&& !!keymap[k.key]);
                    },
                    $getShowValue : function(p,v){
                        return v?linb.UI.TimePicker._ensureValue(p,v):'';
                    },
                    $fromEditor : function(p,v){
                        if(v){
                            v = linb.UI.TimePicker._ensureValue(p,v);
                            if(v=='00:00')v=p.properties.$UIvalue;
                        }
                        return v;
                    }
                },'all');
            }else if(type=='datepicker' || type=='date' || type=='datetime'){
                var date=linb.Date;
                var keymap={a:1,c:1,v:1,x:1};
                _.merge(profile,{
                    $beforeKeypress : function(p,c,k){
                        return k.key.length!=1 || /[0-9:/\-_ ]/.test(k.key) ||(k.ctrlKey && !!keymap[k.key]);
                    },
                    $compareValue : function(p,a,b){
                        return (!a&&!b) || (String(a)==String(b))
                    },
                    $getShowValue : function(p,v){
                        if(p.properties.dateEditorTpl)
                            return v?date.format(v, p.properties.dateEditorTpl):'';
                        else
                            return v?date.getText(new Date(parseInt(v)), p.properties.type=='datetime'?'ymdhn':'ymd'):'';
                    },
                    $toEditor : function(p,v){
                        if(!v)return "";

                        v=new Date(parseInt(v)||0);
                        if(p.properties.dateEditorTpl)
                            return date.format(v, p.properties.dateEditorTpl);
                        else{
                            var m=(date.get(v,'m')+1)+'',d=date.get(v,'d')+'',h=date.get(v,'h')+'',n=date.get(v,'n')+'';
                            return date.get(v,'y')+'-'+(m.length==1?'0':'')+m+'-'+(d.length==1?'0':'')+d 
                            
                              +(p.properties.type=='datetime'?(" "+(h.length==1?'0':'')+h +":" +(n.length==1?'0':'')+n):"");
                        }
                    },
                    $fromEditor : function(p,v){
                        if(v){
                            if(p.properties.dateEditorTpl)
                                v=date.parse(v, p.properties.dateEditorTpl);
                            else
                                v=linb.Date.parse(v);
                            // set to old UIvalue
                            if(!v){
                                v=p.properties.$UIvalue;
                                if(_.isFinite(v))v=new Date(parseInt(v));
                            }
                            if(v){
                                if(p.properties.type!='datetime')
                                    v=date.getTimSpanStart(v,'d',1);
                                // min/max year
                                if(v.getFullYear()<p.properties.min)
                                    v.setTime(p.properties.min);
                                if(v.getFullYear()>p.properties.max)
                                    v.setTime(p.properties.max);
                            }
                        }
                        return v?String(v.getTime()):'';
                    }
                },'all');
            }else if(type=='currency'){
                profile.$isNumber=1;
                var keymap={a:1,c:1,v:1,x:1};
                _.merge(profile,{
                    $beforeKeypress : function(p,c,k){
                        return k.key.length!=1 || /[-0-9,.]/.test(k.key) ||(k.ctrlKey && !!keymap[k.key]);
                    },
                    $compareValue : function(p,a,b){
                        return ((a===''&&b!=='')||(b===''&&a!==''))?false:p.box._number(p, a)==p.box._number(p, b)
                    },
                    $getShowValue : function(p,v){
                        if(_.isSet(v)&&v!==""){
                            v=p.box.formatCurrency(p.box._number(p, v), p.properties.precision);
                            if(p.properties.currencyTpl)
                                v=p.properties.currencyTpl.replace("*", v);
                        }else
                            v="";
                        return v;
                    },
                    $toEditor : function(p,v){
                        return (_.isSet(v)&&v!=="")?p.box.formatCurrency(p.box._number(p, v), p.properties.precision):"";
                    },
                    $fromEditor : function(p,v){
                        return (_.isSet(v)&&v!=="")?p.box._number(p, v):"";
                    }
                },'all');
            }else if(type=='number' || type=='spin'){
                profile.$isNumber=1;
                var keymap={a:1,c:1,v:1,x:1};
                _.merge(profile,{
                    $beforeKeypress : function(p,c,k){
                        return k.key.length!=1 || /[-0-9.]/.test(k.key)|| (k.ctrlKey && !!keymap[k.key]);
                    },
                    $compareValue : function(p,a,b){
                        return ((a===''&&b!=='')||(b===''&&a!==''))?false:p.box._number(p, a)==p.box._number(p, b)
                    },
                    $getShowValue : function(p,v){
                        return (_.isSet(v)&&v!=="")?p.box._number(p, v):"";
                    },
                    $fromEditor : function(p,v){
                        return (_.isSet(v)&&v!=="")?p.box._number(p, v):"";
                    }
                },'all');
            }

            if(pro.value)
                pro.$UIvalue=pro.value=c._ensureValue(profile,pro.value);

            profile.$typeOK=true;
        },
        $drop:{},
        Appearances:{
            POOL:{
                position:'absolute',
                left:0,
                top:0,
                width:0,
                height:0,
                display:'none',
                visibility:'hidden'
            },
            FILE:{
                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'
            },
            'KEY-number INPUT, KEY-spin INPUT, KEY-currency INPUT':{
                $order:4,
                'text-align':'right'
            },
            'KEY-upload INPUT, KEY-cmdbox INPUT, KEY-listbox INPUT':{
                $order:4,
                cursor:'pointer',
                'text-align':'left',
                overflow:'hidden'
            },
            'KEY-upload BOX, KEY-cmdbox BOX, KEY-listbox BOX':{
                $order:4,
                background:linb.UI.$bg('inputbgb.gif', '#fff left bottom repeat-x',"Input")
            },
            'RBTN,SBTN,BTN':{
                display:'block',
                'z-index':'1',
                cursor:'pointer',
                width:'16px',
                height:'20px',
                'font-size':0,
                'line-height':0,
                position:'absolute'
            },
            SBTN:{
                $order:2,
                'z-index':'6'
            },
            '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'
            },
            'SMID':{
                $order:3,
                'background-position':'-16px -16px'
            },
            'SMID-save':{
                $order:8,
                'background-position': '-32px 0'
            },
            'SMID-delete':{
                $order:8,
                'background-position': '-32px -16px'
            },
            'SMID-add':{
                $order:8,
                'background-position': '-32px -32px'
            },
            'SMID-remove':{
                $order:8,
                'background-position': '-32px -48px'
            },
            'SMID-select':{
                $order:8,
                'background-position': 'left -16px'
            },
            'SMID-pop':{
                $order:8,
                'background-position': '-32px -64px'
            },
            '.setting-linb-comboinput':{
                'border-style':'solid',
                'border-top-width':'1px',
                'border-bottom-width':'1px',
                'border-left-width':'1px',
                'border-right-width':'1px'
            }
        },

        _objectProp:{tagVar:1,popCtrlProp:1,popCtrlEvents:1},
        Behaviors:{
            HoverEffected:{BOX:'BOX',BTN:'BTN',SBTN:'SBTN',R1:'R1',R2:'R2'},
            ClickEffected:{BTN:'BTN',SBTN:'SBTN',R1:'R1',R2:'R2'},
            FILE:{
                onClick : function(profile, e, src){
                    var prop=profile.properties;
                    if(prop.disabled || prop.readonly)return;
                    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){
                    var prop=profile.properties;

                    if(prop.type=='popbox' || prop.type=='getter'){
                        if(profile.onClick && false===profile.boxing().onClick(profile, e, src, prop.$UIvalue))
                            return;
                    }

                    if(prop.disabled || prop.readonly)return;
                    profile.boxing()._drop(e, src);
                }
            },
            SBTN:{
                onClick : function(profile, e, src){
                    var prop=profile.properties;
                    if(prop.disabled || prop.readonly)return;
                    if(profile.onCommand)profile.boxing().onCommand(profile,src);
                }
            },
            BOX:{
                onClick : function(profile, e, src){
                    var prop=profile.properties;
                    if(prop.type=='cmdbox'){
                        if(profile.onClick)
                            profile.boxing().onClick(profile, e, src, prop.$UIvalue);
                    //DOM node's readOnly
                    }else if(prop.inputReadonly || profile.$inputReadonly){
                        if(prop.disabled || prop.readonly)return;
                        profile.boxing()._drop(e, src);
                    }
                }
            },
            INPUT:{
                onChange:function(profile, e, src){
                    if(profile.$_onedit||profile.$_inner)return;
                    var o=profile._inValid,
                        b=profile.box,
                        instance=profile.boxing(),
                        v = instance._fromEditor(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{
                            // trigger events
                            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();
                        }
                    }
                    b._asyCheck(profile);
                },
                onKeyup:function(profile, e, src){
                    var p=profile.properties,b=profile.box,
                        key=linb.Event.getKey(e);
                    if(p.disabled || p.readonly)return false;
                    if(profile.$inputReadonly || p.inputReadonly)return;

                    // must be key up event
                    if(key.key=='esc'){
                        if(profile.$escclosedrop){
                            return;
                        }
                        
                        profile.$_onedit=true;
                        profile.boxing().setUIValue(p.value,true);
                        profile.$_onedit=false;
                        if(profile.onCancel)
                            profile.boxing().onCancel(profile);
                    }

                    if(p.dynCheck){
                        var value=linb.use(src).get(0).value;
                        profile.box._checkValid(profile, value);
                        profile.boxing()._setDirtyMark();
                    }
                    b._asyCheck(profile);

                    if(key.key=='down'|| key.key=='up'){
                        if(p.type=='spin'){
                            linb.Thread.abort(profile.$linbid+':spin');
                            return false;
                        }
                    }
                },
                onFocus:function(profile, e, src){
                    var p=profile.properties,b=profile.box;
                    if(p.disabled || p.readonly)return false;
                    if(profile.onFocus)profile.boxing().onFocus(profile);
                    if(profile.$inputReadonly || p.inputReadonly)return;
                    profile.getSubNode('BORDER').tagClass('-focus');
                    
                    var instance=profile.boxing(),
                        uiv=p.$UIvalue,
                        v=instance._toEditor(uiv);
                    //string compare
                    if(linb.use(src).get(0).value!=v){
                        //here, dont use $valueFormat, valueFormat or onValueFormat
                        //use $getShowValue, $toEditor, $fromEditor related functions
                        profile.$_onedit=true;
                        var node=linb.use(src).get(0),
                            resel=linb.browser.ie && !node.readOnly && node.select && document.selection.createRange().text;
                        
                        node.value=v;

                        // reselect
                        if(resel)
                            try{node.select()}catch(e){}

                        delete profile.$_onedit;
                    }

                    //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);                
                },
                onBlur:function(profile, e, src){
                    var p=profile.properties;
                    if(p.disabled || p.readonly)return false;
                    if(profile.onBlur)profile.boxing().onBlur(profile);
                    if(profile.$inputReadonly || p.inputReadonly)return;

                    var b=profile.box,
                        instance=profile.boxing(),
                        uiv=p.$UIvalue,
                        v = instance._fromEditor(linb.use(src).get(0).value);

                    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();
                    b._asyCheck(profile);
                },
                onKeydown : function(profile, e, src){
                   var  p=profile.properties;
                   if(p.disabled || p.readonly)return;
                   var b=profile.box,
                        m=p.multiLines,
                        evt=linb.Event,
                        k=evt.getKey(e);

                    //fire onchange first
                    if(k.key=='enter' && (!m||k.altKey) && !p.inputReadonly && !profile.$inputReadonly){
                        profile.$_onedit=true;
                        profile.boxing().setUIValue(profile.boxing()._fromEditor(linb.use(src).get(0).value),true);
                        profile.$_onedit=false;
                    }

                    b._asyCheck(profile);

                    if(p.mask){
                        if(k.key.length>1)profile.$ignore=true;
                        else delete profile.$ignore;
                        switch(k.key){
                            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;
                        }
                    }

                    if(k.key=='down'|| k.key=='up'){
                        if(p.type=='spin'){
                            if(!k.ctrlKey){
                                profile.box._spin(profile, k.key=='up');
                                return false;
                            }
                        }else if(k.ctrlKey && p.type!='none'){
                            profile.boxing()._drop(e,src);
                            return false;
                        }
                    }
                }
            },
            R1:{
                onMousedown:function(profile){
                    var prop=profile.properties;
                    if(prop.disabled || prop.readonly)return;
                    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){
                    var prop=profile.properties;
                    if(prop.disabled || prop.readonly)return;
                    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){},
            onCommand:function(profile, node){},
            beforeComboPop:function(profile, pos, e, src){},
            beforePopShow:function(profile, popCtl){},
            afterPopShow:function(profile, popCtl){},
            onClick:function(profile, e, src, value){}
        },
        _posMap:{
            none:'',
            currency:'',
            'number':'',
            combobox:'left top',
            listbox:'left top',
            upload:'-16px top',
            getter:'left -31px',
            helpinput:'-16px -46px',
            cmdbox:'left -16px',
            popbox:'left -46px',
            time:'left -60px',
            date:'left -75px',
            color:'-16px -60px',
 
            // Deprecated
            timepicker:'left -60px',
            datepicker:'left -75px',
            datetime:'left -75px',
            colorpicker:'-16px -60px'
        },
        DataModel:{
            cachePopWnd:true,
            // allowed: yyyy,mm,dd,y,m,d
            // yyyy-mm-dd
            // yyyy/mm/dd
            dateEditorTpl:"",
            popCtrlProp:{
                ini:{}
            },
            popCtrlEvents:{
                ini:{}
            },
            currencyTpl:{
                ini:"$ *",
                action: function(){
                    this.boxing().setUIValue(this.properties.$UIvalue,true);
                }
            },
            listKey:{
                set:function(value){
                    var t = linb.UI.getCachedData(value),
                        o=this;
                    o.boxing().setItems(t?_.clone(t):o.properties.items);
                    o.properties.listKey = value;
                }
            },
            dropListWidth:0,
            dropListHeight:0,
            items:{
                ini:[],
                set:function(value){
                    var o=this;
                    value = o.properties.items = o.box._adjustItems(value);
                    if(o.renderId){
                        //clear those
                        o.SubSerialIdMapItem={};
                        o.ItemIdMapSubSerialId={};
                        o.box._prepareItems(o, value);

                        // if popped
                        if(o.$poplink)
                            o.$poplink.boxing().setItems(value).adjustSize();
                        else
                            o.boxing().clearPopCache();
                    }
                }
            },
            btnImage:{
                action: function(value){
                    this.getSubNode('MID')
                        .css('backgroundImage','url('+(value||'')+')');
                }
            },
            btnImagePos:{
                action: function(value){
                    this.getSubNode('MID')
                        .css('backgroundPosition', value);
                }
            },
            type:{
                ini:'combobox',
                listbox:_.toArr('none,combobox,listbox,upload,getter,helpinput,cmdbox,popbox,date,time,datetime,color,spin,currency,number'),
                set:function(value){
                    var pro=this;
                    pro.properties.type=value;
                    if(pro.renderId)
                        pro.boxing().refresh(true);
                }
            },
            precision:2,
            increment:0.01,
            min:-Math.pow(10,15),
            // big number for date
            max:Math.pow(10,15),
            commandBtn:{
                ini:"none",
                listbox:_.toArr("none,save,delete,add,remove,pop,select,custom"),
                action:function(v){
                    this.boxing().refresh();
                }
            },
            inputReadonly:{
                ini:false,
                action: function(v){
                    var n=this.getSubNode('INPUT'),
                        cls=this.getClass('KEY','-inputreadonly');
                    if(v)this.getRoot().addClass(cls);
                    else this.getRoot().removeClass(cls);

                    if(!v && (this.properties.readonly||this.$inputReadonly))
                        v=true;
                    n.attr('readonly',v).css('cursor',v?'pointer':'');
                }
            },
            readonly:{
                ini:false,
                action: function(v){
                    var n=this.getSubNode('INPUT'),
                        cls=this.getClass('KEY','-readonly');                    
                    if(v)this.getRoot().addClass(cls);
                    else this.getRoot().removeClass(cls);

                    if(!v && (this.properties.inputReadonly||this.$inputReadonly))
                        v=true;
                    n.attr('readonly',v).css('cursor',v?'pointer':'');
                        
                }
            },
            // caption is for readonly comboinput(listbox/cmdbox are readonly)
            caption:{
                ini:null,
                set:function(v,force){
                    var p=this.properties;
                    p.caption=v;
                    
                    if(_.isSet(v)){
                        v=v+"";
                        p.caption=linb.adjustRes(v,false);
                    }
                    if(this.renderId){
                        if(this.$inputReadonly || p.inputReadonly){
                            this.getSubNode('INPUT').attr("value",this.boxing().getShowValue());
                        }
                    }
                },
                get:function(){
                    return this.boxing().getShowValue();
                }
            }
        },
        RenderTrigger:function(){
            var self=this,
                instance=self.boxing(),
                p=self.properties;
            self.box._iniType(self);

            if(p.readonly)
                instance.setReadonly(true,true);
            else if(p.inputReadonly)
                instance.setInputReadonly(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 'none':
                case 'currency':
                case 'number':
                break;
                case 'spin':
                    t.RBTN={
                        $order:20,
                        style:"{rDisplay}",
                        R1:{
                            R1T:{},
                            R1B:{}
                        },
                        R2:{
                            R2T:{},
                            R2B:{}
                        }
                    };
                break;
                case 'upload':
                    t.FILE={
                        $order:20,
                        tagName:'input',
                        type:'file',
                        hidefocus:linb.browser.ie?"hidefocus":null,
                        size:'1'
                    };
                case 'listbox':
                case 'cmdbox':
                    t.BOX.WRAP.INPUT.tagName='input';
                    t.BOX.WRAP.INPUT.type='button';
                default:
                    t.BTN={
                        $order:20,
                        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.btnImage? ('background: url('+data.btnImage+')' + (data.btnImagePos||'')) :('background-position:'+map[data.type]);

            data._type="text";

            data._saveDisplay = data.commandBtn!='none'?'':'display:none';
            data._commandCls = profile.getClass("SMID","-"+data.commandBtn);

            data._popbtnDisplay = data.type!='none'?'':'display:none';
            data.typecls=profile.getClass('KEY','-'+data.type);
            return data;
        },
        _ensureValue:function(profile, value){
            var me=arguments.callee, reg=me._reg||(me._reg=/^#[\w]{6}$/),prop=profile.properties;
            //if value is empty
            if(!_.isSet(value) || value==='')return '';

            switch(profile.properties.type){
                case 'date':
                case 'datepicker':
                case 'datetime':
                    var d;
                    if(value){
                        if(_.isDate(value))
                            d=value;
                        else if(_.isFinite(value))
                            d=new Date(parseInt(value));
                    }
                    return d?String(profile.properties.type=='datetime'?d.getTime():linb.Date.getTimSpanStart(d,'d',1).getTime()):"";
                case 'color':
                case 'colorpicker':
                    return '#'+linb.UI.ColorPicker._ensureValue(null,value);
                case 'time':
                case 'timepicker':
                    return linb.UI.TimePicker._ensureValue(null,value);
                case 'currency':
                case 'number':
                case 'spin':
                    return this._number(profile, value);                
                default:
                    return typeof value=='string'?value:(value||value===0)?String(value):'';
            }
        },
        _number:function(profile, value){
            var prop=profile.properties;

            if(!_.isNumb(value))
                value=parseFloat((value+"").replace(/[^\d.-]/g,''))||0;

            if(_.isSet(prop.max))
                value=value>prop.max?prop.max:value;
            if(_.isSet(prop.min))
                value=value<prop.min?prop.min:value;
            if(_.isSet(prop.precision) && prop.precision>=0)
                 value=_.toFixedNumber(value,prop.precision);
                 
            return value;
            //var n=Math.pow(10,Math.max(parseInt(prop.precision)||0,0));
            //value=(+value||0);
            //value=Math.ceil((value-0.0000000000003)*n)/n;
        },
        formatCurrency:function(value, precision){
            if(_.isSet(precision))precision=parseInt(precision);
            precision=(precision||precision===0)?precision:2;
            value=parseFloat(value);
            if((value+"").indexOf('e')==-1){
                value=_.toFixedNumber(value,precision) + "";
                value= value.split(".");
                value[0] = value[0].split("").reverse().join("").replace(/(\d{3})(?=\d)/g, "$1,").split("").reverse().join("");
                return value.join(".");
            }else{
                return '0.00';
            }
        },
        _onresize:function(profile,width,height){
            var f=function(k){return k?profile.getSubNode(k).get(0):null},
                v1=f('INPUT'),
                isB=v1.type.toLowerCase()=='button',
                $hborder=1, 
                $vborder=1,
                toff=isB?0:linb.UI.$getCSSValue('linb-comboinput-input','paddingTop'),
                loff=isB?0:linb.UI.$getCSSValue('linb-comboinput-input','paddingLeft'),
                roff=isB?0:linb.UI.$getCSSValue('linb-comboinput-input','paddingRight');

            var t = profile.properties,
                o = profile.getSubNode('BOX'),
                label = profile.getSubNode('LABEL'),
                labelSize=t.labelSize||0,
                labelGap=t.labelGap||0,
                labelPos=t.labelPos || 'left',
                px='px',
                commandbtn=f(t.commandBtn!='none'?'SBTN':null),
                functionbtn=f(t.type=='spin'?'RBTN':t.type=='none'?null:'BTN'),
                ww=width,
                hh=height,
                bw1=0,
                bw2=0,
                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));
                bw1=(commandbtn?commandbtn.offsetWidth:0);
                bw2=(functionbtn?functionbtn.offsetWidth:0);
                ww -= (bw1+bw2);
                /*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();
            }
            var iL=left + (labelPos=='left'?labelSize:0),
                iT=top + (labelPos=='top'?labelSize:0),
                iW=ww===null?null:Math.max(0,ww - ((labelPos=='left'||labelPos=='right')?labelSize:0)),
                iH=hh===null?null:Math.max(0,hh - ((labelPos=='top'||labelPos=='bottom')?labelSize:0)),
                iH2=hh===null?null:Math.max(0,height - ((labelPos=='top'||labelPos=='bottom')?labelSize:0));

            if(null!==iW && iW-loff-roff>0)
                v1.style.width=Math.max(0,iW-loff-roff)+px;
            if(null!==iH && iH-toff>0)
                v1.style.height=Math.max(0,iH-toff)+px;

            o.cssRegion({
                left:iL,
                top:iT,
                width:iW,
                height:iH
            });
            
            if(labelSize)
                label.cssRegion({
                    left:ww===null?null:labelPos=='right'?(ww-labelSize+labelGap+bw1+bw2+$hborder*2):0,
                    top: height===null?null:labelPos=='bottom'?(height-labelSize+labelGap):0, 
                    width:ww===null?null:Math.max(0,((labelPos=='left'||labelPos=='right')?(labelSize-labelGap):ww)),
                    height:height===null?null:Math.max(0,((labelPos=='top'||labelPos=='bottom')?(labelSize-labelGap):height))
                });

            iL += (iW||0) + $hborder*2;
            if(commandbtn){
                if(iH2!==null)
                    commandbtn.style.height=Math.max(0,iH2-2) + px;
                if(iW!==null)
                    commandbtn.style.left=iL + px;
                commandbtn.style.top=iT + px;
            }
            iL += bw1;
            if(functionbtn){
                if(iH2!==null)
                    functionbtn.style.height=Math.max(0,iH2-2) + px;
                if(iW!==null)
                    functionbtn.style.left=iL + px;
                functionbtn.style.top=iT + px;

               if(iH2!==null && t.type=='spin'){
                    if(iH2/2-2>0){
                        f('R1').style.height=(iH2/2-2)+px;
                        f('R2').style.height=(iH2/2-2)+px;
                    }
                }
            }

            /*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;
        },
        resetPanelView:function(destroyChildren){
            if(!_.isSet(destroyChildren))destroyChildren=true;
            var ins;
            return this.each(function(profile){
                if(profile.renderId){
                    delete profile.$ini;
                    ins=profile.boxing();
                    ins.removeChildren(true,destroyChildren)
                    if(profile.properties.toggle)
                        ins.setToggle(false);
                }
            });
        }
    },
    Static:{
        Behaviors:{
            NavKeys:{CAPTION:1},
            HoverEffected:{TOGGLE:'TOGGLE'},
            ClickEffected:{TOGGLE:'TOGGLE'},
            DroppableKeys:['PANEL'],
            PanelKeys:['PANEL'],
            DraggableKeys:['HANDLE'],
            onSize:linb.UI.$onSize,
            HANDLE:{
                onClick:function(profile, e, src){
                    if(profile.properties.toggleBtn){
                        profile.box._toggle(profile, !profile.properties.toggle);
                        return false;
                    }
                },
                onKeydown : function(profile, e, src){
                    if(linb.Event.getKey(e).key=='enter')
                        linb(src).onClick();
                }
            }
        },
        Templates:{
            tagName : 'div',
            style:'{_style}',
            className:'{_className}',
            FIELDSET:{
                tagName : 'fieldset',
                className: ' {toggleCls}',
                LEGEND:{
                    tagName : 'legend',
                    HANDLE:{
                        tabindex: '{tabindex}',
                        TOGGLE:{
                            className: 'linb-uicmd-toggle2 {toggleCls2}',
                            style:"{toggleDispplay}"
                        },
                        ICON:{
                            $order:1,
                            className:'linb-ui-icon {imageClass}',
                            style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {imageDisplay}'
                        },
                        CAPTION : {
                            text:   '{caption}',
                            $order:2
                        }
                    }
                },
                PANEL:{
                    $order:1,
                    tagName:'div',
                    style:'{panelDisplay};{_overflow};',
                    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.img_bg+') no-repeat left top':null
            },
            'FIELDSET-checked PANEL':{
                $order:4,
                display:'none'
            },
            CAPTION:{
                'vertical-align':linb.browser.ie6?'baseline':'middle',
                'font-family': '"Verdana", "Helvetica", "sans-serif"',
                'font-size':'12px',
                'line-height':'18px'
            }
        },

        DataModel:{
            selectable:true,
            caption:{
                ini:undefined,
                // ui update function when setCaption
                action: function(v){
                    v=(_.isSet(v)?v:"")+"";
                    this.getSubNode('CAPTION').html(linb.adjustRes(v,true));
                }
            },
            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){},
            beforeFold:function(profile){},
            beforeExpend:function(profile){},
            afterFold:function(profile){},
            afterExpend: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?'linb-uicmd-toggle2-checked':'';
            
            profile._toggle = !!data.toggle;
            
            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, ins=profile.boxing();

            //event
            if(value &&!profile.$ini){
                if(ins.onIniPanelView){
                    if(ins.onIniPanelView(profile)!==false){
                        profile.$ini=true;
                    }
                    if(p.iframeAutoLoad||p.ajaxAutoLoad)
                        linb.UI.Div._applyAutoLoad(profile);
                }
            }
            if(profile._toggle !== !!value){
                //set toggle mark
                profile._toggle = p.toggle = !!value;
    
                if(value){
                    if(ins.beforeExpend && false===ins.beforeExpend(profile))return;
                }else{
                    if(ins.beforeFold && false===ins.beforeFold(profile))return;
                }
    
                //show/hide/panel
                profile.getSubNode('PANEL').css('display',value?'':'none');
                //chang toggle button
                if(p.toggleBtn)
                    profile.getSubNode('TOGGLE').tagClass('-checked', !!value);
    
                profile.getSubNode('FIELDSET').tagClass('-checked',!value);
                
                if(value){
                    if(ins.afterExpend)
                        ins.afterExpend(profile);
                }else{
                    if(ins.afterFold)
                        ins.afterFold(profile);
                }
            }
        }
    }
});Class('linb.UI.ColorPicker', ['linb.UI',"linb.absValue"], {
    Instance:{
        activate:function(){
            this.getSubNode('TOGGLE').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,
            tag=linb.UI.$tag_special,
            key=ns.KEY,
            list=ns._slist,
            l=list.length,
            i,data,
            arr=[],
            evs=linb.$IEUNSELECTABLE();

        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('<span  '+'id="'+key+'-SC:'+id+':'+list[i]+'" style="background-color:#'+list[i]+'" '+evs+'>'+list[i]+'</span>');

        //data
        data = '<div '+evs+'><span class="'+cls+'-txt"'+evs+'>R: </span><span '+'id="'+key+'-R:'+id+':" class="'+cls+'-dd2 linb-ui-draggable '+tag+'DD2_CC'+tag+'" '+evs+'>R</span><span style="width:8px;height:8px" '+evs+' ></span><span class="'+cls+'-txt"'+evs+'>H: </span><span '+'id="'+key+'-HH:'+id+':" class="'+cls+'-dd2 linb-ui-draggable '+tag+'DD2_CC'+tag+'" '+evs+'>H</span><span '+evs+'>\xB0</span></div>' +
               '<div '+evs+'><span class="'+cls+'-txt"'+evs+'>G: </span><span '+'id="'+key+'-G:'+id+':" class="'+cls+'-dd2 linb-ui-draggable '+tag+'DD2_CC'+tag+'" '+evs+'>G</span><span style="width:8px;height:8px" '+evs+' ></span><span class="'+cls+'-txt"'+evs+'>S: </span><span '+'id="'+key+'-S:'+id+':" class="'+cls+'-dd2 linb-ui-draggable '+tag+'DD2_CC'+tag+'"  '+evs+'>S</span><span '+evs+'>%</span></div>' +
               '<div '+evs+'><span class="'+cls+'-txt"'+evs+'>B: </span><span '+'id="'+key+'-B:'+id+':" class="'+cls+'-dd2 linb-ui-draggable '+tag+'DD2_CC'+tag+'" '+evs+'>B</span><span style="width:8px;height:8px" '+evs+' ></span><span class="'+cls+'-txt"'+evs+'>V: </span><span '+'id="'+key+'-V:'+id+':" class="'+cls+'-dd2 linb-ui-draggable '+tag+'DD2_CC'+tag+'" '+evs+'>V</span><span '+evs+'>%</span></div>' +
               '<div '+evs+'><span style="width:38px"'+evs+'>HEX: </span><span '+'id="'+key+'-H:'+id+':" class="'+cls+'-dd3 linb-ui-draggable '+tag+'DD3_CC'+tag+'" '+evs+'>H</span><span '+'id="'+key+'-E:'+id+':" class="'+cls+'-dd3 linb-ui-draggable '+tag+'DD3_CC'+tag+'" '+evs+''+evs+'>E</span><span '+'id="'+key+'-X:'+id+':" class="'+cls+'-dd1 linb-ui-draggable '+tag+'DD1_CC'+tag+'" '+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:'linb-uibar-t',
                        tagName:'table',
                        BARTR:{
                            tagName:'tr',
                            BARTDL:{
                                tagName:'td',
                                className:'linb-uibar-tdl'
                            },
                            BARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'linb-uibar-tdm'
                            },
                            BARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'linb-uibar-tdr'
                            }
                        }
                    },
                    BARCMDL:{
                        tagName: 'div',
                        className:'linb-uibar-cmdl'
                    },
                    BARCMDR:{
                        tagName: 'div',
                        className:'linb-uibar-cmdr',
                        CLOSE:{
                            className:'linb-uicmd-close ',
                            style:'{closeDisplay}'
                        }
                    }
                },
                MAIN:{
                    $order:2,
                    tagName:'div',
                    className:'linb-uicon-main',
                    MAINI:{
                        tagName:'div',
                        className:'linb-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:'linb-uicon-main',
                    TAILI:{
                        tagName:'div',
                        className:'linb-uicon-maini',
                        CAPTION:{
                            text : '{caption}'
                        },
                        SET:{
                            className:'linb-ui-btn',
                            SETI:{
                                className:'linb-ui-btni',
                                SETC:{
                                    className:'linb-ui-btnc',
                                    SETA:{
                                        tabindex: '{tabindex}',
                                        text:linb.wrapRes('inline.set')
                                    }
                                }
                            }
                        },
                        TOGGLE:{
                            $order:2,
                            tabindex: '{tabindex}'
                        }
                    }
                },
                BBAR:{
                    $order:4,
                    tagName:'div',
                    className:'linb-uibar-bottom-s',
                    BBART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        tagName:'table',
                        className:'linb-uibar-t',
                        BBARTR:{
                            tagName:'tr',
                            BBARTDL:{
                                tagName:'td',
                                className:'linb-uibar-tdl'
                            },
                            BBARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'linb-uibar-tdm'
                            },
                            BBARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'linb-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('linb-uibar-top-s','linb-uibar-top');
                    else
                        this.getSubNode('BAR').replaceClass('linb-uibar-top','linb-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('TOGGLE').tagClass("-adv", v);
                    ns.getRoot().width(v?410:210);
                    if(v)
                        ns.box._updateMarks(ns,ns.properties.$UIvalue,true, ns.$hsv[0])
                }
            }
        },
        Appearances:{
            KEY:{
            },
            MAINI:{
                padding:'4px 5px 4px 0'
            },
            CON:{
                height:'198px',
                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':linb.browser.ie6?'baseline':'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:'92px',
                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 span':{
                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'
            },
            SET:{
                position:'absolute',
                color:'#ff0000',
                display:'none',
                top:'0',
                right:'28px'
            },
            TOGGLE:{
                position:'absolute',
                right:'6px',
                top:'4px',
                display:linb.$inlineBlock,
                width:'15px',
                height:'15px',
                cursor:'default',
                background: linb.UI.$bg('icons.gif', 'no-repeat -300px -70px', true),
                zoom:linb.browser.ie6?1:null
            },
            'TOGGLE-mouseover':{
                'background-position': '-300px -90px'
            },
            'TOGGLE-mousedown':{
                'background-position': '-300px -110px'
            },
            "TOGGLE-adv":{
                'background-position': '-240px -70px'
            },
            'TOGGLE-adv-mouseover':{
                'background-position': '-240px -90px'
            },
            'TOGGLE-adv-mousedown':{
                'background-position': '-240px -110px'
            }
        },
        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);
                    p.box._vC(p);
                    if(!p.properties.advance)
                        p.boxing().setUIValue(sid);
                        
                    return false;
                },
                onDblclick:function(p,e,s){
                    var sid=p.getSubId(s);
                    p.boxing()._setCtrlValue(p.$tempValue=sid,false);
                    p.box._vC(p);
                    p.boxing().setUIValue(sid);
                    return false;
                }
            },
            LIST:{
                onMouseout:function(p,e,s){
                    p.box._updateDftTip(p);
                }
            },
            SET:{
                onClick:function(p,e,src){
                    p.box._vC(p);
                    p.boxing().setUIValue(p.$tempValue,true);
                }
            },
            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||properties.readonly)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);
                },
                onDblclick:function(p,e,src){
                    p.box._updateValueByPos(p, e);
                    p.box._vC(p);
                    p.boxing().setUIValue(p.$tempValue);
                }
            },
            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);
                },
                onDblclick:function(p,e,src){
                    p.box._updateValueByPos(p, e);
                    p.box._vC(p);
                    p.boxing().setUIValue(p.$tempValue);
                }
            }
        },
        _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?'linb-uibar-top':'linb-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.$onUIValueSet=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){
            if(linb.Event.getBtn(e)!="left")return;
            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;
                cls._to(profile,value,true);
                if(profile.keys.CAPTION)
                    profile.getSubNode('CAPTION').html(linb.Date.getText(value,'ymd',p.firstDayOfWeek),false);
            });
        },
        getDateFrom:function(){
            return this.get(0)._realstart;
        }
    },
    Initialize:function(){
        var self=this,
            id=linb.UI.$ID,
            tag=linb.UI.$tag_special,
            cls=linb.UI.$CLS,
            key=self.KEY;
            
        self.addTemplateKeys(['H', 'COL', 'W','TBODY', 'THEADER','TD']);
        var colgroup = '<colgroup id="'+key+'-COL:'+id+':"  class="'+tag+'COL_CS'+tag+'"  style="'+tag+'COL_CS'+tag+'"><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 ID="'+key+'-THEADER:'+id+':" class="'+tag+'THEADER_CS'+tag+'"  style="'+tag+'THEADER_CS'+tag+'" ><tr height="1%"><th id="'+key+'-H:'+id+':7" class="linb-node linb-node-th '+cls+'-h '+cls+'-w '+tag+'H_CC'+tag+'" style="'+tag+'H_CS'+tag+'"></th>',
            thead2='</tr></thead>',
            th='<th id="'+key+'-H:'+id+':@" class="linb-node linb-node-th '+cls+'-h '+tag+'H_CC'+tag+'"  style="'+tag+'H_CS'+tag+'">@</th>',
            tbody1 = '<tbody id="'+key+'-TBODY:'+id +':"  class="'+tag+'TBODY_CS'+tag+'"  style="'+tag+'TBODY_CS'+tag+'" >',
            tbody2 = '</tbody>',
            tr1='<tr>',
            tr2='</tr>',
            td1='<th id="'+key+'-W:'+id+':@"  class="linb-node linb-node-th '+cls+'-w '+tag+'W_CC'+tag+'"  style="'+tag+'W_CS'+tag+'">@</th>',
            td2='<td id="'+key+'-TD:'+id+':@" class="linb-node linb-node-td '+cls+'-td '+tag+'TD_CC'+tag+'"  style="'+tag+'TD_CS'+tag+'" '+linb.$IEUNSELECTABLE()+' >'+
                '</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) + (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:'linb-uibar-top',
                    style:'{barDisplay};',
                    BART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        className:'linb-uibar-t',
                        tagName:'table',
                        BARTR:{
                            tagName:'tr',
                            BARTDL:{
                                tagName:'td',
                                className:'linb-uibar-tdl'
                            },
                            BARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'linb-uibar-tdm'
                            },
                            BARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'linb-uibar-tdr'
                            }
                        }
                    },
                    BARCMDL:{
                        tagName:'div',
                        className:'linb-uibar-cmdl',
                        PRE2:{
                            $order:0,
                            tabindex: '{tabindex}'
                        },
                        PRE:{
                            $order:1,
                            tabindex: '{tabindex}'
                        },
                        YEAR:{
                            $order:2,
                            className:'linb-ui-draggable'
                        },
                        YTXT:{$order:3,text:'-'},
                        MONTH:{
                            $order:4,
                            className:'linb-ui-draggable'
                        },
                        MTXT:{$order:5,text:'-'},
                        DAY:{
                            $order:6
                        },
                        NEXT:{
                            $order:7,
                            tabindex: '{tabindex}'
                        },
                        NEXT2:{
                            $order:8,
                            tabindex: '{tabindex}'
                        }
                    },
                    BARCMDR:{
                        tagName: 'div',
                        className:'linb-uibar-cmdr',
                        CLOSE:{
                            className:'linb-uicmd-close ',
                            style:'{closeDisplay}'
                        }
                    }
                },
                MAIN:{
                    $order:2,
                    tagName:'div',
                    className:'linb-uicon-main',
                    MAINI:{
                        tagName:'div',
                        className:'linb-uicon-maini',
                        CON:{
                            tagName:'div',
                            BODY:{
                                tagName:'table',
                                cellpadding:"0",
                                cellspacing:"0",
                                width:'100%',
                                text:body
                            }
                        }
                    }
                },
                TAIL:{
                    $order:3,
                    tagName:'div',
                    className:'linb-uicon-main',
                    TAILI:{
                        tagName:'div',
                        className:'linb-uicon-maini',
                        CAPTION:{
                            tagName:'div',
                            style:'{_nocap}',
                            text : '{caption}',
                            $order:0
                        },
                        TIME:{
                            style:"{_timectrl}",
                            tagName:'div',
                            TPRE2:{
                                $order:0,
                                tabindex: '{tabindex}'
                            },
                            TPRE:{
                                $order:1,
                                tabindex: '{tabindex}'
                            },
                            HOUR:{
                                $order:2,
                                className:'linb-ui-draggable'
                            },
                            MTXT:{$order:3,text:':'},
                            MINUTE:{
                                $order:4,
                                className:'linb-ui-draggable'
                            },
                            TNEXT:{
                                $order:6,
                                tabindex: '{tabindex}'
                            },
                            TNEXT2:{
                                $order:7,
                                tabindex: '{tabindex}'
                            }
                        },
                        TODAY:{
                             tabindex: '{tabindex}',
                             title:"{_todaytitle}"
                        },
                        SET:{
                            className:'linb-ui-btn',
                            SETI:{
                                className:'linb-ui-btni',
                                SETC:{
                                    className:'linb-ui-btnc',
                                    SETA:{
                                        tabindex: '{tabindex}',
                                        text:linb.wrapRes('inline.set')
                                    }
                                }
                            }
                        }
                    }
                },
                BBAR:{
                    $order:4,
                    tagName:'div',
                    className:'linb-uibar-bottom-s',
                    BBART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        tagName:'table',
                        className:'linb-uibar-t',
                        BBARTR:{
                            tagName:'tr',
                            BBARTDL:{
                                tagName:'td',
                                className:'linb-uibar-tdl'
                            },
                            BBARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'linb-uibar-tdm'
                            },
                            BBARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'linb-uibar-tdr'
                            }
                        }
                    }
                }
            }
        });
    },
    Static:{
        Appearances:{
            KEY:{
                overflow:'visible'
            },
            BORDER:{
                overflow: 'visible',
                position: 'relative'
            },
            BODY:{
                position:'relative'
            },
            BARCMDL:{
                top:'3px'
            },
            TAILI:{
                position:'relative',
                height:'24px'
            },
            TIME:{
                'padding':'2px 18px'
            },
            SET:{
                position:'absolute',
                display:'none',
                color:'#ff0000',
                top:'0',
                right:'5px'
            },
            TODAY:{
                position:'absolute',
                top:'3px',
                left:'0',
                display:linb.$inlineBlock,
                width:'16px',
                height:'16px',
                cursor:'default',
                background: linb.UI.$bg('icons.gif', 'no-repeat right top', true),
                _zoom:1
            },
            'TODAY-mouseover':{
                'background-position': 'right -20px'
            },
            'TODAY-mousedown':{
                'background-position': 'right -40px'
            },
            'PRE,PRE2,NEXT,NEXT2,TPRE,TPRE2,TNEXT,TNEXT2':{
                $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, TPRE':{
                $order:1,
                'background-position': '-260px -70px'
            },
            'PRE-mouseover, TPRE-mouseover':{
                $order:2,
                'background-position': '-260px -90px'
            },
            'PRE-mousedown, TPRE-mousedown':{
                $order:3,
                'background-position': '-260px -110px'
            },
            'PRE2, TPRE2':{
                $order:1,
                'background-position': '-240px -70px'
            },
            'PRE2-mouseover, TPRE2-mouseover':{
                $order:2,
                'background-position': '-240px -90px'
            },
            'PRE2-mousedown, TPRE2-mousedown':{
                $order:3,
                'background-position': '-240px -110px'
            },
            'NEXT, TNEXT':{
                $order:1,
                'background-position': '-280px -70px'
            },
            'NEXT-mouseover, TNEXT-mouseover':{
                $order:2,
                'background-position': '-280px -90px'
            },
            'NEXT-mousedown, TNEXT-mousedown':{
                $order:3,
                'background-position': '-280px -110px'
            },
            'NEXT2, TNEXT2':{
                $order:1,
                'background-position': '-300px -70px'
            },
            'NEXT2-mouseover, TNEXT2-mouseover':{
                $order:2,
                'background-position': '-300px -90px'
            },
            'NEXT2-mousedown, TNEXT2-mousedown':{
                $order:3,
                'background-position': '-300px -110px'
            },
            'YEAR,MONTH,DAY,HOUR,MINUTE':{
                $order:4,
                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, DAY,HOUR, MINUTE':{
                width:'16px'
            },
            CAPTION:{
                padding:'4px 0 0 0',
                'text-align':'center',
                'font-size':'12px',
                'vertical-align':linb.browser.ie6?'baseline':'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',
                'font-size': '12px'
            },
            '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',TPRE:'TPRE',TPRE2:'TPRE2',TNEXT:'TNEXT',TNEXT2:'TNEXT2',SET:'SET', TODAY:'TODAY'},
            ClickEffected:{CLOSE:'CLOSE',TD:'TD',PRE:'PRE',PRE2:'PRE2',NEXT:'NEXT',NEXT2:'NEXT2',TPRE:'TPRE',TPRE2:'TPRE2',TNEXT:'TNEXT',TNEXT2:'TNEXT2',SET:'SET', 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||p.readonly)return false;

                    linb.use(src).onMouseout(true,{$force:true});

                    v = linb.Date.add(profile.$tempValue, 'd', linb.Date.diff(profile.$tempValue, v, 'd', p.firstDayOfWeek));
                    profile.box._to(profile,v);
                    
                    // set dir
                    if(!p.timeInput)
                        //onClick event
                        profile.boxing().setUIValue(v);
                },
                onDblclick:function(profile,e,src){
                    var p=profile.properties;
                    if(p.timeInput){
                        linb.use(src).onMouseout(true,{$force:true});
                        profile.boxing().setUIValue(profile.$tempValue, true);
                    }
                }
            },
            TODAY:{
                onClick:function(profile,e,src){
                    linb.use(src).onMouseout(true,{$force:true});
                    profile.boxing().setUIValue(
                        profile.properties.timeInput ?
                        new Date :
                        linb.Date.getTimSpanStart(new Date,'d',1)
                    ,true);
                }
            },
            SET:{
                onClick:function(profile,e,src){
                    linb.use(src).onMouseout(true,{$force:true});
                    profile.boxing().setUIValue(profile.$tempValue, true);
                }
            },
            CLOSE:{
                onClick:function(profile, e, src){
                    var p = profile.properties,
                        instance = profile.boxing();
                    if(p.disabled||p.readonly)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||p.readonly)return;
                    profile.box._to(profile,linb.Date.add(profile.$tempValue,'m',-1));
                }
            },
            NEXT:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    profile.box._to(profile,linb.Date.add(profile.$tempValue,'m',1));
                }
            },
            PRE2:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    profile.box._to(profile,linb.Date.add(profile.$tempValue,'y',-1));
                }
            },
            NEXT2:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    profile.box._to(profile,linb.Date.add(profile.$tempValue,'y',1));
                }
            },
            TPRE:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    profile.box._to(profile,linb.Date.add(profile.$tempValue,'n',-1));
                }
            },
            TNEXT:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    profile.box._to(profile,linb.Date.add(profile.$tempValue,'n',1));
                }
            },
            TPRE2:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    profile.box._to(profile,linb.Date.add(profile.$tempValue,'h',-1));
                }
            },
            TNEXT2:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    profile.box._to(profile,linb.Date.add(profile.$tempValue,'h',1));
                }
            },
            YEAR:{
                onMousedown:function(profile, e, src){
                    return profile.box._ondown(profile,e,src,10);
                },
                onDrag:function(profile, e, src){
                    var count,off = linb.DragDrop.getProfile().offset;
                    count=parseInt(profile.$year)+parseInt(off.x/10);
                    if(profile.$temp!=count){
                        profile.$temp2=parseInt(off.x/10);
                        profile.getSubNode('YEAR').html(count,false);
                    }
                },
                onDragstop:function(profile, e, src){
                    return profile.box._onds(profile,e,src,'y');
                }
            },
            MONTH:{
                onMousedown:function(profile, e, src){
                    return profile.box._ondown(profile,e,src,20);
                },
                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)<=9?"0":"")+(count+1),false);
                    }
                },
                onDragstop:function(profile, e, src){
                    return profile.box._onds(profile,e,src,'m');
                }
            },
            DAY:{
                onMousedown:function(profile, e, src){
                    return profile.box._ondown(profile,e,src,10);
                },
                onDrag:function(profile, e, src){
                    var date=new Date(profile.$year,profile.$month,0),
                        days=date.getDate();

                    var p=profile.properties,
                        count,
                        off = linb.DragDrop.getProfile().offset;
                    count=parseInt(profile.$day)+(parseInt(off.x/10)%days);
                    count=(count%days+days)%days + 1;
                    if(profile.$temp!=count){
                        profile.$temp=count;
                        profile.$temp2=count-profile.$day;
                        profile.getSubNode('DAY').html((count<=9?"0":"")+count,false);
                    }
                },
                onDragstop:function(profile, e, src){
                    return profile.box._onds(profile,e,src,'d');
                }
            },
            HOUR:{
                onMousedown:function(profile, e, src){
                    return profile.box._ondown(profile,e,src,20);
                },
                onDrag:function(profile, e, src){
                    return profile.box._ondrag(profile,20,24,'HOUR',profile.$hour);
                },
                onDragstop:function(profile, e, src){
                    return profile.box._onds(profile,e,src,'h');
                }
            },
            MINUTE:{
                onMousedown:function(profile, e, src){
                    return profile.box._ondown(profile,e,src,10);
                },
                onDrag:function(profile, e, src){
                    return profile.box._ondrag(profile,10,60,'MINUTE',profile.$minute);
                },
                onDragstop:function(profile, e, src){
                    return profile.box._onds(profile,e,src,'n');
                }
            }
        },
        DataModel:{
            timeInput:{
                ini:false,
                action:function(v){
                    this.getSubNode('CAPTION').css('display',v?'none':'block');
                    this.getSubNode('SET').css('display',v?'block':'none');
                    this.getSubNode('TIME').css('display',v?'block':'none');
                    this.getSubNode('TODAY').attr("title",linb.getRes(v?"inline.now":"inline.today"));
                }
            },
            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');
                }
            },
            firstDayOfWeek:{
                ini:0,
                action:function(){
                    this.boxing().refresh();
                }
            },
            offDays:{
                ini:'60',
                action:function(){
                    this.boxing().refresh();
                }
            },
            hideWeekLabels:{
                ini:false,
                action:function(){
                    this.boxing().refresh();
                }
            },
            dateInputFormat:{
                ini:"yyyy-mm-dd",
                listbox:["yyyy-mm-dd","mm-dd-yyyy","dd-mm-yyyy"],
                action:function(){
                    this.boxing().refresh();
                }
            }
        },
        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;
            
            var none="display:none;";
            if(profile.properties.timeInput){
                data._todaytitle=linb.getRes("inline.now");
                data._nocap=none;
            }else{
                data._todaytitle=linb.getRes("inline.today");
                data._timectrl=none;
            }

            return data;
        },
        _ensureValue:function(profile, value){
            var d;
            if(value){
                if(_.isDate(value))
                    d=value;
                else if(_.isFinite(value))
                    d=new Date(parseInt(value));
            }
            d = d||new Date;
            if(!profile.properties.timeInput)
                d=linb.Date.getTimSpanStart(d,'d');
            return d;
        },
        RenderTrigger:function(){
            var self=this, p=self.properties, o=self.boxing(), b=self.box;
            b._setWeekLabel(self);
            
            var hash={yyyy:'YEAR',mm:'MONTH',dd:'DAY'},arr=p.dateInputFormat.split('-');
            if(hash[arr[0]] && hash[arr[1]] && hash[arr[2]]){
                self.getSubNode('YTXT').addPrev(self.getSubNode(hash[arr[0]]));
                self.getSubNode('MTXT').addPrev(self.getSubNode(hash[arr[1]]));
                self.getSubNode('MTXT').addNext(self.getSubNode(hash[arr[2]]));
            }
            
//            self.getSubNode('YTXT').html(linb.wrapRes('date.Y'),false);
//            self.getSubNode('MTXT').html(linb.wrapRes('date.M'),false);
        },
        _getWeekNodes:function(profile){
            return profile.$weeks || (profile.$weeks=profile.getSubNode('W',true));
        },
        _getTDNodes:function(profile){
            return profile.$tds || (profile.$tds=profile.getSubNode('TD',true));
        },
        _getLabelNodes:function(profile){
            return profile.$days || (profile.$days=profile.getSubNode('TD',true));
        },
        _getHeaderNodes:function(profile){
            return profile.$header || (profile.$header=profile.getSubNode('H',true));
        },
        _setWeekLabel:function(profile){
            var p=profile.properties;

            // for week
            var fw=p.firstDayOfWeek,
                f=function(id){
                id=profile.getSubId(id); 

                // The special one
                if(id=='7')return id;
                
                id=(parseInt(id)+fw);
                return id<7?id:(id-7);
            };

            profile.box._getHeaderNodes(profile).each(function(node,i){
                node.innerHTML=linb.wrapRes('date.WEEKS.'+f(node.id))
            });
            
            // for weeklable
            if(p.hideWeekLabels){
                profile.getSubNode('BODY').query('TR').first().remove();
                profile.getSubNode('COL').first().remove();
            }

            // for free days            
            var cls2=profile.getClass('TD','-free'),
                fdmap={};
            if(p.offDays){
                _.arr.each(p.offDays.split(""),function(i){
                    i=parseInt(i);
                    if(i>=0 && i<=6)
                        fdmap[i]=1;
                });
                profile.box._getTDNodes(profile).each(function(node,i){
                    i = ((i+fw) - 7*parseInt((i+fw)/7)) ;
                    if(fdmap[i])
                        node.className=node.className + " " +cls2;
                });
            }
            
        },
        _setBGV:function(profile, v, m){
            var date=linb.Date,
                p=profile.properties,
                daymap=profile.$daymap||(profile.$daymap=[]),
                t,n;
            profile.box._getLabelNodes(profile).each(function(node,i){
                n=date.add(v,'d',i);
                daymap[i]=n;
                t=date.get(n,'m')==m?'#':'<p class="linb-node linb-node-p exday">#</p>';
                n=date.get(n,'d');
                node.innerHTML = t.replace('#',n);
            });

            if(!p.hideWeekLabels)
                profile.box._getWeekNodes(profile).each(function(node,i){
                    node.innerHTML=date.get(date.add(v,'ww',i),'ww',p.firstDayOfWeek);
                });
        },
        _to:function(profile, time, force){
            var p = profile.properties,
                fw = p.firstDayOfWeek,
                date=linb.Date,
                keys=profile.keys,
                uiv=p.$UIvalue,
                index=-1,
                node,
                temp,
                _realstart = date.getTimSpanStart(date.getTimSpanStart(time,'m'),'ww',1,fw),
                m=date.get(time,'m',fw);

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

            //remove checked css class
            if(profile.$selnode)
                profile.$selnode.tagClass('-checked',false);
            //[[add cecked css class
            _.arr.each(profile.$daymap,function(o,i){
                if(date.get(o,'m',fw)+'-'+date.get(o,'d',fw)==date.get(time,'m',fw)+'-'+date.get(time,'d',fw)){
                    index=i;
                    return false;
                }
            });
            node=this._getTDNodes(profile).get()[index];
            (profile.$selnode=linb([node]).tagClass('-checked'));
            //]]
            
            //[[ show dirty
            profile.getSubNode('SET').css('display',(force||uiv.getTime()==time.getTime())?'none':'block');
            profile.getSubNode('CAPTION').css('color',(force||uiv.getTime()==time.getTime())?'':'#ff0000');
            //]]

            temp=date.get(time,'y',fw);
            if(profile.$year!=temp){
                profile.$year=temp;
                profile.getSubNode('YEAR').html(temp,false);
            }
            temp=date.get(time,'m',fw)+1;
            if(profile.$month!=temp){
                profile.$month=temp;
                profile.getSubNode('MONTH').html((temp<=9?"0":"")+temp,false);
            }
            temp=date.get(time||time,'d',fw);
            if(profile.$day!=temp){
                profile.$day=temp;
                profile.getSubNode('DAY').html((temp<=9?"0":"")+temp,false);
            }
            temp=date.get(time,'h',fw);
            if(profile.$hour!=temp){
                profile.$hour=temp;
                profile.getSubNode('HOUR').html((temp<=9?"0":"")+temp,false);
            }
            temp=date.get(time,'n',fw);
            if(profile.$minute!=temp){
                profile.$minute=temp;
                profile.getSubNode('MINUTE').html((temp<=9?"0":"")+temp,false);
            }
        },
        _ondown:function(profile, e, src,increment){
            if(linb.Event.getBtn(e)!="left")return;
            linb.use(src).startDrag(e, {
                dragType:'blank',
                targetReposition:false,
                widthIncrement:increment,
                dragCursor:true
            });
            profile.$temp=profile.$temp2=0;
        },
        _ondrag:function(profile,increment,max,key,data){
            var p=profile.properties,
                count,
                off = linb.DragDrop.getProfile().offset;
            count=parseInt(data)+(parseInt(off.x/increment)%max);
            count=(count%max+max)%max;
            if(profile.$temp!=count){
                profile.$temp=count;
                profile.$temp2=count-data;
                profile.getSubNode(key).html((count<=9?"0":"")+count,false);
            }
        },
        _onds:function(profile, e, src, type){
            if(profile.$temp2){
                var p=profile.properties,
                    v = linb.Date.add(profile.$tempValue,type,profile.$temp2);
                profile.box._to(profile,v);
            }
            profile.$temp=profile.$temp2=0;
        },
        _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];
                profile.$minute=arr2[1];
                
                profile.getSubNode('HI',true).removeClass(cls._excls_c3).removeClass(cls._excls_mo3);
                profile.getSubNode('HI',arr2[0]).addClass(cls._excls_c3);

                profile.getSubNode('MI',true).removeClass(cls._excls_c).removeClass(cls._excls_mo);
                profile.getSubNode('MI',arr2[1]).addClass(cls._excls_c);

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

        var a,i,h,m,cls,cls2,id,t;

        cls=this._excls3;
        cls2=this._excls4;
        id=linb.UI.$ID;
        t='<span id="'+this.KEY+'-HI:'+id+':@" class="linb-node linb-node-span '+cls+' !" '+linb.$IEUNSELECTABLE()+' >@</span>';
        a=[];
        for(i=0;i<24;i++)
            a[a.length]=t.replace(/@/g,i<10?('0'+i):i).replace('!',(i%6===0)?cls2:'');
        h=a.join('');
        a.length=0;

        cls=this._excls;
        cls2=this._excls2;
        id=linb.UI.$ID;
        t='<span id="'+this.KEY+'-MI:'+id+':@" class="linb-node linb-node-span '+cls+' !" '+linb.$IEUNSELECTABLE()+' >@</span>';
        a=[];
        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:'linb-uibar-top',
                    style:'{barDisplay};',
                    BART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        tagName:'table',
                        className:'linb-uibar-t',
                        BARTR:{
                            tagName:'tr',
                            BARTDL:{
                                tagName:'td',
                                className:'linb-uibar-tdl'
                            },
                            BARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'linb-uibar-tdm'
                            },
                            BARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'linb-uibar-tdr'
                            }
                        }
                    },
                    BARCMDL:{
                        tagName: 'div',
                        className:'linb-uibar-cmdl',
                        PRE2:{
                            $order:0,
                            tabindex: '{tabindex}'
                        },
                        PRE:{
                            $order:1,
                            tabindex: '{tabindex}'
                        },
                        HOUR:{
                            $order:2,
                            className:'linb-ui-draggable'
                        },
                        MTXT:{$order:3,text:':'},
                        MINUTE:{
                                $order:4,
                                className:'linb-ui-draggable'
                            },
                        NEXT:{
                            $order:6,
                            tabindex: '{tabindex}'
                        },
                        NEXT2:{
                            $order:7,
                            tabindex: '{tabindex}'
                        }
                    },
                    BARCMDR:{
                        tagName: 'div',
                        className:'linb-uibar-cmdr',
                        CLOSE:{
                            className:'linb-uicmd-close ',
                            style:'{closeDisplay}'
                        }
                    }
                },
                MAIN:{
                    $order:2,
                    tagName:'div',
                    className:'linb-uicon-main',
                    MAINI:{
                        tagName:'div',
                        className:'linb-uicon-maini',
                        CONH:{
                            tagName:'div',
                            className:'linb-uiborder-inset',
                            text:h
                        },
                        CONM:{
                            $order:2,
                            tagName:'div',
                            className:'linb-uiborder-inset',
                            text:m
                        }
                    }
                },
                TAIL:{
                    $order:3,
                    tagName:'div',
                    className:'linb-uicon-main',
                    TAILI:{
                        tagName:'div',
                        className:'linb-uicon-maini',
                        CAPTION:{
                            text : '{caption}'
                        },
                        SET:{
                            className:'linb-ui-btn',
                            SETI:{
                                className:'linb-ui-btni',
                                SETC:{
                                    className:'linb-ui-btnc',
                                    SETA:{
                                        tabindex: '{tabindex}',
                                        text:linb.wrapRes('inline.set')
                                    }
                                }
                            }
                        }
                    }
                },
                BBAR:{
                    $order:4,
                    tagName:'div',
                    className:'linb-uibar-bottom-s',
                    BBART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        tagName:'table',
                        className:'linb-uibar-t',
                        BBARTR:{
                            tagName:'tr',
                            BBARTDL:{
                                tagName:'td',
                                className:'linb-uibar-tdl'
                            },
                            BBARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'linb-uibar-tdm'
                            },
                            BBARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'linb-uibar-tdr'
                            }
                        }
                    }
                }
            }
        });
    },
    Static:{
        _excls:'linbex-timepicker',
        _excls2:'linbex-timepicker2',
        _excls3:'linbex-timepicker3',
        _excls4:'linbex-timepicker4',

        _excls_mo:'linbex-timepicker-mouseover',
        _excls_c:'linbex-timepicker-checked',
        _excls_mo3:'linbex-timepicker3-mouseover',
        _excls_c3:'linbex-timepicker3-checked',
        _mover:function(src, type){
            var b=this,cn=src.className;
            if(type==2){
                if(cn.indexOf(b._excls_mo3)==-1)
                    src.className=cn + ' ' + b._excls_mo3;
            }else{
                if(cn.indexOf(b._excls_mo)==-1)
                    src.className=cn + ' ' + b._excls_mo;
            }
            src=null;
        },
        _mout:function(src,type){
            var b=this,cn=src.className;
            if(type==2){
                if(cn.indexOf(b._excls_mo3)!=-1)
                    src.className=cn.replace(b._excls_mo3,'');
            }else{
                if(cn.indexOf(b._excls_mo)!=-1)
                    src.className=cn.replace(b._excls_mo,'');
            }
            src=null;
        },
        Appearances:{
            KEY:{
            },
            MAINI:{
                'padding-top':'4px'
            },
            CONH:{
                width:'240px'
            },
            CONM:{
                'margin-top':'4px',
                width:'240px'
            },
            BARCMDL:{
                top:'3px'
            },
            'PRE,PRE2,NEXT,NEXT2':{
                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'
            },
            NEXT:{
                $order:1,
                'background-position': '-280px -70px'
            },
            'NEXT-mouseover':{
                $order:2,
                'background-position': '-280px -90px'
            },
            'NEXT-mousedown':{
                $order:3,
                'background-position': '-280px -110px'
            },
            PRE2:{
                $order:1,
                'background-position': '-240px -70px'
            },
            'PRE2-mouseover':{
                $order:2,
                'background-position': '-240px -90px'
            },
            'PRE2-mousedown':{
                $order:3,
                'background-position': '-240px -110px'
            },
            NEXT2:{
                $order:1,
                'background-position': '-300px -70px'
            },
            'NEXT2-mouseover':{
                $order:2,
                'background-position': '-300px -90px'
            },
            'NEXT2-mousedown':{
                $order:3,
                'background-position': '-300px -110px'
            },
            'HOUR, MINUTE':{
                $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':linb.browser.ie6?'baseline':'middle'
            },
            '.linbex-timepicker2, .linbex-timepicker4':{
                $order:1,
                'background-color':'#FDF8D2'
            },
            '.linbex-timepicker':{
                'font-size':"12px",
                width:'24px',
                height:'16px',
                'text-align':'center',
                'background-color': '#F9F9FB'
            },
            '.linbex-timepicker3':{
                'font-size':"12px",
                width:'20px',
                height:'16px',
                'text-align':'center',
                'background-color': '#F9F9FB',
                'font-weight':'bold'
            },
            '.linbex-timepicker-mouseover, .linbex-timepicker3-mouseover':{
                $order:2,
                'background-color': '#d9e8fb'
            },
            '.linbex-timepicker-checked, .linbex-timepicker3-checked':{
                $order:2,
                'background-color':'#316AC5',
                color:'#fff'
            }
        },
        Behaviors:{
            HoverEffected:{CLOSE:'CLOSE',PRE:'PRE',NEXT:'NEXT',PRE2:'PRE2',NEXT2:'NEXT2',SET:'SET'},
            ClickEffected:{CLOSE:'CLOSE',PRE:'PRE',NEXT:'NEXT',PRE2:'PRE2',NEXT2:'NEXT2',SET:'SET'},
            KEY:{onClick:function(){return false}},
            HOUR:{
                onMousedown:function(profile, e, src){
                    if(linb.Event.getBtn(e)!="left")return;
                    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.boxing()._setCtrlValue(profile.$hour+":"+profile.$minute);
                    }
                    profile.$temp2=0;
                    profile.box._hourC(profile);
                }
            },
             MINUTE:{
                onMousedown:function(profile, e, src){
                    if(linb.Event.getBtn(e)!="left")return;
                    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/20);
                    a[0]=(a[0]%60+60)%60;
                    profile.$temp2=(a[0]<=9?'0':'')+a[0];

                    if(v[0]!=profile.$temp2)
                        profile.getSubNode('MINUTE').html(profile.$temp2,false);
                },
                onDragstop:function(profile, e, src){
                    if(profile.$temp2){
                        profile.$minute=profile.$temp2;
                        profile.boxing()._setCtrlValue(profile.$hour+":"+profile.$minute);
                    }
                    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;
                    a[1]=profile.$minute;
                    profile.boxing().setUIValue(a.join(':'),true);
                    profile.box._hourC(profile);
                }
            },
            HI:{
                onMouseover:function(profile, e, src){
                    if(profile.properties.disableHoverEffect)return;
                    profile.box._mover(linb.use(src).get(0),2);
                },
                onMouseout:function(profile, e, src){
                    if(profile.properties.disableHoverEffect)return;
                    profile.box._mout(linb.use(src).get(0),2);
                },
                onClick:function(profile, e, src){
                    profile.$hour=profile.getSubId(src);
                    profile.boxing()._setCtrlValue(profile.$hour+":"+profile.$minute);
                    profile.box._hourC(profile);
                },
                onDblclick:function(profile, e, src){
                    profile.$hour=profile.getSubId(src);
                    profile.boxing().setUIValue(profile.$hour+":"+profile.$minute,true);
                    profile.box._hourC(profile);
                }
            },
            MI:{
                onMouseover:function(profile, e, src){
                    if(profile.properties.disableHoverEffect)return;
                    profile.box._mover(linb.use(src).get(0));
                },
                onMouseout:function(profile, e, src){
                    if(profile.properties.disableHoverEffect)return;
                    profile.box._mout(linb.use(src).get(0));
                },
                onClick:function(profile, e, src){
                    profile.$minute=profile.getSubId(src);
                    profile.boxing().setUIValue(profile.$hour+":"+profile.$minute,true);
                    profile.box._hourC(profile);
                }
            },
            PRE:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    var v=profile.$minute;
                    v=(parseFloat(v)||0)-1;
                    v=(v%60+60)%60;
                    profile.$minute=v=(v<=9?'0':'')+v;
                    profile.boxing()._setCtrlValue(profile.$hour+":"+profile.$minute);
                    profile.box._hourC(profile);
                }
            },
            NEXT:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    var v=profile.$minute;
                    v=(parseFloat(v)||0)+1;
                    v=(v%60+60)%60;
                    profile.$minute=v=(v<=9?'0':'')+v;
                    profile.boxing()._setCtrlValue(profile.$hour+":"+profile.$minute);
                    profile.box._hourC(profile);
                }
            },
            PRE2:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    var v=profile.$hour;
                    v=(parseFloat(v)||0)-1;
                    v=(v%24+24)%24;
                    profile.$hour=v=(v<=9?'0':'')+v;
                    profile.boxing()._setCtrlValue(profile.$hour+":"+profile.$minute);
                    profile.box._hourC(profile);
                }
            },
            NEXT2:{
                onClick:function(profile, e, src){
                    var p = profile.properties;
                    if(p.disabled||p.readonly)return;
                    var v=profile.$hour;
                    v=(parseFloat(v)||0)+1;
                    v=(v%24+24)%24;
                    profile.$hour=v=(v<=9?'0':'')+v;
                    profile.boxing()._setCtrlValue(profile.$hour+":"+profile.$minute);
                    profile.box._hourC(profile);
                }
            },
            CLOSE:{
                onClick:function(profile, e, src){
                    var properties = profile.properties,
                        instance = profile.boxing();
                    if(properties.disabled||properties.readonly)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:250,
                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+"") && (a[1]+"")==(profile.$minute+"");
            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('-checked',false).tagClass('-mouseover',false);

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

                    //scroll
                    if(itemId){
                        var o = getN(item,itemId);
                        if(o){
                            var items = profile.getSubNode('ITEMS'),
                                offset = o.offset(null, items),
                                top = offset?offset.top:0,
                                height = o.offsetHeight(),
                                sh=items.scrollHeight(),
                                st=items.scrollTop(),
                                hh=items.height();
                            if(sh > hh)
                                if(top<st || (top+height)>(st+hh))
                                    items.scrollTop(top);
                        }
                    }
                }else if(p.selMode=='multi'||p.selMode=='multibycheckbox'){
                    uiv = uiv?uiv.split(p.valueSeparator):[];
                    value = value?value.split(p.valueSeparator):[];
                    //check all
                    _.arr.each(uiv,function(o){
                        getN(k, getI(o)).tagClass('-checked',false).tagClass('-mouseover',false);
                    });
                    _.arr.each(value,function(o){
                        getN(k, getI(o)).tagClass('-checked');
                    });
                }
            });
        },
        _clearMouseOver:function(){
            var box=this.constructor,
                item=box._ITEMKEY || 'ITEM';
            this.getSubNode(item, true).tagClass('-mouseover',false);
        },
        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 arguments.callee.upper.apply(this,['ITEMS']);
        }
    },
    Static:{
        _DIRTYKEY:'ITEM',
        Templates:{
            tagName : 'div',
            style:'{_style}',
            className:'linb-uibg-base {_className}',
            ITEMS:{
               $order:10,
               tagName:'div',
               className:'{_bordertype}',
               text:"{items}"
            },
            $submap:{
                items:{
                    ITEM:{
                        className:'{itemClass} {disabled} {readonly}',
                        style:'{itemStyle}{itemDisplay}',
                        tabindex:'{_tabindex}',
                        MARK:{
                            $order:5,
                            style:"{_cbDisplay}"
                        },
                        ICON:{
                            $order:10,
                            className:'linb-ui-icon {imageClass}',
                            style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {imageDisplay}'
                        },
                        CAPTION:{
                            tagName : 'text',
                            text : '&nbsp;{caption}',
                            $order:20
                        },
                        EXTRA:{
                            text : '{ext}',
                            $order:30
                        }
                    }
                }
            }
        },
        Appearances:{
            KEY:{
                'font-size':'12px'
            },
            EXTRA:{
                display:'none'
            },
            ITEMS:{
                position:'relative',
                overflow:'auto',
                'overflow-x': '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'
            },
            MARK:{
               $order:1,
               cursor:'pointer',
               width:'16px',
               height:'16px',
               'vertical-align':'middle',
               background: linb.UI.$bg('icons.gif', 'no-repeat -20px -70px', true)
            },
            'ITEM-checked MARK':{
                $order:2,
                'background-position': '0 -70px'
            }
        },
        Behaviors:{
            HoverEffected:{ITEM:'ITEM'},
            ClickEffected:{ITEM:'ITEM'},
            DraggableKeys:["ITEM"],
            DroppableKeys:["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, e, 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;

                    if(profile.onClick)
                        box.onClick(profile,item,e,src);

                    linb.use(src).focus();

                    switch(properties.selMode){
                    case 'none':
                        rt=box.onItemSelected(profile, item, e, src, 0);
                        break;
                    case 'multibycheckbox':
                        if(properties.readonly|| item.readonly)return false;
                        if(profile.keys.MARK){
                            if(profile.getKey(linb.Event.getSrc(e).id||"")!=profile.keys.MARK){
                                rt=box.onItemSelected(profile, item, e, src, 0);
                                rt=false;
                                break;
                            }
                        }
                    case 'multi':
                        if(properties.readonly|| item.readonly)return false;
                        var value = box.getUIValue(),
                            arr = value?value.split(properties.valueSeparator):[],
                            checktype=1;

                        if(arr.length&&(ks.ctrlKey||ks.shiftKey||properties.noCtrlKey||properties.$checkbox)){
                            //for select
                            rt2=false;
                            if(ks.shiftKey){
                                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);
                                    checktype=-1
                                }else
                                    arr.push(item.id);
                            }

                            arr.sort();
                            value = arr.join(properties.valueSeparator);

                            //update string value only for setCtrlValue
                            if(box.getUIValue() == value)
                                rt=false;
                            else{
                                box.setUIValue(value);
                                if(box.get(0) && box.getUIValue() == value)
                                    rt=box.onItemSelected(profile, item, e, src, checktype)||rt2;
                            }
                            break;
                        }
                    case 'single':
                        if(properties.readonly|| item.readonly)return false;

                        if(box.getUIValue() == item.id)
                            rt=false;
                        else{
                            profile.$firstV=item;
                            box.setUIValue(item.id);
                            if(box.get(0) && box.getUIValue() == item.id)
                                rt=box.onItemSelected(profile, item, e, src, 1);
                        }
                        break;
                    }
                    var node=linb.use(src).get(0),href=node&&node.href;
                    node=null;
                    return (!href || href.indexOf('javascript:')==0)?false: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();
                            break;
                    }
                },
                onContextmenu:function(profile, e, src){
                    if(profile.onContextmenu)
                        return profile.boxing().onContextmenu(profile, e, src,profile.getItemByDom(src))!==false;
                }
            }
            
        },
        DataModel:{
            selMode:{
                ini:'single',
                listbox:['single','none','multi','multibycheckbox'],
                action:function(value){
                    this.getSubNode('MARK',true).css('display',(value=='multi'||value=='multibycheckbox')?'':'none');
                }  
            },
            borderType:{
                ini:'flat',
                listbox:['none','flat','inset','outset'],
                action:function(v){
                    var ns=this,
                        p=ns.properties,
                        node=ns.getSubNode('ITEMS'),
                        reg=/^uiborder-/,
                        pretag='linb-uiborder-',
                        root=ns.getRoot();
                    node.removeClass(reg);
                    node.addClass(pretag+v);

                    //force to resize
                    linb.UI.$tryResize(ns,root.get(0).style.width,root.get(0).style.height,true);
                }
            },
            noCtrlKey:true,
            width:120,
            height:150,
            maxHeight:300
        },
        EventHandlers:{
            onClick:function(profile, item, e, src){},
            onDblclick:function(profile, item, e, src){},
            onItemSelected:function(profile, item, e, src, type){}
        },
        _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;
        },
        _prepareData:function(profile){
            var data=arguments.callee.upper.call(this, profile);
            data._bordertype='linb-uiborder-'+data.borderType;
            return data;
        },
        _prepareItem:function(profile, item){
            item._cbDisplay = (profile.properties.selMode=='multi'||profile.properties.selMode=='multibycheckbox')?'':'display:none;';
        },
        _onresize:function(profile,width,height){
            var size=profile.properties.borderType!='none'?2:0;
            if(height)
                profile.getSubNode('ITEMS').height(height=='auto'?height:(height-size));
            if(width)
                profile.getSubNode('ITEMS').width(width=='auto'?width:(width-size));
        }
    }
});
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:{
                    tabindex:'{_tabindex}',
                    className:'{itemClass} {disabled} {readonly}',
                    style:'padding:{itemPadding}px;margin:{itemMargin}px;{itemStyle}',
                    ITEMFRAME:{
                        style:'width:{itemWidth}px;height:{itemHeight}px;',
                        CAPTION:{
                            tagName : 'div',
                            style:'{capDisplay}',
                            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:'visible'
            },
            ITEMS:{
                position:'relative',
                overflow:'auto',
                'overflow-x': 'hidden',
                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'
            },
            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'
            },
            'ITEM-mouseover, ITEM-mousedown, ITEM-checked':{
            },
            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.capition = item.capition || '';
            if(item.caption===null)capDisplay='display:none;';
            item.comment = item.comment || '';
            item._tabindex = p.tabindex;
            //Avoid Empty Image src
            if(!item.image)item.image=linb.ini.img_bg;
        }
    }
});
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:{
                    tabindex:'{_tabindex}',
                    className:'{itemClass} {disabled}  {readonly}',
                    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': 'hidden'
            },
            ITEMS:{
                overflow:'auto',
                'overflow-x': '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'
            },
            'ITEM-mouseover, ITEM-mousedown, ITEM-checked':{
            }
        },
        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;
            //Avoid Empty Image src
            if(!item.image)item.image=linb.ini.img_bg;
        }
    }
});
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;
            }
        },
        resetPanelView:function(destroyChildren){
            if(!_.isSet(destroyChildren))destroyChildren=true;
            var ins;
            return this.each(function(profile){
                if(profile.renderId){
                    delete profile.$ini;
                    ins=profile.boxing();
                    ins.removeChildren(true,destroyChildren)
                    if(profile.properties.toggle)
                        ins.setToggle(false);
                }
            });
        }
    },
    Static:{
        Templates:{
            tagName : 'div',
            style:'{_style}',
            className:'{_className}',
            BORDER:{
                tagName:'div',
                TBAR:{
                    tagName:'div',
                    className:'linb-uibar-top',
                    BART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        height:'100%',
                        border:'0',
                        tagName:'table',
                        className:'linb-uibar-t',
                        BARTR:{
                            tagName:'tr',
                            BARTDL:{
                                tagName:'td',
                                className:'linb-uibar-tdl'
                            },
                            BARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'linb-uibar-tdm'
                            },
                            BARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'linb-uibar-tdr'
                            }
                        }
                    },
                    BARCMDL:{
                        tagName: 'div',
                        className:'linb-uibar-cmdl',
                        TOGGLE:{
                            className: 'linb-uicmd-toggle {toggleCls}',
                            style:'{toggleDisplay}',
                            $order:0
                        },
                        ICON:{
                            $order:0,
                            className:'linb-ui-icon {imageClass}',
                            style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {imageDisplay}'
                        },
                        CAPTION:{
                            tabindex: '{tabindex}',
                            text : '{caption}',
                            $order:1
                        }
                    },
                    BARCMDR:{
                        tagName: 'div',
                        className:'linb-uibar-cmdr',
                        INFO:{
                            className:'linb-uicmd-info',
                            style:'{infoDisplay}',
                            $order:1
                        },
                        OPT:{
                            className:'linb-uicmd-opt',
                            style:'{optDisplay}',
                            $order:1
                        },
                        POP:{
                            className:'linb-uicmd-pop',
                            style:'{popDisplay}',
                            $order:2
                        },
                        REFRESH:{
                            className:'linb-uicmd-refresh',
                            style:'{refreshDisplay}',
                            $order:3
                        },
                        CLOSE:{
                            className:'linb-uicmd-close ',
                            style:'{closeDisplay}',
                            $order:4
                        }
                    }
                },
                MAIN:{
                    $order:2,
                    tagName:'div',
                    className:'linb-uicon-main',
                    MAINI:{
                        tagName:'div',
                        className:'linb-uicon-maini',
                        PANEL:{
                            tagName:'div',
                            className:'{_bordertype}',
                            style:'{panelDisplay};{_overflow};',
                            text:'{html}'+linb.UI.$childTag
                        }
                    }
                },
                BBAR:{
                    $order:3,
                    tagName:'div',
                    className:'linb-uibar-bottom-s',
                    BBART:{
                        cellpadding:"0",
                        cellspacing:"0",
                        width:'100%',
                        border:'0',
                        tagName:'table',
                        className:'linb-uibar-t',
                        BBARTR:{
                            tagName:'tr',
                            BBARTDL:{
                                tagName:'td',
                                className:'linb-uibar-tdl'
                            },
                            BBARTDM:{
                                $order:1,
                                width:'100%',
                                tagName:'td',
                                className:'linb-uibar-tdm'
                            },
                            BBARTDR:{
                                $order:2,
                                tagName:'td',
                                className:'linb-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',
                cursor:'pointer',
                display:'inline',
                'vertical-align':linb.browser.ie6?'baseline':'middle'
            }
        },
        Behaviors:{
            DroppableKeys:['PANEL'],
            PanelKeys:['PANEL'],
            DraggableKeys:['TBAR'],
            NoDraggableKeys:['INFO','OPT','CLOSE','POP','REFRESH','TOGGLE','CAPTION'],
            HoverEffected:{INFO:'INFO',OPT:'OPT', CLOSE:'CLOSE',POP:'POP', REFRESH:'REFRESH',TOGGLE:'TOGGLE'},
            ClickEffected:{INFO:'INFO',OPT:'OPT', CLOSE:'CLOSE',POP:'POP', REFRESH:'REFRESH',TOGGLE:'TOGGLE'},
            onSize:linb.UI.$onSize,
            INFO:{
                onClick:function(profile, e, src){
                    profile.boxing().onShowInfo(profile, e, src);
                }
            },
            OPT:{
                onClick:function(profile, e, src){
                    profile.boxing().onShowOptions(profile, e, src);
                }
            },
            REFRESH:{
                onClick:function(profile, e, src){
                    profile.boxing().onRefresh(profile);
                }
            },
            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).shiftKey;
                }
            },
            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;
                }
            },
            POP:{
                onClick:function(profile, e, src){
                    var properties=profile.properties;
                    if(properties.disabled)return;
                    var pos = profile.getRoot().offset(), size=profile.getRoot().cssSize(),
                        options={parent:null,host:null,properties:null,events:null,CS:null,CC:null,CB:null,CF:null};

                    if(profile.beforePop && false==profile.boxing().beforePop(profile,options))
                        return false;
                        
                    var pro = _.copy(linb.UI.Dialog.$DataStruct),
                        events={};
                    _.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,
                        landBtn:true
                    },'all');
                     if(options.properties)
                        _.merge(pro, options.properties, 'with');

                    if(options.events)
                        _.merge(events, options.events, 'all');
                    if(!events.onRender){
                        var arr=[];
                        _.arr.each(profile.children,function(o){
                            arr.push(o[0]);
                        });
                        if(arr.length)
                            events.onRender=function(){
                                dialog.append(linb.UI.pack(arr,false));
                            };
                    }                    

                    var dialog = new linb.UI.Dialog(pro,events,options.host||profile.host,options.CS||null,options.CC||null,options.CB||null,options.CF||null);
                    
                    (options.parent||linb('body')).append(dialog);

                    profile.boxing().removeChildren().destroy();

                    //for design mode in firefox
                    return false;
                }
            }
        },
        DataModel:{
            selectable:true,
            position:'absolute',
            zIndex:0,
            dock:'fill',
            // setCaption and getCaption
            caption:{
                ini:undefined,
                // ui update function when setCaption
                action: function(v){
                    v=(_.isSet(v)?v:"")+"";
                    this.getSubNode('CAPTION').html(linb.adjustRes(v,true));
                }
            },
            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);
                }
            },
            html:{
                action:function(v){
                    this.getSubNode('PANEL').html(v);
                }
            },
            toggle:{
                ini:true,
                action:function(v){
                    this.box._toggle(this, v);
                }
            },
            infoBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('INFO').css('display',v?'':'none');
                }
            },
            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');
                }
            },
            refreshBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('REFRESH').css('display',v?'':'none');
                }
            },
            popBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('POP').css('display',v?'':'none');
                }
            },
            borderType:{
                ini:'inset',
                listbox:['none','flat','inset','outset'],
                action:function(v){
                    var ns=this,
                        p=ns.properties,
                        node=ns.getSubNode('PANEL'),
                        reg=/^uiborder-/,
                        pretag='linb-uiborder-',
                        root=ns.getRoot();
                    node.removeClass(reg);
                    node.addClass(pretag+v);

                    //force to resize
                    linb.UI.$tryResize(ns,root.get(0).style.width,root.get(0).style.height,true);
                }
            }
        },
        EventHandlers:{
            onRefresh:function(profile){},
            beforePop:function(profile, options){},
            beforeClose:function(profile){},
            onIniPanelView:function(profile){},
            beforeFold:function(profile){},
            beforeExpend:function(profile){},
            afterFold:function(profile){},
            afterExpend:function(profile){},
            onShowInfo:function(profile, e, src){},
            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?'linb-uicmd-toggle-checked':'';

            data.toggleDisplay = data.toggleBtn?'':nodisplay;
            data.infoDisplay = data.infoBtn?'':nodisplay;
            data.optDisplay = data.optBtn?'':nodisplay;
            data.closeDisplay = data.closeBtn?'':nodisplay;
            data.popDisplay = data.popBtn?'':nodisplay;
            data.refreshDisplay= data.refreshBtn?'':nodisplay;
            
            data._bordertype='linb-uiborder-'+data.borderType;
            
            profile._toggle = !!data.toggle;

            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'),
                size=profile.properties.borderType=='none'?0:2,
                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-size;
                }
            }
            if(width)
                isize.width=width-(parseInt(v6.css('paddingRight'))||0)-(parseInt(v5.css('paddingLeft'))||0)-v2._borderW();
            v2.cssSize(isize, true);
        },

        _toggle:function(profile, value){
            var p=profile.properties, ins=profile.boxing();

            //event
            if(value &&!profile.$ini){
                if(ins.onIniPanelView){
                    if(ins.onIniPanelView(profile)!==false){
                        profile.$ini=true;
                    }
                    
                    if(p.iframeAutoLoad||p.ajaxAutoLoad)
                        linb.UI.Div._applyAutoLoad(profile);
                }
            }

            if(profile._toggle !== !!value){
                //set toggle mark
                profile._toggle = p.toggle = !!value;

                if(value){
                    if(ins.beforeExpend && false===ins.beforeExpend(profile))return;
                }else{
                    if(ins.beforeFold && false===ins.beforeFold(profile))return;
                }

                //show/hide/panel
                profile.getSubNode('PANEL').css('display',value?'':'none');
                //chang toggle button
                if(p.toggleBtn)
                    profile.getSubNode('TOGGLE').tagClass('-checked', !!value);

                var h=profile.getSubNode('BORDER').height();
                // display => adjust ctrl's height to border's
                // display-none => adjust ctrl's height to p.height(expand) or 'auto'(fold)
                profile.getRoot().height(h?h:p.toggle?p.height:'auto');

                if(value){
                    if(ins.afterExpend)
                        ins.afterExpend(profile);
                }else{
                    if(ins.afterFold)
                        ins.afterFold(profile);
                }
            }
        }
    }
});
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,k){
                        if(i)n.first(3).attr('href',prop.uriTpl.replace('*',i));
                        if(_.isSet(j))
                            n.first(3).html(prop.textTpl.replace('*',j),false);
                        
                        if(_.isSet(k))
                            n.get(0)._real_page=k;
                    },
                    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) , 1);
                change(prev, cur-1, prop.prevMark);
                change(current, cur, cur);
                change(next, cur+1, prop.nextMark);
                change(nexthide, '','..' + _.str.repeat('.',String(max-cur-1).length) , 1);
                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);
                    change(prev, cur-1, cur-1);
                }else{
                    display(first,1);display(prehide,1);display(prev,1);
                    if(t==3){
                        change(prev, cur-1, cur-1);
                        change(prehide, cur-2, cur-2, 0);
                    }
                }
                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);
                    change(next, cur+1, cur+1);
                }else{
                    display(last,1);display(nexthide,1);display(next,1);
                    if(t==3){
                        change(next, cur+1, cur+1);
                        change(nexthide, cur+2, cur+2, 0);
                    }
                }
            });
        },
        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}',
            className:'{_className}',
            POOL:{
                style:'position:absolute;display:none;',
                POP:{
                    tagName:'div',
                    className:'linb-uibg-base'
                }
            },
            LABEL:{
                text:'{caption}'
            },
            FIRST:{
                $order:1,
                className:'linb-ui-btn',
                FIRSTI:{
                    className:'linb-ui-btni',
                    FIRSTC:{
                        className:'linb-ui-btnc',
                        FIRSTA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}'
                        }
                    }
                }
            },
            PREM:{
                $order:2,
                className:'linb-ui-btn',
                PREMI:{
                    className:'linb-ui-btni',
                    PREMC:{
                        className:'linb-ui-btnc',
                        PREMA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}'
                        }
                    }
                }
            },
            PREV:{
                $order:3,
                className:'linb-ui-btn',
                PREVI:{
                    className:'linb-ui-btni',
                    PREVC:{
                        className:'linb-ui-btnc',
                        PREVA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}',
                            text:'{prevMark}'
                        }
                    }
                }
            },
            CUR:{
                $order:4,
                className:'linb-ui-btn linb-ui-btn-focus',
                CURI:{
                    className:'linb-ui-btni',
                    CURC:{
                        className:'linb-ui-btnc',
                        CURA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}'
                        }
                    }
                }
            },
            NEXT:{
                $order:5,
                className:'linb-ui-btn',
                NEXTI:{
                    className:'linb-ui-btni',
                    NEXTC:{
                        className:'linb-ui-btnc',
                        NEXTA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}',
                            text:'{nextMark}'
                        }
                    }
                }
            },
            NEXTM:{
                $order:6,
                className:'linb-ui-btn',
                NEXTMI:{
                    className:'linb-ui-btni',
                    NEXTMC:{
                        className:'linb-ui-btnc',
                        NEXTMA:{
                            tagName:'a',
                            href:'#',
                            tabindex: '{tabindex}'
                        }
                    }
                }
            },
            LAST:{
                $order:7,
                className:'linb-ui-btn',
                LASTI:{
                    className:'linb-ui-btni',
                    LASTC:{
                        className:'linb-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':{
                'outline-offset':'',
                '-moz-outline-offset': (linb.browser.gek && parseInt(linb.browser.ver)<3)?'':null
            },
            'KEY .linb-ui-btn, POP .linb-ui-btn':{
                'margin-right':'3px'
            },
            'KEY .linb-ui-btn a, POP .linb-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, src){
                    if(linb.use(src).get(0)._real_page){
                        profile.box._show(profile,e,src,0);
                        return false;
                    }else{
                        return profile.box._click(profile,src);
                    }
                }
            },
            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, src){
                    if(linb.use(src).get(0)._real_page){
                        profile.box._show(profile,e,src,1);
                        return false;
                    }else{
                        return profile.box._click(profile,src);
                    }
                }
            },
            LAST:{
                onClick:function(profile, e, src){
                    return profile.box._click(profile,src);
                }
            }
        },
        DataModel:{
            dataField:null,
            dataBinder:null,

            caption:{
                ini:' Page: ',
                action:function(v){
                    v=(_.isSet(v)?v:"")+"";
                    this.getSubNode('LABEL').html(linb.adjustRes(v,true));
                }
            },
            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="linb-node linb-node-span linb-ui-btn"><span class="linb-node linb-node-span linb-ui-btni"><span class="linb-node linb-node-span linb-ui-btnc"><a class="linb-node linb-node-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(),
                    prop = profile.properties,
                    dm=profile.box.$DataModel,

                    fold=function(itemId, arr){
                        var subId = profile.getSubIdByItemId(itemId),
                            item = profile.getItemByItemId(itemId);
                        if(subId){
                            arr.push(subId);
                            
                            if(!dm.hasOwnProperty("noPanel") || !prop.noPanel){
                                // hide pane
                                //box.getPanel(itemId).hide();
                                var pn=box.getPanel(itemId).get(0);
                                if(pn && (item._scrollTop=pn.scrollTop||0))
                                    pn.scrollTop=0;

                                box.getPanel(itemId).css('display','none');
                            }
                        }
                    },
                    expand = function(itemId, arr){
                        var subId = profile.getSubIdByItemId(itemId),
                            item=profile.getItemByItemId(itemId);
                        if(subId){
                            arr.push(subId);

                            if(!dm.hasOwnProperty("noPanel") || !prop.noPanel){
                                // show pane
                                //box.getPanel(value).css('position','relative').show('auto','auto');
                                box.getPanel(itemId).css('display','block');
                                if(item._scrollTop)
                                    box.getPanel(itemId).get(0).scrollTop=item._scrollTop;

                                var t=profile.getRootNode().style;
                                //reset width and height
                                linb.UI.$tryResize(profile, t.width, t.height, true, value);
                                t=null;

                                profile.box._forLazzyAppend(profile, item, value);
                                profile.box._forIniPanelView(profile, item, value);
                            }
                        }
                    };
                var arr1=[],arr2=[];
                if(dm.hasOwnProperty("selMode") &&
                    dm.hasOwnProperty("noPanel") &&
                    prop.noPanel &&
                    prop.selMode=="multi"){

                    uiv = uiv?uiv.split(prop.valueSeparator):[];
                    _.arr.each(uiv,function(key){
                        fold(key, arr1);
                    });
                    value = value?value.split(prop.valueSeparator):[];
                    var lastV="";
                    _.arr.each(value,function(key){
                        var l=arr2.length;
                        expand(key, arr2);
                        // the last one
                        if(l<arr2.length)
                            lastV=key;
                    });

                    if(lastV)
                        _.tryF(profile.box._adjustScroll,[profile,lastV],profile.box);
                }else{
                    fold(uiv, arr1);
                    expand(value, arr2);
                    
                    if(arr2.length)
                        _.tryF(profile.box._adjustScroll,[profile,value],profile.box);
                }

                if(arr1.length)
                    profile.getSubNodes('ITEM',arr1).tagClass('-checked',false);
                if(arr2.length){
                    profile.getSubNodes('ITEM',arr2).tagClass('-checked');
                }

            });
        },
        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),
                dm=profile.box.$DataModel,
                v=profile.properties.$UIvalue;
            if(dm.hasOwnProperty("noPanel") && dm.hasOwnProperty("selMode") && profile.properties.selMode=='multi'){
                v=v.split(prop.valueSeparator);
                v=v[0]||null;
            }
            return v?this.getPanel(v):null;
        },
        // 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,
                popBtn:para.popBtn || 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)){
                // add panels anyway
                obj.append(profile._buildItems('panels', data));
                // for stacks only
                if(!profile.box.$DataModel.hasOwnProperty("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.box.$DataModel.hasOwnProperty("noPanel") || !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.box.$DataModel.hasOwnProperty("noPanel") || !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.box.$DataModel.hasOwnProperty("noPanel") || !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;
        },
        _scrollToBottom:function(){
            return this.each(function(profile){
                var o = profile.getSubNode('ITEMS'),
                border = profile.getSubNode('LIST'),
                y = o.left(),
                offset,
                h = o.width(),
                b=false,
                bh = border.width();
                if(bh<h+y){
                    if(!profile.$scrollStep)profile.$scrollStep=1;

                    if(profile.$scrollStep<5)
                        profile.$scrollStep = profile.$scrollStep*1.01;

                    y -= profile.$scrollStep;
                    if(bh>h+y){
                        y=bh-h;
                        b=true;
                    }
                    o.left(y);
                    if(b){
                        profile.getSubNode('RIGHT').css('display','none');
                        profile.$scrollTobottom=false;
                        profile.$scrollStep=null;
                    }else{
                        profile.getSubNode('LEFT').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.left(),
                b=false;

                if(y<0){
                    if(!profile.$scrollStep)profile.$scrollStep=1;

                    if(profile.$scrollStep<5)
                        profile.$scrollStep = profile.$scrollStep*1.01;

                    y += profile.$scrollStep;
                    if(y>=-1){
                        y=0;
                        b=true;
                    }
                    o.left(y);
                    if(b){
                        profile.getSubNode('LEFT').css('display','none');
                        profile.$scrollToTop=false;
                        profile.$scrollStep=null;
                    }else{
                        profile.getSubNode('RIGHT').css('display','block');
                        if(profile.$scrollToTop)
                            _.asyRun(arguments.callee, 0, [profile], this);
                    }
                }
            });
        }
    },
    Static:{
        Templates:{
            tagName : 'div',
            style:'{_style};',
            className:'{_className}',
            LIST:{
                $order:0,
                tagName : 'div',
                ITEMS:{
                    tagName : 'div',
                    text:"{items}",
                    style:'{HAlign}'
                },
                LEFT:{},
                RIGHT:{}
            },
            PNAELS:{
                $order:1,
                tagName:'text',
                text:'{panels}'
            },
            $submap:{
                items:{
                    ITEM:{
                        className:'{itemClass} {disabled} {readonly}',
                        style:'{itemDisplay} {itemStyle}',
                        ITEMI:{
                            ITEMC:{
                                HANDLE:{
                                    tabindex: '{_tabindex}',
                                    IBWRAP:{
                                        tagName:'div',
                                        style:"white-space:nowrap;",
                                        RULER:{},
                                        ICON:{
                                            $order:0,
                                            className:'linb-ui-icon {imageClass}',
                                            style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {imageDisplay}'
                                        },
                                        CAPTION:{
                                            text: '{caption}',
                                            $order:1
                                        },
                                        CMDS:{
                                            $order:2,
                                            OPT:{
                                                $order:1,
                                                className:'linb-uicmd-opt',
                                                style:'{_opt}'
                                            },
                                            POP:{
                                                className:'linb-uicmd-pop',
                                                style:'{popDisplay}',
                                                $order:1
                                            },
                                            CLOSE:{
                                                className:'linb-uicmd-close ',
                                                style:'{closeDisplay}',
                                                $order:2
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                },
                panels:{
                    PANEL:{
                        tagName : 'div',
                        className:'linb-uibg-base',
                        style:"{_overflow};",
                        text:'{html}'+linb.UI.$childTag
                    }
                }
            }
        },
        Appearances:{
            KEY:{
                position:'absolute',
                overflow:'hidden'
            },
            LIST:{
                position:'relative',
                overflow:'hidden',
                left:0,
                width:'100%',
                background: linb.UI.$bg('line.gif', 'repeat-x center bottom')
            },
            LEFT:{
                cursor:'pointer',
                display:'none',
                position:'absolute',
                top:0,
                left:0,
                height:'16px',
                width:'16px',
                'z-index':'10',
                background: linb.UI.$bg('icons.gif', 'no-repeat -152px -244px', true)
            },
            RIGHT:{
                cursor:'pointer',
                display:'none',
                position:'absolute',
                top:0,
                right:0,
                height:'16px',
                width:'16px',
                'z-index':'10',
                background: linb.UI.$bg('icons.gif', 'no-repeat -170px -244px', true)
            },
            ITEMS:{
                padding:'0 4px 2px 0',
                position:'relative',
                left:0,
                top:0,
                'white-space':'nowrap'
            },
            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':linb.browser.ie6?'baseline':'middle',
                margin:'0 4px'
            },
            CMDS:{
                'vertical-align':'middle'
            }
        },
        Behaviors:{
            DroppableKeys:['PANEL','KEY', 'ITEM'],
            PanelKeys:['PANEL'],
            DraggableKeys:['ITEM'],
            HoverEffected:{ITEM:'ITEM',OPT:'OPT',CLOSE:'CLOSE',POP:'POP'},
            ClickEffected:{ITEM:'ITEM',OPT:'OPT',CLOSE:'CLOSE',POP:'POP'},
            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(properties.readonly || item.readonly)return false;
                    if(box.getUIValue() == item.id){
                         if(profile.onCaptionActive)
                            profile.boxing().onCaptionActive(profile, profile.getItemByDom(src), e, 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 prop = profile.properties,
                        dm=profile.box.$DataModel,
                        itemId = profile.getSubId(src),
                        item = profile.getItemByDom(src),
                        box = profile.boxing();

                    if(prop.disabled || item.disabled)return false;
                    if(prop.readonly || item.readonly)return false;

                    //for some input onblur event
                    profile.getSubNode('HANDLE', itemId).focus();

                    if(dm.hasOwnProperty("selMode") &&
                        dm.hasOwnProperty("noPanel") &&
                        prop.noPanel &&
                        prop.selMode=="multi"){

                        var value = box.getUIValue(),
                            arr = value?value.split(prop.valueSeparator):[],
                            checktype=1,
                            rt=false,
                            rt2=false;
                        // for multi selection
                        if(arr.length){
                            //for select
                            if(_.arr.indexOf(arr,item.id)!=-1){
                                _.arr.removeValue(arr,item.id);
                                checktype=-1
                            }else
                                arr.push(item.id);

                            arr.sort();
                            value = arr.join(prop.valueSeparator);

                            //update string value only for setCtrlValue
                            if(box.getUIValue() == value)
                                rt=false;
                            else{
                                box.setUIValue(value);
                                if(box.get(0) && box.getUIValue() == value)
                                    rt=box.onItemSelected(profile, item, e, src, checktype)||rt2;
                            }
                            return rt;
                        }

                    }
                    // for single selection
                    if(box.getUIValue() != item.id){
                        box.setUIValue(item.id);
                        //if success
                        if(box.getUIValue() == item.id){
                            box.onItemSelected(profile, item, e, src);
                            return false;
                        }
                    }
                }
            },
            HANDLE:{
                onClick:function(profile, e, src){
                    return linb.Event.getKey(e).shiftKey;
                },
                onKeydown:function(profile, e, src){
                    var keys=linb.Event.getKey(e), key = keys.key, shift=keys.shiftKey;
                    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),
                        uiv=properties.$UIvalue,
                        bak;

                    if(properties.disabled || item.disabled)return;
                    if(properties.readonly || item.readonly)return false;
                    var instance = profile.boxing();

                    if(false===instance.beforePageClose(profile, item, src)) return;

                    bak=_.copy(item);

                    // if the current item is selected, select the next or the pre one item
                    if(uiv && uiv==item.id){
                        var items=properties.items,
                        index=_.arr.subIndexOf(items,"id",item.id),
                        t,
                        nuiv=(t=items[index+1])?t.id:(t=items[index-1])?t.id:(t=items[0])?t.id:null;
                        if(nuiv && nuiv!=uiv){
                            profile.boxing().fireItemClickEvent(nuiv);
                        }
                    }

                    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;
                }
            },
            POP:{
                onMousedown:function(){
                    return false;
                },
                onClick:function(profile, e, src){
                    var properties = profile.properties,
                        item = profile.getItemByDom(src),
                        options={parent:null,host:null,properties:null,events:null,CS:null,CC:null,CB:null,CF:null},
                        id=item.id;

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

                    if(profile.beforePagePop && false==profile.boxing().beforePagePop(profile,item,options))
                        return false;

                    var panel = profile.boxing().getPanel(id),
                        pos = profile.getRoot().offset(),
                        size=profile.getRoot().cssSize(),
                        pro = _.copy(linb.UI.Dialog.$DataStruct),
                        events={};
                    
                    _.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,
                        landBtn:true
                    },'all');
                    if(options.properties)
                        _.merge(pro, options.properties, 'with');
                    
                    if(options.events)
                        _.merge(events, options.events, 'all');
                    if(!events.onRender){
                        var arr=[];
                        _.arr.each(profile.children,function(o){
                            if(o[1]==id){
                                // removed the lazy render flag
                                delete o[0]['parent:'+profile.$linbid];
                                arr.push(o[0]);
                            }
                        });
                        if(arr.length)
                            events.onRender=function(){
                                dialog.append(linb.UI.pack(arr,false));
                            };
                    }
                    var dialog = new linb.UI.Dialog(pro,events,options.host||profile.host,options.CS||null,options.CC||null,options.CB||null,options.CF||null);
                    (options.parent||linb('body')).append(dialog);

                    profile.boxing().removeChildren(id).removeItems(id);

                    //for design mode in firefox
                    return false;
                }
            },
            ITEMS:{
                onMousedown:function(profile, e, src){
                    var ep=linb.Event.getPos(e);
                    if(!profile._$scroll_l && !profile._$scroll_r)return;
                    linb.use(src).startDrag(e, {
                        horizontalOnly:true,
                        dragType:'blank',
                        dragDefer:2,
                        targetLeft:ep.left,
                        targetTop:ep.top,
                        targetReposition:false,
                        maxLeftOffset:profile._$scroll_l,
                        maxRightOffset:profile._$scroll_r
                    });
                },
                onDrag:function(profile, e, src){
                    var dd=linb.DragDrop.getProfile();
                    linb.use(src).left(-profile._$scroll_r + dd.offset.x);
                },
                onDragstop:function(profile, e, src){
                    profile.box._adjustScroll(profile);
                }
            },
            LEFT:{
                onMouseover:function(profile, e, src){
                    profile.$scrollToTop=true;
                    profile.boxing()._scrollToTop();
                },
                onMouseout:function(profile, e, src){
                    profile.$scrollToTop=false;
                    profile.$scrollStep=null;
                },
                onClick:function(profile, e, src){
                    profile.$scrollStep*=2;
                }
            },
            RIGHT:{
                onMouseover:function(profile, e, src){
                    profile.$scrollTobottom=true;
                    profile.boxing()._scrollToBottom();
                },
                onMouseout:function(profile, e, src){
                    profile.$scrollTobottom=false;
                    profile.$scrollStep=null;
                },
                onClick:function(profile, e, src){
                    profile.$scrollStep*=2;
                }
            }
        },
        DataModel:{
            selectable:true,
            dirtyMark:false,

            dataBinder:null,
            dataField:null,

            lazyAppend:true,

            dock:'fill',
            noPanel:false,
            width:200,
            height:200,
            position:'absolute',
            overflow:{
                ini:undefined,
                action:function(v){
                    this.getSubNode('PANEL',true).css('overflow',v||'');
                }
            },
            HAlign:{
                ini:'left',
                listbox:['left','center','right'],
                action:function(value){
                    this.getSubNode('ITEMS').css('textAlign',value);
                }
            },
            dropKeysPanel:'',
            value:{
                ini:''
            },
            selMode:{
                ini:'single',
                listbox:['single', 'multi']
            },
            //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){},
            beforePagePop:function(profile, item, options){},
            beforePageClose:function(profile, item, src){},
            afterPageClose:function(profile, item){},
            onShowOptions:function(profile,item,e,src){},
            onItemSelected:function(profile, item,e,src,type){},
            onCaptionActive:function(profile, item,e,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;
            if(data.HAlign)
                data.HAlign = 'text-align:'+data.HAlign+';';
            return data;
        },
        _prepareItem:function(profile, item){
            var dpn = 'display:none',prop=profile.properties;
            item.closeDisplay = item.closeBtn?'':dpn;
            item.popDisplay = item.popBtn?'':dpn;
            item._opt = item.optBtn?'':dpn;
            item.itemDisplay = item.hidden?dpn:'';

            if(_.isStr(item.overflow))
                item._overflow = item.overflow.indexOf(':')!=-1?(item.overflow):("overflow:"+item.overflow);
            else if(_.isStr(prop.overflow))
                item._overflow = prop.overflow.indexOf(':')!=-1?(prop.overflow):("overflow:"+prop.overflow);
        },
        getDropKeys:function(profile,node){
            return profile.properties[profile.getKey(linb.use(node).id())==profile.keys.PANEL?'dropKeys':'dropKeysPanel'];
        },
        _forLazzyAppend:function(profile, item, value){
            var prop=profile.properties,box=profile.boxing();
            //dynamic render
            if(prop.lazyAppend){
                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);

                // $attached is dynamic
                if(profile.$attached){
                    for(var i=0,v;v=profile.$attached[i++];)
                        if(v._render)
                            v._render(true);
                    delete profile.$attached;
                }

                arr=profile.exchildren;
                if(arr && arr.length){
                    a=[];
                    _.filter(arr,function(o){
                        if(o[1]==value){
                            a.push(o[0]);
                            return false;
                        }
                    });
                    if(a.length)
                        _.arr.each(a,function(o){
                            box.append(linb(o),value);
                        });
                }

                arr=profile.excoms;
                if(arr && arr.length){
                    a=[];
                    _.filter(arr,function(o){
                        if(o[1]==value){
                            a.push(o[0]);
                            return false;
                        }
                    });
                    if(a.length)
                        _.arr.each(a,function(o){
                            o.show(null, box, value, false);
                        });
                }
            }
        },
        _forIniPanelView:function(profile, item, value){
            var prop=profile.properties,box=profile.boxing();
            if(!item._$ini){
                if(box.onIniPanelView(profile,item)!==false)
                    item._$ini=true;
                if(item.iframeAutoLoad){
                    box.getPanel(item.id).css('overflow','hidden');

                    if(typeof item.iframeAutoLoad=='string')
                        item.iframeAutoLoad={url:item.iframeAutoLoad};
                    var hash=item.iframeAutoLoad,
                        id="diframe_"+_(),
                        e=linb.browser.ie && parseInt(linb.browser.ver)<9,
                        ifr=document.createElement(e?"<iframe name='"+id+"'>":"iframe");
                    item.iframeAutoLoad.frameName=ifr.id=ifr.name=id;
                    if(!hash.query)hash.query={};
                    hash.query._rand=_();
                    ifr.src=hash.url;
                    ifr.frameBorder='0';
                    ifr.marginWidth='0';
                    ifr.marginHeight='0';
                    ifr.vspace='0';
                    ifr.hspace='0';
                    ifr.allowTransparency='true';
                    ifr.width='100%';
                    ifr.height='100%';
                    box.getPanel(item.id).html("").append(ifr);
                    linb.Dom.submit(hash.url, hash.query, hash.method, id, hash.enctype);
                }else if(item.ajaxAutoLoad){
                    if(typeof item.ajaxAutoLoad=='string')
                        item.ajaxAutoLoad={url:item.ajaxAutoLoad};
                    var hash=item.ajaxAutoLoad,options={rspType:"text"};
                    _.merge(options, hash.options);
                    if(!hash.query)hash.query={};
                    hash.query._rand=_();
                    box.busy(null,null,"PANEL",profile.getSubIdByItemId(item.id));
                    linb.Ajax(hash.url, hash.query, function(rsp){
                        var n=linb.create("div");
                        n.html(rsp,false,true);
                        box.getPanel(item.id).html("").append(n.children());
                        box.free();
                    }, function(err){
                        box.getPanel(item.id).html("").append("<div>"+err+"</div>");
                        box.free();
                    }, null, options).start();
                }
            }
        },
        _showTips:function(profile, node, pos){
            if(profile.properties.disableTips)return;
            if(profile.onShowTips)
                return profile.boxing().onShowTips(profile, node, pos);
            if(!linb.Tips)return;

            if(!node.id)return false;
            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'),
                listH;
            ;
            if(!o || o.isEmpty())return;

            var hc=null,wc=null;
            if(force)item._w=item._h=null;
            if(height && item._h!=height){
                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;
                    if(height>0)hc=height;
                }else hc=height;
            }

            if(width && item._w!=width){
                l.width(item._w=width);
                this._adjustScroll(profile);
                wc=width;
            }
            if(hc||wc)o.height(hc).onSize();
        },

        _adjustScroll:function(profile, itemid){
            // SCROLL
            var list = profile.getSubNode('LIST'),
                w=list.offsetWidth(),
                items = profile.getSubNode('ITEMS'),
                l=items.left(),
                left =  profile.getSubNode('LEFT'),
                right =  profile.getSubNode('RIGHT'),
                wi=0,
                sl=0,sw=0;
            items.children().each(function(item){
                // to show the seleted one
                if(itemid && profile.getItemIdByDom(item.id) == itemid){
                    sl=wi;
                    sw=item.offsetWidth;
                }
                wi += item.offsetWidth;
            });
            items.width(Math.max(wi,w));

            if(wi<=w){
                items.left(0);
                profile._$scroll_r=profile._$scroll_l=0;
                items.css('cursor','');
            }else{
                // to show the seleted one
                if(sw){
                    if((sl+l<0) || (sl+sw-l>w)){
                        l=-sl;
                    }
                }

                if(wi+l<w){
                    items.left(w-wi);
                    profile._$scroll_r = wi-w;
                    profile._$scroll_l = 0;
                }else{
                    items.left(l);
                    profile._$scroll_r = -l;
                    profile._$scroll_l =  wi - w + l;
                }
                items.css('cursor','move');
            }


            left.css('display', profile._$scroll_r ? 'block' : 'none');
            right.css('display', profile._$scroll_l ? 'block' : 'none');

        }
    }
});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;
        delete t.LEFT;
        delete t.TOP;
        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
            },
            // to cover Tab's setting, must use ITEMC/ITEMI separately
            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,
            selMode: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);
        },
        _adjustScroll:null
    }
});
Class("linb.UI.ButtonViews", "linb.UI.Tabs",{
    Initialize:function(){
        var t = this.getTemplate();
        t.LIST.className='linb-uibg-bar linb-uiborder-outset';
        delete t.LEFT;
        delete t.TOP;
        this.setTemplate(t);
    },
    Static:{
        Appearances:{
            LIST:{
                'z-index':'2',
                position:'absolute'
            },
            ITEMS:{
                'z-index':'2',
                position:'absolute',
                left:0,
                top:0
            },
            'ITEMS-left, ITEMS-left ITEMC':{
                $order:1,
                'text-align': 'left'
            },
            'ITEMS-center, ITEMS-center ITEMC':{
                $order:1,
                'text-align': 'center'
            },
            'ITEMS-right, ITEMS-right ITEMC':{
                $order:1,
                'text-align': 'right'
            },
            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',
                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',
                height:'20px',
                padding:'2px 0',
                background: linb.UI.$bg('button.gif', 'repeat-x left -300px', true)
            },
            'ITEMS-block ITEM, ITEMS-block ITEMI, ITEMS-block ITEMC':{
                $order:2,
                display:'block'
            }, 
            'ITEM-mouseover ITEMC':{
                $order:1,
                'background-position' : 'left -390px'
            },
            'ITEM-mousedown ITEMC, ITEM-checked ITEMC':{
                $order:2,
                'background-position' : 'left -480px'
            },
            HANDLE:{
                display:linb.$inlineBlock,
                zoom:linb.browser.ie6?1:null,
                cursor:'pointer',
                'vertical-align':'middle',
                'font-size':'12px',
                margin:'1px'
            }
        },
        DataModel:{
            HAlign:null,
            barLocation:{
                ini:'top',
                listbox:['top','bottom','left','right'],
                action:function(v){
                    var self=this,
                        hs = self.getSubNode('LIST'),
                        h = self.getSubNode('ITEMS');
                    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.tagClass('-block',true);
                            break;
                        case 'top':
                        case 'bottom':
                            h.tagClass('-block',false);
                            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.tagClass('(-left|-right|-center)',false).tagClass('-'+v, true);
                }
            },
            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,
                        noPanel=t.noPanel,
                        hs = self.getSubNode('LIST'),
                        hl = self.getSubNode('ITEMS');
                    if(t.barLocation=='left'||t.barLocation=='right'){
                        if(!noPanel)
                            hs.merge(hl).width(v);
                    }else{
                        if(!noPanel)
                            hs.height(v);
                    }
                    var t=self.getRootNode().style;
                    linb.UI.$tryResize(self,t.width, t.height,true);
                }
            },
            noPanel:{
                ini:false,
                action:function(v){
                    this.boxing().setBarSize(this.properties.barSize,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,
                noPanel=t.noPanel,
                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,itmsH;

            if(t.barLocation=='top'||t.barLocation=='bottom'){
                if(width){
                    hs.width(width-2);
                    hl.width(width-2);
                    // for nopanel:
                    if(noPanel)
                        hs.height(height-2);
                 
                    left = 0;
                    wc=width;
                }

                hs.height(itmsH = hl.offsetHeight());
                if(height-itmsH>0)hc=height-itmsH-2;
                top = t.barLocation=='top'?2- -itmsH:0;
            }else{
                if(height){
                    // for nopanel:
                    if(noPanel){
                        hs.width(width-2);
                        hl.width(width-2);
                    }
                    hs.height(height-2);

                    top=0;
                    hc=height;
                }
                if(width){
                    left = t.barLocation=='left'?2- -t.barSize:0;
                    wc=width-t.barSize-2;
                }
            }

            if(!noPanel)
                if(o && !o.isEmpty())o.cssRegion({width:wc?wc:null,height:hc?hc:null,left:left,top:top},true);
        },
        _adjustScroll:null
    }
});Class("linb.UI.RadioBox", "linb.UI.List",{
    Initialize:function(){
        //modify default template for shell
        var t = this.getTemplate();
        t.className=t.ITEMS.className='';
        t.$submap={
            items:{
                ITEM:{
                    className:'{itemClass}  {disabled} {readonly}',
                    style:'{itemStyle}',
                    tabindex: '{_tabindex}',
                    MARK:{
                        $order:0,
                        className:'{_markcls}'
                    },
                    ICON:{
                        $order:1,
                        className:'linb-ui-icon {imageClass}',
                        style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {imageDisplay}'
                    },
                    CAPTION:{
                        text : '{caption}',
                        $order:2
                    }
                }
            }
        };
        this.setTemplate(t);
    },
    Static:{
        _DIRTYKEY:'MARK',
        Appearances:{
            ITEM:{
               display:linb.$inlineBlock,
               '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':linb.browser.ie6?'baseline':'middle'
            },
            ITEMS:{
                overflow:'auto',
                'overflow-x': 'hidden',
                position:'relative',
                'line-height':'14px'
            },
            MARK:{
               $order:1,
               cursor:'pointer',
               width:'16px',
               height:'16px',
               'vertical-align':'middle'
            },
            'ITEM-checked MARK':{
                $order:2
            }
        },
        DataModel:{
            checkBox:{
                ini:false,
                action:function(v){
                    this.getSubNode('MARK',true).replaceClass(v ? /(uicmd-radio)|(\s+uicmd-radio)/g : /(^uicmd-check)|(\s+uicmd-check)/g , v ? ' linb-uicmd-check' : ' linb-uicmd-radio');
                }
            }
        },
        Behaviors:{
            HoverEffected:{ITEM:null,MARK:'MARK'},
            ClickEffected:{ITEM:null,MARK:'MARK'}
        },
        _prepareItem:function(profile, item){
            item._markcls = profile.properties.checkBox?'linb-uicmd-check':'linb-uicmd-radio';
        }
    }
});
Class("linb.UI.StatusButtons", ["linb.UI.List"],{
    Initialize:function(){
        //modify default template fro shell
        var t = this.getTemplate();
        t.className='{_className}';
        t.$submap={
            items:{
                ITEM:{
                    className:'{itemClass} {_endsClass} {disabled} {readonly}',
                    style:'{itemMargin};{itemWidth};{itemAlign};{itemStyle}',
                    tabindex: '{_tabindex}',
                    CAPTION:{
                        $order:1,
                        text:'{caption}'
                    }
                }
            }
        };
        this.setTemplate(t);
    },
    Static:{
        Appearances:{
            ITEMS:{
                position:'relative',
                overflow:'auto',
                'overflow-x': 'hidden'
            },
            ITEM:{
                'vertical-align':'middle',
                position:'relative',
                height:'16px',
                padding:'3px',
                'font-size':0,
                'line-height':0,
                'white-space':'nowrap'
            },
            "ITEM-none":{
                background: linb.UI.$bg('icons.gif', 'no-repeat -12px -130px', true),
                'border-left':'solid 1px #7C9CBC',
                'border-right':'solid 1px #7C9CBC'
            },
            "ITEM-left":{
                background: linb.UI.$bg('icons.gif', 'no-repeat left -130px', true),
                'border-right':'solid 1px #7C9CBC'
            },
            "ITEM-right":{
                background: linb.UI.$bg('icons.gif', 'no-repeat right -130px', true),
                'border-left':'solid 1px #7C9CBC'
            },
            // ignore linb.UI.List setting
            'ITEM-mouseover, ITEM-mousedown, ITEM-checked':{
            },
            'ITEM-mouseover':{},
            'ITEM-mousedown':{},
            'ITEM-checked':{},
            
            'ITEM-left-mouseover':{
                $order:1,
                'background-position': 'left -153px'
            },
            'ITEM-left-mousedown':{
                $order:2,
                'background-position': 'left -176px'
            },
            'ITEM-left-checked':{
                $order:3,
                'background-position': 'left -176px'
            },
            'ITEM-none-mouseover':{
                $order:1,
                'background-position': '-20px -153px'
            },
            'ITEM-none-mousedown':{
                $order:2,
                'background-position': '-20px -176px'
            },
            'ITEM-none-checked':{
                $order:3,
                'background-position': '-20px -176px'
            },
            'ITEM-right-mouseover':{
                $order:1,
                'background-position': 'right -153px'
            },
            'ITEM-right-mousedown':{
                $order:2,
                'background-position': 'right -176px'
            },
            'ITEM-right-checked':{
                $order:3,
                'background-position': 'right -176px'
            },
            CAPTION:{
                display:linb.$inlineBlock,
                zoom:linb.browser.ie6?1:null,
                'vertical-align':'middle',
                'font-size':'12px',
                'line-height':'14px'
            },
            "ITEM-none CAPTION":{
                padding:'1px 4px'
            },
            "ITEM-left CAPTION":{
                padding:'1px 4px 1px 12px'
            },
            "ITEM-right CAPTION":{
                padding:'1px 12px 1px 1px'
            }
        },
        DataModel:({
            maxHeight:null,
            
            itemMargin:{
                ini:"",
                action:function(value){
                    this.getSubNode('ITEM',true).css('margin',value);
                }
            },
            itemWidth:{
                ini:0,
                action:function(value){
                    this.getSubNode('ITEM',true).width(value);
                }
            },
            itemAlign:{
                ini:"",
                listbox:['','left','center','right'],
                action:function(value){
                    this.getSubNode('ITEM',true).css('text-align',value);
                }
            },
            itemLinker:{
                ini:'left',
                listbox:['none','left','right'],
                action:function(value){
                    this.getSubNode('ITEM',true)
                    .tagClass('-none', false)
                    .tagClass('-left', false)
                    .tagClass('-right', false)
                    .tagClass('-'+value, true);
                }
            }
        }),
        Behaviors:{
            DroppableKeys:["ITEMS"]
        },
        EventHandlers:{
        },
        _prepareItem:function(profile, item){
            var p = profile.properties, t;
            item._tabindex = p.tabindex;

            if(t = item.itemMargin || p.itemMargin)
                item.itemMargin = "margin:" + t;

            if(t = item.itemWidth || p.itemWidth)
                item.itemWidth = "width:"+ ( t=='auto'?t:(t+'px'));

            if(t = item.itemAlign || p.itemAlign)
                item.itemAlign = "text-align:"+ t;

            if(t = item.itemLinker || p.itemLinker)
               item._endsClass = profile.getClass('ITEM', '-'+t);
        }
    }
});

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');
                    //scroll
                        var o = profile.getSubNode('ITEM',itemId);
                        if(o){
                            var items = profile.getSubNode('BOX'),
                                offset = o.offset(null, items),
                                top = offset?offset.top:0,
                                height = o.offsetHeight(),
                                sh=items.scrollHeight(),
                                st=items.scrollTop(),
                                hh=items.height();
                            if(sh > hh)
                                if(top<st || (top+height)>(st+hh))
                                    items.scrollTop(top);
                        }
                    }
                }else if(selmode=='multi'||selmode=='multibycheckbox'){
                    uiv = uiv?uiv.split(properties.valueSeparator):[];
                    value = value?value.split(properties.valueSeparator):[];
                    if(flag){
                        _.arr.each(value,function(o){
                            fun('BAR', o);
                        });
                    }else{
                        //check all
                        _.arr.each(uiv,function(o){
                            fun('BAR', o, false);
                        });
                        _.arr.each(value,function(o){
                            fun('BAR', o);
                        });
                    }
                }
            });
        },
        insertItems:function(arr, pid, base ,before){
            if(!arr || !_.isArr(arr) || arr.length<1)return this;
            var node,data,
                b=this._afterInsertItems;

            return this.each(function(profile){
                // prepare properties format
                var tar,r,k;

                data=profile.box._adjustItems(arr);

                if(!pid){
                    k=profile.properties;
                    tar = k.items ||(k.items=[])
                }else{
                    k=profile.getItemByItemId(pid);
                    tar = _.isArr(k.sub)?k.sub:(k.sub= []);
                }
                //1
                if(profile.renderId){
                    if(!base){
                        if(!pid)
                            node=profile.getSubNode('ITEMS');
                        else if(pid && k._inited)
                            node=profile.getSubNodeByItemId('SUB', pid);
                        if(node){
                            r=profile._buildItems('items', profile.box._prepareItems(profile, data, 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, data, pid));
                            if(before)
                                node.addPrev(r);
                            else
                                node.addNext(r);
                        }
                    }
                }
                //2
                //must be here
                if(!base)
                    _.arr.insertAny(tar,data, before?0:-1);
                else{
                    var index = _.arr.subIndexOf(tar, 'id', base);
                    _.arr.insertAny(tar,data, before?index:(index+1));
                }
                //3
                if(profile.renderId){
                    //open parent node
                    if(!(('iniFold' in k)?k.iniFold:profile.properties.iniFold))
                        if(!pid || profile.getItemByItemId(pid)._inited)
                            profile.boxing()._toggleNodes(data, true);
                }
                
                if(b && profile.renderId)
                    profile.boxing()._afterInsertItems(profile, data, pid, base, before);

                if(profile.renderId && pid){
                    profile.box._tofold(profile,k,pid);
                }

            });
        },
        _toggleNodes:function(items, expend, recursive){
            var self=this;
            if(_.isArr(items))
                _.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 this;
        },
        /*
        *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 && _.isArr(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,i){
                        if(o.sub){
                            profile.boxing().toggleNode(o.id,true);
                            // for the last one, trigger its onclick event
                            if(i==a.length-1 && !(o.hasOwnProperty('group')?o.group:profile.properties.group))
                                profile.boxing().fireItemClickEvent(o.id);
                        }else
                            profile.boxing().fireItemClickEvent(o.id);
                    });
                }
            });
        }
    },
    Initialize:function(){
        this.addTemplateKeys(['DISABLED']);
    },
    Static:{
        _focusNodeKey:'BAR',
        Templates:{
            tagName : 'div',
            style:'{_style}',
            className:'{_className}',
            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}  {readonly}',
                        style:'{itemStyle}{itemDisplay}',
                        tagName : 'div',
                        BAR:{
                            $order:0,
                            tabindex: '{_tabindex}',
                            className:'{cls_group} {cls_fold}',
                            RULER:{
                                $order:0,
                                style:'{rulerStyle}',
                                text:'{innerIcons}'
                            },
                            TOGGLE:{
                                $order:1,
                                className:'{togglemark}'
                            },
                            MARK:{
                                $order:2,
                                style:'{mark2Display}'
                            },
                            ITEMICON:{
                                $order:3,
                                className:'linb-ui-icon {imageClass}',
                                style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {imageDisplay}'
                            },
                            ITEMCAPTION:{
                                text : '&nbsp;{caption}',
                                className:"{disabled}  {readonly}",
                                $order:4
                            },
                            EXTRA:{
                                text : '{ext}',
                                $order:5
                            }
                        },
                        SUB:{
                            $order:1,
                            tagName : 'div',
                            text:linb.UI.$childTag
                        }
                    }
                }
            }
        },
        Appearances:{
            KEY: {
                'font-family': 'Verdana, Helvetica, sans-serif',
                'border':0
            },
            EXTRA:{
                display:'none'
            },
            BOX:{
                left:0,
                overflow: 'auto',
                'overflow-x': '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',
               'outline-offset':'-1px',
               '-moz-outline-offset':(linb.browser.gek && parseInt(linb.browser.ver)<3)?'-1px !important':null,
               'border-color':'#EDF4FC #698AB3 #698AB3 #EDF4FC',
               '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:linb.browser.ie?1:null,
                height:0,
                'font-size':'1px',
                //1px for ie8
                'line-height':'1px',
                position:'relative',
                'margin-left':'16px'
            },

            MARK:{
               cursor:'pointer',
               width:'16px',
               height:'16px',
               'vertical-align':'middle',
               background: linb.UI.$bg('icons.gif', 'no-repeat -20px -70px', true)
            },
            'BAR-checked MARK':{
                $order:3,
                'background-position': '0 -70px'
            },
            ITEMCAPTION:{
                'vertical-align':linb.browser.ie6?'baseline':'middle',
                padding:'2px'
            }
        },
        Behaviors:{
            HoverEffected:{TOGGLE:'TOGGLE', BAR:'BAR'},
            ClickEffected:{TOGGLE:'TOGGLE', BAR:'BAR'},
            DraggableKeys:["BAR"],
            NoDraggableKeys:['TOGGLE'],
            DroppableKeys:["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:{
                onDblclick:function(profile, e, src){
                    var properties = profile.properties,
                        item = profile.getItemByDom(src),
                        rtn=profile.onDblclick && profile.boxing().onDblclick(profile, item, e, src);
                    if(item.sub && rtn!==false){
                        profile.getSubNode('TOGGLE',profile.getSubId(src)).onClick();
                    }
                },
                onClick:function(profile, e, src){
                    return profile.box._onclickbar(profile,e,src);
                },
                onKeydown:function(profile, e, src){
                    return profile.box._onkeydownbar(profile,e,src);
                },
                onContextmenu:function(profile, e, src){
                    if(profile.onContextmenu)
                        return profile.boxing().onContextmenu(profile, e, src,profile.getItemByDom(src))!==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:{
            onDblclick:function(profile, item, e, src){},
            onGetContent:function(profile, item, callback){},
            onItemSelected:function(profile, item, e, src, type){},
            beforeFold:function(profile,item){},
            beforeExpend:function(profile,item){},
            afterFold:function(profile,item){},
            afterExpend:function(profile,item){}
        },
        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','multibycheckbox'],
                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('MARK',o.id).get(0));
                    });
                    linb(sels).css('display',(value=='multi'||value=='multibycheckbox')?'':'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);
        },
        _onclickbar: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);
    
            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;
            }
    
            profile.getSubNode(profile.box._focusNodeKey, itemId).focus();
    
            switch(properties.selMode){
            case 'none':
                box.onItemSelected(profile, item, e, src, 0);
                break;
            case 'multibycheckbox':
                if(properties.readonly|| item.readonly)return false;
                if(profile.keys.MARK){
                    if(profile.getKey(linb.Event.getSrc(e).id||"")!=profile.keys.MARK){
                        box.onItemSelected(profile, item, e, src, 0);
                        break;
                    }
                }
            case 'multi':
                if(properties.readonly|| item.readonly)return false;
                var value = box.getUIValue(),
                    arr = value?value.split(properties.valueSeparator):[],
                    checktype=1;
                if(arr.length&&(ks.ctrlKey||ks.shiftKey||properties.noCtrlKey)){
                    if(ks.shiftKey){
                        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);
                            checktype=-1;
                        }else
                            arr.push(item.id);
                    }
                    arr.sort();
                    value = arr.join(properties.valueSeparator);
    
                    //update string value only for _setCtrlValue
                    if(box.getUIValue() != value){
                        box.setUIValue(value);
                        if(box.get(0) && box.getUIValue() == value)
                            box.onItemSelected(profile, item, e, src, checktype);
                    }
                    break;
                }
            case 'single':
                if(box.getUIValue() != item.id){
                    profile.$firstV=item;
                    box.setUIValue(item.id);
                    if(box.get(0) && box.getUIValue() == item.id)
                        box.onItemSelected(profile, item, e, src, 1);
                }
                break;
            }
        },
        _onkeydownbar:function(profile, e, src){
            var keys=linb.Event.getKey(e), key = keys.key, shift=keys.shiftKey, ctrl=keys.ctrlKey,
                cur = profile.getSubNode(profile.box._focusNodeKey, profile.getSubId(src)),
                root = profile.getRoot(),
                first = root.nextFocus(true, true, false),
                last = root.nextFocus(false, true, false);

            switch(key){
                case 'enter':
                    cur.onClick();
                    break;
                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':
                    if(ctrl){
                        profile.getSubNode('TOGGLE',profile.getSubId(src)).onClick();
                        return false;
                    }
                    if(cur.get(0)==first.get(0))
                        last.focus();
                    else
                        cur.nextFocus(false, true, false).focus();
                     return false;
                     break;
                case 'down':
                    if(ctrl){
                        profile.getSubNode('TOGGLE',profile.getSubId(src)).onClick();
                        return false;
                    }
                     if(cur.get(0)==last.get(0))
                        first.focus();
                     else
                        cur.nextFocus(true, false, false).focus();
                     return false;
                     break;
                case 'right':
                case 'left':
                    profile.getSubNode('TOGGLE',profile.getSubId(src)).onClick();
                    return false;
            }
        },
        _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;
        },
        _prepareItem:function(profile, item, oitem, pid, index,len){
            var p=profile.properties,
                map1=profile.ItemIdMapSubSerialId,
                map2=profile.SubSerialIdMapItem,
                pitem;

            if(pid)
                oitem._pid=pid;

            // set 'visible' will show when parent call .height()
            item.togglemark = item.sub?'linb-uicmd-toggle':'linb-uicmd-none';

            item.disabled = item.disabled?profile.getClass('KEY', '-disabled'):'';
            item.itemDisplay=item.hidden?'display:none;':'';
            item.mark2Display = (p.selMode=='multi'||p.selMode=='multibycheckbox')?'':'display:none;';
            item._tabindex = p.tabindex;
            //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,
                ins=profile.boxing(),
                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){
                    if(ins.beforeFold && false===ins.beforeFold(profile,item)){
                        return;
                    }
                    var h=subNs.height();

                    if(properties.animCollapse)
                        subNs.animate({'height':[h,0]},null,function(){
                            subNs.css({display:'none'})
                        }, 100, 5, 'expoIn', profile.key+profile.id).start();
                    else
                        subNs.css({
                            display:'none',
                            height:0
                        });

                    markNode.tagClass('-checked', false);
                    barNode.tagClass('-expand',false).tagClass('-fold');
                    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._inited;
                    }
                }
                if(ins.afterFold)
                    ins.afterFold(profile,item);
                    
                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){
                    if(ins.beforeExpend && false===ins.beforeExpend(profile,item)){
                        return;
                    }

                    var openSub = function(profile, item, id, markNode, subNs, barNode, sub, recursive){
                            var b=profile.boxing(),
                                p=profile.properties;
                            //created
                            if(!item._inited){
                                delete item.sub;
                                //before insertRows
                                item._inited=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.setUIValue(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]},function(){
                                            subNs.css({display:''})
                                        },function(){
                                            subNs.css({height:'auto'})
                                        },100, 5, 'expoOut', profile.key+profile.id).start();
                                else
                                    subNs.css({display:'',height:'auto'});
                            }else
                                subNs.css({display:'',height:'auto'});

                            markNode.tagClass('-checked');
                            barNode.tagClass('-fold',false).tagClass('-expand');
                            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){
                            //return true: continue UI changing
                            if(r===true)
                                item._inited=true;
                            callback(r);
                        }                                                              }
                }
                if(ins.afterExpend)
                    ins.afterExpend(profile,item);

                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);
                    });
                }
            }
        },
        _tofold:function(profile,item,pid){
            profile.getSubNodeByItemId('BAR', pid).addClass(profile.getClass('BAR','-fold'));
            profile.getSubNodeByItemId('TOGGLE', pid).replaceClass(new RegExp("\\buicmd-none\\b"), "linb-uicmd-toggle");
        },
        _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.TreeView","linb.UI.TreeBar",{
    Instance:{
        _afterInsertItems:function(profile, data, pid){
            profile.box._reorderItems(profile, pid);
        },
        _afterRemoveItems:function(profile, data){
            _.arr.each(data,function(item){
                profile.box._reorderItems(profile, item._pid);
            });
        }
    },
    Initialize:function(){
        this.addTemplateKeys(['IMAGE']);
        var t=this.getTemplate();
        delete t.$submap.items.ITEM.BAR.tabindex;
        t.$submap.items.ITEM.BAR.ITEMCAPTION.tabindex='{_tabindex}';
        this.setTemplate(t);
    },
    Static:{
        _focusNodeKey:'ITEMCAPTION',
        Appearances:{
            ITEMS:{
                //overflow: 'visible'
            },
            ITEM:{
                'white-space': 'nowrap',
                position:'relative'
            },
            BAR:{
               zoom:linb.browser.ie?1:null,
               position:'relative',
               display:'block',
               'font-size':'12px',
               padding:'0',
               border: '0'
            },
            SUB:{
                zoom:linb.browser.ie?1:null,
                height:0,
                'font-size':'1px',
                //1px for ie8
                'line-height':'1px',
                position:'relative'
            },
            BOX:{
                left:0,
                overflow: 'auto',
                position:'relative',
                'background-color':'#FFF'
            },
            'BAR ITEMICON':{
                background: linb.UI.$bg('icons.gif', 'no-repeat 0 0', true),
                'background-position' : '-244px -236px'
            },
            'BAR-fold ITEMICON':{
                $order:1,
                'background-position' : '-260px -236px'
            },
            'BAR-expand ITEMICON':{
                $order:1,
                'background-position' : '-276px -236px'
            },
            'IMAGE-vertical, IMAGE-path-1, IMAGE-path-2, IMAGE-path-3, IMAGE-fold-1, IMAGE-fold-2, IMAGE-fold-3':{
                $order:1,
                background: linb.UI.$bg('icons.gif', 'no-repeat 0 0', true),
                width:'16px',
                height:'18px',
                'vertical-align':'middle'
            },
            'IMAGE-none':{
                width:'16px',
                height:'18px',
                'vertical-align':'middle'
            },
            'IMAGE-path-1,IMAGE-path-2':{
                $order:2,
                'background-position' : '-196px -236px'
            },
            'IMAGE-path-3':{
                $order:3,
                'background-position' : '-212px -236px'
            },
            'IMAGE-fold-1':{
                $order:4,
                'background-position' : '-196px -254px'
            },
            'IMAGE-fold-2':{
                $order:5,
                'background-position' : '-212px -254px'
            },
            'IMAGE-fold-3':{
                $order:6,
                'background-position' : '-228px -254px'
            },
            'IMAGE-fold-1-checked':{
                $order:7,
                'background-position' : '-244px -254px'
            },
            'IMAGE-fold-2-checked':{
                $order:8,
                'background-position' : '-260px -254px'
            },
            'IMAGE-fold-3-checked':{
                $order:9,
                'background-position' : '-276px -254px'
            },
            'IMAGE-fold-1-mousedown':{
                $order:10,
                'background-position' : '-196px -272px'
            },
            'IMAGE-fold-2-mousedown':{
                $order:11,
                'background-position' : '-212px -272px'
            },
            'IMAGE-fold-3-mousedown':{
                $order:12,
                'background-position' : '-228px -272px'
            },
            'IMAGE-fold-1-checked-mousedown':{
                $order:13,
                'background-position' : '-244px -272px'
            },
            'IMAGE-fold-2-checked-mousedown':{
                $order:14,
                'background-position' : '-260px -272px'
            },
            'IMAGE-fold-3-checked-mousedown':{
                $order:15,
                'background-position' : '-276px -272px'
            },
            'IMAGE-vertical':{
                $order:16,
                'background-position' : '-228px -236px'
            },
            ITEMCAPTION:{
                cursor:'pointer',
               'outline-offset':'-1px',
               '-moz-outline-offset':(linb.browser.gek && parseInt(linb.browser.ver)<3)?'-1px !important':null
            },
            'ITEMCAPTION-mouseover':{
                $order:12,
               'background-color': '#eee'
            },
            'BAR-checked':{
            },
            'ITEMCAPTION-mousedown, BAR-checked ITEMCAPTION':{
               $order:14,
               'background-color':'#4E8FDF',
               'color':'#fff'
            }
        },
        Behaviors:{
            HoverEffected:{ITEMCAPTION:'ITEMCAPTION'},
            ClickEffected:{TOGGLE:'TOGGLE', ITEMCAPTION:'ITEMCAPTION'},
            DraggableKeys:["ITEMCAPTION"],
            DroppableKeys:["BAR","TOGGLE","BOX"],
            BAR:{
                onDblclick:null,
                onClick:null,
                onKeydown:null,
                afterMouseover:null,
                afterMouseout:null,
                afterMousedown:null,
                afterMouseup:null,
                beforeDragbegin:null,
                beforeDragstop:null,
                beforeMousedown:null
            },
            ITEMCAPTION:{
                onDblclick:function(profile, e, src){
                    var properties = profile.properties,
                        item = profile.getItemByDom(src),
                        rtn=profile.onDblclick && profile.boxing().onDblclick(profile, item, src);
                    if(item.sub && rtn!==false){
                        profile.getSubNode('TOGGLE',profile.getSubId(src)).onClick();
                    }
                },
                onClick:function(profile, e, src){
                    return profile.box._onclickbar(profile,e,linb.use(src).parent().linbid());
                },
                onKeydown:function(profile, e, src){
                    return profile.box._onkeydownbar(profile,e,linb.use(src).parent().linbid());
                }
            },
            MARK:{
                onClick:function(profile, e, src){
                   return profile.box._onclickbar(profile,e,linb.use(src).parent().linbid());
                }
            },
            ITEMICON:{
                onClick:function(profile, e, src){
                   return profile.box._onclickbar(profile,e,linb.use(src).parent().linbid());
                }
            },
            BOX:{
                onScroll:null
            }
        },
        DataModel:{
            group:null
        },
        _buildIcon:function(cls, type){
            return "<span class='"+cls+type+"'></span>";
        },
        _getType:function(sub, type){
            return sub
                ? type=='last' ? '-fold-3': type=='first'? '-fold-1' : '-fold-2'
                : type=='last' ? '-path-3': type=='first'? '-path-1' : '-path-2';
        },
        _prepareItem:function(profile, item, oitem, pid, index,len){
            var p=profile.properties,
                map1=profile.ItemIdMapSubSerialId,
                map2=profile.SubSerialIdMapItem,
                pitem,arr,ll,
                html,
                cls=profile.getClass('IMAGE'),
                buildIcon=this._buildIcon,
                getType=this._getType;

            if(pid){
                oitem._pid=pid;
                if(pitem=map2[map1[pid]]){
                    oitem._deep=pitem._deep+1;
                    arr=_.copy(pitem._icons);
                    arr.push(index==len-1?'last':index===0?'first':'middle');
                    oitem._icons=arr;
                    item.rulerStyle='width:'+(oitem._deep*16)+'px;';


                    // build image html
                    html='';
                    ll=arr.length-1;
                    _.arr.each(arr,function(o,i){
                        if(i!==ll)
                            html+=buildIcon(cls, o=='last'?'-none':'-vertical');
                    });
                    item.innerIcons=html;


                    // for the last one
                    item.togglemark = cls+getType(item.sub, arr[ll]);
                }
            }else{
                oitem._deep=0;
                oitem._icons=[index==len-1?'last':index===0?'first':'middle'];
                item.rulerStyle='';
                item.innerIcons='';

                item.togglemark = cls+getType(item.sub, oitem._icons[0]);
            }
            // show image
            item.imageDisplay='';
            //
            item.cls_fold = item.sub?profile.getClass('BAR','-fold'):'';

            item.disabled = item.disabled?profile.getClass('KEY', '-disabled'):'';
            item.itemDisplay=item.hidden?'display:none;':'';
            item.mark2Display = (p.selMode=='multi'||p.selMode=='multibycheckbox')?'':'display:none;';
            item._tabindex = p.tabindex;
        },
        _reorderItems:function(profile, pid){
            var p=profile.properties,
                map1=profile.ItemIdMapSubSerialId,
                map2=profile.SubSerialIdMapItem,
                cls=profile.getClass('IMAGE'),
                getType=this._getType;

            var getAllSub=function(item, arr){
                if(item.sub && item.sub.length){
                    var me=arguments.callee;
                    _.arr.each(item.sub,function(item){
                        if(item._icons)
                            arr.push(item);
                        me(item, arr);
                    });
                }
            };
            // no parent now
            if(pid && !map1[pid])
                return;

            var baseid=profile.box.KEY+"-RULER:"+profile.serialId+":",
                arr=pid?map2[map1[pid]].sub:p.items,
                len=arr.length,ov,nv,deep=0,
                aitem,ns;
            _.arr.each(arr,function(item,i){
                if(item._icons){
                    ov=item._icons[item._icons.length-1];
                    nv=i==len-1?'last':i===0?'first':'middle';
                    if(ov!=nv){
                        ns=[];
                        aitem=null;

                        item._icons[deep=item._icons.length-1]=nv;
                        // ui
                        aitem=item;
                        // recursive
                        var a=[];
                        getAllSub(item, a);
                        _.arr.each(a,function(o){
                            o._icons[deep]=nv;
                            // ui
                            ns.push(o.id);
                        });
                        // the toggle image
                        if(aitem){
                            profile.getSubNodeByItemId('TOGGLE', aitem.id)
                                // "linb-treeview-image-fold-2 linb-treeview-image--fold-2-checked"
                                // "linb-treeview-image-path-2"
                                .replaceClass(new RegExp("\\b"+cls+"-[\\w]+-[\\w]+((-[\\w]+)*)\\b", "g"), cls + getType(aitem.sub, nv) + '$1');
                        }
                        // parent's images
                        if(ns.length){
                            _.arr.each(ns,function(id,i){
                                ns[i]=baseid+map1[id];
                            });

                            // refresh className. -none or -vertical only
                            ns=linb(ns).first();
                            if(deep)
                                ns=ns.next(deep);
                            ns.removeClass(new RegExp("\\b"+cls+"[-\\w]+\\b"))
                              .addClass(cls+(nv=='last'?'-none':'-vertical'));
                        }
                    }
                }
            });

        },
        _tofold:function(profile,item,pid){
            var cls=profile.getClass('IMAGE');
            profile.getSubNodeByItemId('BAR', pid).addClass(profile.getClass('BAR','-fold'));
            profile.getSubNodeByItemId('TOGGLE', pid).replaceClass(new RegExp("\\b"+cls+"-path([-\\w]+)\\b"), cls + '-fold$1');
        }
    }
});
Class("linb.UI.PopMenu",["linb.UI.Widget","linb.absList"],{
    Instance:{
        adjustSize:function(){
            this.each(function(profile){
                if(profile.renderId){
                    var border = profile.getSubNode('BORDER'),
                        items = profile.getSubNode('ITEMS').cssSize({width:'auto',height:'auto'}),
                        itemNs = profile.getSubNode('ITEM',true),
                        pro=profile.properties,
                        ww=0,hh=0;

                        hh = items.height();
                        if(hh%2==0)hh+=2;else hh+=1;

                        items.addClass(profile.getClass('ITEMS','-inline'));
                        itemNs.each(function(n){
                            ww=Math.max(ww, n.offsetWidth);
                        });
                        if(ww%2==0)ww+=2;else ww+=1;
                        
                        items.removeClass(profile.getClass('ITEMS','-inline'));

                    // for IE7
                    items.cssSize({width:ww,height:hh});

                    var h = Math.min(pro._maxHeight, hh) + border._borderW(),
                        w = Math.min(pro._maxWidth, ww) + border._borderH();
                    pro.width=w;
                    pro.height=h;
                    //set size first, for adding shadow later
                    profile.getRoot().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){
                if(profile.renderId){
                    var o=profile.getSubNode('ITEMS'),
                        t=o.offsetTop(),
                        h=o.offsetHeight(),
                        b = profile.getRoot(),
                        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<5)
                        profile.$scrollStep = profile.$scrollStep*1.01;

                    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<5)
                        profile.$scrollStep = profile.$scrollStep*1.01;

                    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),
                sms='$subPopMenuShowed',
                hl='$highLight',
                cm='$childPopMenu';

            //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;
                // maybe destroyed here
                if(p.box){
                    p.boxing().hide();
                    if(p.$popGrp)
                        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);
            }
            profile[cm]=profile[sms]=profile[hl]=null;
            return this;
        },
        hide:function(triggerEvent){
            var t,
                profile=this.get(0),
                root=profile.getRoot(),
                sms='$subPopMenuShowed',
                hl='$highLight',
                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');

            if(t=profile[hl])
               linb([t]).tagClass('-mouseover',false);

            //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] = q[hl] = null;
            }
            profile[cm]=profile[sms]=profile[hl]=null;
            if(t=profile.$parentPopMenu)t[sms]=null;
            
            if(profile.$popGrp)
                _.arr.removeValue(profile.$popGrp,root._get(0));

            if(false!==triggerEvent)
                profile.boxing().onHide(profile);
            return this;
        },
        _afterInsertItems:function(profile){
            if(!profile.renderId)return;
            profile.boxing().adjustSize();
        },
        _afterRemoveItems:function(profile){
            if(!profile.renderId)return;
            profile.boxing().adjustSize();
        }
    },
    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:{
                    style:"{itemDisplay}"
                }
            },
            'items.button':{
                ITEM:{
                    tabindex: -1,
                    className: '{itemClass} {disabled}',
                    style:'{itemStyle}{itemDisplay}',
                    ICON:{
                        $order:0,
                        className:'linb-ui-icon {imageClass}',
                        style:'{backgroundImage} {backgroundPosition} {backgroundRepeat}'
                    },
                    CAPTION:{
                        text : '{caption}',
                        $order:1
                    },
                    RULER:{
                        style:'{displayAdd}',
                        $order:2
                    },
                    ADD:{
                        tagName : 'div',
                        style:'{displayAdd}',
                        text : '{add}',
                        $order:2
                    },
                    SUB:{style:'{displaySub}'}
                }
            },
            'items.checkbox':{
                ITEM:{
                    tabindex: -1,
                    className: '{itemClass} {disabled}',
                    style:'{itemStyle}{itemDisplay}',
                    CHECKBOX:{
                        $order:0,
                         className:'linb-ui-icon {checkboxCls}'
                    },
                    CAPTION:{
                        text : '{caption}',
                        $order:1
                    },
                    RULER:{
                        style:'{displayAdd}',
                        $order:2
                    },
                    ADD:{
                        tagName : 'div',
                        style:'{displayAdd}',
                        text : '{add}',
                        $order:2
                    }
                }
            },
            'items.radiobox':{
                ITEM:{
                    tabindex: -1,
                    className: '{itemClass} {disabled}',
                    style:'{itemStyle}{itemDisplay}',
                    RADIOBOX:{
                        $order:0,
                         className:'linb-ui-icon {radioboxCls}'
                    },
                    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:'hidden',
                background: linb.UI.$bg('bg.gif', 'repeat-y left top')
            },
            'ITEMS-inline ITEM':{
                $order:5,
                display:linb.$inlineBlock
            },
            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'
            },
            'ITEM-checked':{
                $order:2,
                'background-color':'#FFFA9F'
            },
            ICON:{
                margin:0
            },
            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)
            },
            'RADIOBOX, CHECKBOX, RADIOBOX-checked, CHECKBOX-checked':{
                cursor:'pointer',
                'vertical-align':'middle',
                width:'16px',
                height:'16px'
            },
            CHECKBOX:{
               background: linb.UI.$bg('icons.gif', 'no-repeat -20px -70px', true),
               margin:0
            },
            'CHECKBOX-checked':{
               $order:1,
               background: linb.UI.$bg('icons.gif', 'no-repeat -0px -70px', true)
            },
            RADIOBOX:{
               background: linb.UI.$bg('icons.gif', 'no-repeat -60px -70px', true),
               margin:0
            },
            'RADIOBOX-checked':{
               $order:1,
               background: linb.UI.$bg('icons.gif', 'no-repeat -40px -70px', true)
            },
            CAPTION:{
                'vertical-align':linb.browser.ie6?'baseline':'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',
                zoom:linb.browser.ie?1:null
            },
            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 no sub arrays
                        if(!(_.isArr(item.sub) && item.sub.length)){
                            if(profile.onShowSubMenu){
                                var r=profile['$sub:'+item.id];
                                if(r && r['linb.UI'] && !r.isEmpty()){}
                                else
                                    r=profile.boxing().onShowSubMenu(profile, item, src);
                                
                                // return UI control
                                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);
                                    
                                    return;
                                }
                                // return items array
                                else if(r && _.isArr(r) && r.length){
                                    item.sub=r;
                                }
                            }                            
                        }
                        
                        // show items
                        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.onShowSubMenu(function(pro, item, src){
                                    return profile.boxing().onShowSubMenu(profile, item, src);
                                });
                                pop.onMenuSelected(function(pro, item, src){
                                    return 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;
                        }
                    }
                },
                onMouseout:function(profile, e, src){
                    var properties = profile.properties,
                        item = profile.getItemByDom(src),
                        itemId = item.id,
                        action = true,
                        hl='$highLight',
                        t;
                    if(profile[hl] == src)return;

                    //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[hl] = null;
                },
                onClick:function(profile, e, src){
                    var prop = profile.properties,
                        item = profile.getItemByDom(src),
                        itemId = item.id;
                    if(prop.disabled || item.disabled)return false;

                    // give a change to click an item with sub popmenu
                    if(!item.group){
                        if(item.type=='checkbox')
                            profile.getSubNodeByItemId('CHECKBOX',item.id).tagClass('-checked', item.value = !item.value);
                        else if(item.type=='radiobox'){
                            profile.getSubNode('RADIOBOX',true).tagClass('-checked', false);
                            _.arr.each(prop.items,function(o){
                                if(o.type=='radiobox')
                                    o.value=false;
                            });
                            profile.getSubNodeByItemId('RADIOBOX',item.id).tagClass('-checked', item.value = true);
                        }

                        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;
                                if(!p.renderId)return;
                                while(p){
                                    p.boxing().hide();
                                    p=(q=p).$parentPopMenu;
                                    q.$parentPopMenu = q.$subPopMenuShowed = null;
                                }
                                //reset
                                profile.$subPopMenuShowed = null;
                                if(profile.$popGrp)
                                    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).key,
                        itemId = item.id,
                        flag,r,tid,node,t;

                    switch(key){
                        case 'enter':
                            linb(src).onClick();
                            break;
                        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*=2;
                }
            },
            BOTTOM:{
                onMouseover:function(profile){
                    profile.$scrollTobottom=true;
                    profile.boxing()._scrollToBottom();
                },
                onMouseout:function(profile){
                    profile.$scrollTobottom=false;
                    profile.$scrollStep=null;
                },
                onClick:function(profile){
                    profile.$scrollStep*=2;
                }
            },
            ITEMS:{
                afterKeydown:function(profile, e){
                    var key=linb.Event.getKey(e).key;
                    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();
                    if(profile.$popGrp)
                        profile.$popGrp.length=0;
                }
            }
        },
        _prepareItem:function(profile, item){
            var none='display:none;';
            item.add = item.add || '';
            item.displayAdd = item.add?'':none;
            item.displaySub = item.sub?'':none;
            item.itemDisplay=item.hidden?none:'';

            item.type=item.type||'button';
            if(item.type=='checkbox')
                item.checkboxCls =profile.getClass('CHECKBOX', item.value?'-checked':'');
            else if(item.type=='radiobox')
                item.radioboxCls =profile.getClass('RADIOBOX', 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),
                items=profile.properties.items;
            //the root
            if(_.arr.subIndexOf(items,"id",subId)!=-1)
                arguments.callee.upper.call(self,subId,options);
            //try each sub popmenu
            else{
                var ok=0;
                _.each(profile.$allPops,function(o){
                    o.updateItem(subId,options);
                    ok=1;
                });
                if(!ok)
                    arguments.callee.upper.call(self,subId,options);
            }
            return self;
        },
        _pop:function(item,src){
            var self=this,
                profile=self.get(0);
            //hide first
            if(profile.$curPop)self.hide();

            if(!item.sub)return ;

            if(profile.beforePopMenu && false==profile.boxing().beforePopMenu(profile, item, src)){
                return;
            }else{
                
                linb.use(src).tagClass('-mousedown');
                
                var menu, 
                    id=item.id,
                    pro=profile.properties,
                    all='$allPops';
                
                profile.$curPop=id;
                profile.$curElem=src;
                profile.$menuPop = id;

                profile[all] = profile[all] || {};
                if(!profile[all][id]){
                    var callback=function(sub){
                        var 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;
                    }

                    if(_.isArr(item.sub) && item.sub.length)
                        callback(item.sub);
                    else if(profile.onGetPopMenu){
                        var r=profile.boxing().onGetPopMenu(profile, item, callback);
                        if(_.isArr(r) && r.length)
                            callback(item.sub=r);
                    }
                }
                // popmenu
                if(profile[all][id])
                    profile[all][id].pop(linb(src), 1, linb(pro.parentID));

                return false;
            }
        },
        _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',
            className:'{_className}',
            style:'{_style}',
            POOL:{
                tagName:'div'
            },
            BORDER:{
                className:'linb-uibg-bar linb-uiborder-outset',
                tagName:'div',
                LIST:{
                    tagName:'div',
                    HANDLER:{
                        style:'{handler}'
                    },
                    ITEMS:{
                        $order:1,
                        text:"{items}"
                    }
                }
            },
            $submap:{
                items:{
                    ITEM:{
                        ITEMI:{
                            ITEMC:{
                                ITEMA:{
                                    tabindex: '{_tabindex}',
                                    className:' {typeCls} {disabled}',
                                    ICON:{
                                        $order:1,
                                        className:'linb-ui-icon {imageClass}',
                                        style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {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',
                top:'-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':linb.browser.ie6?'baseline':'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;
                    linb.use(ns).tagClass('-mouseover');

                    if(profile.$menuPop){
                        if(profile.$menuPop != itemId){
                            //show current popmenu
                            profile.boxing()._pop(item, ns);
                        }
                    }else{
                        if(p.autoShowTime){
                            _.resetRun(profile.$linbid+':autoShowTime', function(){
                                profile.boxing()._pop(item, 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;

                    linb.use(src).tagClass('-mousedown');
                    
                    // if poped, stop to trigger document.body's onmousedown event
                    return profile.boxing()._pop(item, src);                    
                },
                onMouseup:function(profile,e,src){
                    var item = profile.getItemByDom(src);
                    if(profile.$menuPop != item.id)
                        linb.use(src).tagClass('-mousedown',false);
                },
                onKeydown:function(profile, e, src){
                    var keys=linb.Event.getKey(e), key = keys.key, shift=keys.shiftKey,
                    cur = linb(src),
                    first = profile.getRoot().nextFocus(true, true, false),
                    last = profile.getRoot().nextFocus(false, true, false);

                    switch(linb.Event.getKey(e).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;
                        case 'enter':
                            cur.onMousedown();
                            break;
                    }
                },
                onClick:function(profile, e, src){
                    var item = profile.getItemByDom(src);
                    if(profile.$menuPop != item.id)
                        if(profile.onMenuBtnClick)
                            profile.boxing().onMenuBtnClick(profile, item, src);
                }
            }
        },
        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:{
            onGetPopMenu:function(profile, item, callback){},
            onMenuBtnClick:function(profile, item, src){},
            beforePopMenu:function(profile, item, src){},
            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.call(this,subId,options);
            }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),
                    nid,item,n1,n2,n3,n4,t;
                if(_.isStr(options))options={caption:options};

                if(rst.length){
                        rst=rst[0];
                        if(item=rst[0]){
                            
                        // [[modify id
                        if(_.isSet(options.id))options.id+="";
                        if(options.id && subId!==options.id){
                            nid=options.id;
                            var m2=profile.ItemIdMapSubSerialId, v;
                            if(!m2[nid]){
                                if(v=m2[subId]){
                                    m2[nid]=v;
                                    delete m2[subId];
                                    profile.SubSerialIdMapItem[v].id=nid;
                                }else{
                                    item.id=nid;
                                }
                            }
                        }
                        delete options.id;
                        // modify id only
                        if(_.isEmpty(options))
                            return self;
                        //]]
                    
                        //in dom already?
                        n1=profile.getSubNodeByItemId('ICON',nid||subId);
                        n2=profile.getSubNodeByItemId('CAPTION',nid||subId);
                        n3=profile.getSubNodeByItemId('ITEM',nid||subId);
                        n4=profile.getSubNodeByItemId('LABEL',nid||subId);

                        if('value' in options && options.value!=item.value)
                            profile.getSubNodeByItemId('BTN',nid||subId).tagClass('-checked', !!options.value);
                            
                        if('caption' in options&& options.caption!=item.caption){
                            n2.html(options.caption);
                            if(options.caption && !item.caption)
                                n2.css('display','');
                            if(!options.caption && item.caption)
                                n2.css('display','none');
                        }
                        if('label' in options&& options.label!=item.label){
                            n4.html(options.label);
                            if(options.label && !item.label)
                                n4.css('display','');
                            if(!options.label && item.label)
                                n4.css('display','none');
                        }
                        if('disabled' in options && options.disabled!=item.disabled){
                            if(options.disabled)
                                n2.addClass('linb-ui-itemdisabled');
                            else
                                n2.removeClass('linb-ui-itemdisabled');
                        }
                        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);
                        }
                        if('hidden' in options){
                            var  b = !!options.hidden;
                            if(b){
                                if(item.hidden!==true){
                                    n3.css('display','none');
                                }
                            }else{
                                if(item.hidden===true){
                                    n3.css('display','');
                                }
                            }
                        }

                        //merge options
                        _.merge(item, options, 'all');
                    }
                }
                return self;
            }
        },
        showItem:function(itemId, value){
            return this.each(function(profile){
                var item=profile.getItemByItemId(itemId);
                if(item){
                    item.hidden=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.hidden=value===false;
                        return false;
                    }
                });
                var n=profile.getSubNodeByItemId('GROUP', grpId);
                n.css('display',value===false?'none':'');    
                if(profile.renderId && profile.getRootNode().offsetWidth)
                    linb.UI.$dock(profile,true,true);
            });
        }
    },
    Static:{
        _focusNodeKey:'BTN',
        _ITEMKEY:'GROUP',
        Templates:{
            tagName:'div',
            className:'{_className}',
            style:'{_style}',
            ITEMS:{
                className:'linb-uibg-bar linb-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:'linb-ui-btn {itemcls} {itemClass}',
                                style:'{itemStyle} {boxDisplay}',
                                BTNI:{
                                    className:'linb-ui-btni',
                                    BTNC:{
                                        className:'linb-ui-btnc',
                                        BOX:{
                                            tabindex: '{_tabindex}',
                                            BOXWRAP:{
                                                tagName:'div',
                                                RULER:{},
                                                ICON:{
                                                    $order:1,
                                                    className:'linb-ui-icon {imageClass}',
                                                    style:'{backgroundImage} {backgroundPosition} {backgroundRepeat}  {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',
                overflow:'hidden',
                left:0,
                top:0
            },
            'ITEM-object':{
                'vertical-align':'middle',
                'margin-left':'4px'
            },
            RULER:{
                padding:'0px',
                margin:'0px',
                width:'0px'
            },
            ICON:{
                margin:0,
                'vertical-align':'middle'
            },
            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,
                // crack for: The IE 'non-disappearing content' bug
                position:'static',
                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':'middle',
                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'
            },
            BOX:{
                height:'22px'
            },
            'LABEL, CAPTION':{
                '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(_.isArr(o)){
                    o={
                        id:_.id(),
                        sub:o
                    };
                }
                if(_.isHash(o)){
                    //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(_.isHash(v)?_.copy(v):{id: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, index,len, mapCache, serialId){
            var dn='display:none',
                tabindex = profile.properties.tabindex,
                fun=function(profile, dataItem, item, pid, index,len, 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';
                            var addcls=profile.getClass('ITEM','-object'),
                                cck = t.CC.KEY || (cck=t.CC.KEY='');
                            if(cck.indexOf(addcls)===-1)
                                t.CC.KEY = cck + " " + addcls;
                        }
                        item.$linbid=t.$linbid;
                        t.$item=item;
                        t.$holder=profile;
                        if(!t.host||t.host===t)t.boxing().setHost(profile.host,t.alias);
                        if(!profile.$attached)profile.$attached=[];
                        profile.$attached.push(t);
                    }else{
                        if(item.type=='split'){
                            item.split=true;
                        }else{
                            if(!item.caption)
                                item.caption="";
                        }

                        linb.UI.adjustData(profile,item, dataItem);

                        if(item.statusButton && !!item.value)
                            dataItem.itemcls=" linb-ui-btn-checked "+profile.getClass('BTN','-checked', !!item.value);

                        dataItem._tabindex=tabindex;
                        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.hidden?dn:'';
                    item._pid=pid;
                };

            if(pid){
                fun(profile,oitem,sitem,pid,index,len,mapCache,serialId);
            }else{
                var arr=[],
                dataItem,
                a=sitem.sub||[];

                pid=sitem.id;
                oitem.mode2 = ('handler'in sitem)?(sitem.handler?'':dn):(profile.properties.handler?'':dn);
                oitem.grpDisplay=sitem.hidden?dn:'';
                oitem.sub = arr;

                _.arr.each(a,function(item){
                    dataItem={id: item.id};
                    fun(profile,dataItem,item,pid,index,len,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');
        },
        insertItems:function(arr, base, before){
            return this._insertItems(arr, base, before);
        },
        _insertItems:function(arr, base, before, all){
            var node,arr2,
                items, index, r,
                data,box,
                pos="before",
                b=this._afterInsertItems;
            return this.each(function(profile){
                box=profile.box;
                items = profile.properties.items;
                if(!all){
                    index = _.arr.subIndexOf(items,'id',base);
                    if(index==-1){
                        pos=before?'before':'after';
                    }else{
                        if(items[index].id=='main')
                            pos=before?'before':'after';
                        else
                            pos=items[index].pos;
                    }
    
                    arr2=box._adjustItems2(arr, pos);
                }else{
                    arr2=arr;
                }

                //must be here
                if(index==-1)
                    _.arr.insertAny(items,arr2, before?0:-1);
                else
                    _.arr.insertAny(items,arr2, before?index:index+1);

                //if in dom, create it now
                if(profile.renderId){
                    data = box._prepareItems(profile, arr2, base);
                    r=profile._buildItems('items', data);
                    profile.getRoot().prepend(r);
                    
                    var t=profile.getRootNode().style;
                    linb.UI.$tryResize(profile, t.width, t.height, true);
                    t=null;
                }

                if(b)
                    profile.boxing()._afterInsertItems(profile, data, base, before);
            });
        },
        _afterRemoveItems:function(profile){
            if(profile.renderId){                    
                var t=profile.getRootNode().style;
                linb.UI.$tryResize(profile, t.width, t.height, true);
                t=null;
            }            
        },
        updateItem:function(subId,options){
            var self=this,
                profile=self.get(0),
                vertical=profile.properties.type=='vertical',
                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),
                nid,item,serialId,node,sub,t;
            if(typeof options!='object')return;

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

                // [[modify id
                if(_.isSet(options.id))options.id+="";
                if(options.id && subId!==options.id){
                    nid=options.id;
                    var m2=profile.ItemIdMapSubSerialId, v;
                    if(!m2[nid]){
                        if(v=m2[subId]){
                            m2[nid]=v;
                            delete m2[subId];
                            profile.SubSerialIdMapItem[v].id=nid;
                        }else{
                            item.id=nid;
                        }
                    }
                }
                delete options.id;
                // modify id only
                if(_.isEmpty(options))
                    return self;
                //]]

                var bResize=false;
                //in dom already?
                node=profile.getSubNodeByItemId('ITEM',subId);
                if(!node.isEmpty()){
                    if(options.hasOwnProperty('size')){
                        options.size = parseInt(''+options.size);
                        if(options.size!=item.size){
                            item.size=options.size;
                            if(vertical)
                                node.height(options.size);
                             else
                                node.width(options.size);
                            bResize=true;
                        }
                    }
                    if(options.hasOwnProperty('hidden')){
                        options.hidden = !!options.hidden;
                        if(options.hidden !== item.hidden){
                            profile.getSubNodeByItemId('ITEM',subId).css('display',options.hidden?'none':'');
                            bResize=true;
                        }
                    }
                    if(options.hasOwnProperty('locked')){
                        options.locked = !!options.locked;
                        if(options.locked !== item.locked){
                            profile.getSubNodeByItemId('MOVE',subId).css('display',options.locked?'none':'');
                            bResize=true;
                        }
                    }
                    if(options.hasOwnProperty('folded')){
                        options.folded = !!options.folded;
                        if(options.folded !== item.folded)
                            profile.boxing().fireCmdClickEvent(subId);
                    }
                    if(options.hasOwnProperty('cmd')){
                        options.cmd = !!options.cmd;
                        if(options.cmd !== item.cmd)
                            profile.getSubNodeByItemId('CMD',subId).css('display',options.cmd?'':'none');
                    }
                }
                //merge options
                _.merge(item, options, 'all');

                if(bResize){
                    var t=profile.getRootNode().style;
                    linb.UI.$tryResize(profile, t.width, t.height, true);
                    t=null;
                }
            }
            return self;
        },
        fireCmdClickEvent:function(subId){
            this.getSubNodeByItemId('CMD', subId).onMousedown();
            return this;
        }
    },
    Static:{
        Templates:{
            tagName:'div',
            style:'{_style}',
            className:'{_className}',
            text:"{items}",
            $submap:{
                items:{
                    ITEM:{
                        tagName:'div',
                        className:'{cls1} {itemClass}',
                        style:'{size};{itemStyle};{display}',
                        MOVE:{
                            $order:0,
                            tagName:'div',
                            className:'linb-uibg-bar {cls2} ',
                            style:'{moveDisplay}'
                        },
                        CMD:{
                            $order:1,
                            tagName:'div',
                            style:'{cmdDisplay}',
                            className:'{cls3} '
                        },
                        PANEL:{
                            tagName:'div',
                            className:'linb-uibg-base',
                            style:'position:absolute;left:0;top:0;{_overflow};',
                            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:'0px'
            },
            '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:{
            DroppableKeys:['PANEL'],
            PanelKeys:['PANEL'],
            HoverEffected:{MOVE:'MOVE',CMD:'CMD'},
            onSize:linb.UI.$onSize,
            MOVE:{
                onMousedown:function(profile, e, src){
                    if(linb.Event.getBtn(e)!="left")return;
                    var itemId = profile.getSubId(src),
                        item = profile.getItemByDom(src);
                    if(item.folded)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,
                            // IE8 bug
                            targetWidth:linb.browser.ie?linb.use(src).offsetWidth():null,
                            targetHeight:linb.browser.ie?linb.use(src).offsetHeight():null,
                            targetCallback:linb.browser.ie?function(n){n.tagClass('-(top|bottom)',false)}:null
                        });
                    }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,
                            // IE8 bug
                            targetWidth:linb.browser.ie?linb.use(src).offsetWidth():null,
                            targetHeight:linb.browser.ie?linb.use(src).offsetHeight():null,
                            targetCallback:linb.browser.ie?function(n){n.tagClass('-(left|right)',false)}:null
                        });
                    }

                    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){
                    if(linb.Event.getBtn(e)!="left")return;
                    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.folded){
                            if(item.size <= m.height() - main.min + _handlerSize){
                                //restore h
                                o.height(item.size);
                                panel.show();

                                item.folded=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.folded=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.folded){
                            if(item.size <= m.width()-main.min + _handlerSize){
                                o.width(item.size);
                                panel.show();
                                item.folded=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.folded=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:{
            selectable:true,
            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());
                            })
                            .css({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());
                            })
                            .css({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,
            overflow:{
                ini:undefined,
                action:function(v){
                    this.getSubNode('PANEL',true).css('overflow',v||'');
                }
            },
            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._adjustItems(value);
                        //inset all items
                        box._insertItems(vv,null,null,true);

                        //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);
                }
            }
        },
        _adjustItems2:function(items, pos){
            var arr=[];
            //arrage items
            _.arr.each(items,function(o){
                if(o.id!='main'){
                    arr.push(o=_.isHash(o)?o:{id:''+o});
                    o.pos=pos;
                }
            });

            //set the items to default value
            _.arr.each(arr,function(o){
                o.id = _.isStr(o.id)?o.id:_.id();
                o.min = o.min || 10;
                o.size = parseInt(o.size) || 80;
                o.locked= typeof o.locked=='boolean'?o.locked:false;
                o.folded = typeof o.folded=='boolean'?o.folded:false;
                o.hidden = typeof o.hidden=='boolean'?o.hidden:false;
                o.cmd = typeof o.cmd=='boolean'?o.cmd:true;
            });
            return arr;
        },
        _adjustItems:function(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, this._adjustItems2(before,'before'));
            _.arr.insertAny(items, main);
            _.arr.insertAny(items, this._adjustItems2(after,'after'));

            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._adjustItems(prop.items);
            return arguments.callee.upper.call(this, profile);
        },
        _prepareItems:function(profile, items){
            var data = arguments.callee.upper.apply(this, arguments);
            _.arr.each(items,function(o){
                delete o.caption;
            });            
            return data;
        },
        _prepareItem:function(profile, item){
            var prop=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(prop.type=='vertical')
                item.size = 'height:'+item.size+'px';
            else
                item.size = 'width:'+item.size+'px';

            var pos;
            if(prop.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.hidden?'display:none':'';
            item.moveDisplay = item.locked?'display:none':'';
            item.cmdDisplay = item.cmd?'':'display:none';

            if(_.isStr(item.overflow))
                item._overflow = item.overflow.indexOf(':')!=-1?(item.overflow):("overflow:"+item.overflow);
            else if(_.isStr(prop.overflow))
                item._overflow = prop.overflow.indexOf(':')!=-1?(prop.overflow):("overflow:"+prop.overflow);
        },
        RenderTrigger:function(){
            var t, profile=this;
            _.arr.each(profile.properties.items,function(item){
                if(item.id!='main'){
                    if(item.folded && (t=profile.getSubIdByItemId(item.id))){
                            item.folded=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.hidden){
                                m=0;
                                obj2[itemId].width=o.size;
                            }else if(o.folded){
                                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.hidden){
                                m=0;
                                obj2[itemId].width=o.size;
                            }else if(o.folded){
                                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.hidden){
                                m=0;
                                obj2[itemId].height=o.size;
                            }else if(o.folded){
                                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);

                            if(o.hidden){
                                m=0;
                                obj2[itemId].height=o.size;
                            }else if(o.folded){
                                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]);
            });
        }
    }
});
Class("linb.UI.ColLayout",["linb.UI","linb.absList"],{
    Dependency:['linb.UI.Panel'],
    Instance:{
        addPanel:function(args, col, basePrf, before){
            var profile=this.get(0),
                items=profile.properties.items,
                prop=profile.properties;
            if(!col)
                col=items[0].id;
                
            if(_.arr.subIndexOf(items, 'id',col)==-1)
                return this;
            
            if(!args.properties)args.properties={};
            var ns=this, profile=ns.get(0);
            _.merge(args.properties,{   
                dock:'none',
                position:'relative',
                left:0,
                top:0,
                width:'auto',
                height:'auto',
                
                toggle:true,
                toggleBtn:true,
                
                dragKey: prop.disabled?null:profile.box.KEY+":"+profile.$linbid,                
                closeBtn:!prop.disabled 
            });
            var panel=new linb.UI.Panel(args.properties, args.events, args.host, args.theme, args.CS, args.CC, args.CB, args.CF);

            return this.movePanel(panel.get(0), col, basePrf, before);
        },
        movePanel:function(prf, col, basePrf, before){
            var profile=this.get(0);
            if(prf["linb.UI"])prf=prf.get(0);
            if(basePrf && basePrf["linb.UI"])basePrf=basePrf.get(0);

            if(prf && prf!=basePrf){

                var flag,items=profile.children;

                // add to collayout, or move to the right container first
                if(prf.parent!=profile || prf.childrenId != col){
                    this.append(prf, col);
                    flag=1;
                }
                
                var node,
                    tnode=prf.getRootNode();

                // reposition
                if(!basePrf){
                    node=this.getSubNodeByItemId('PANEL', col);
                    if(node.last().isEmpty() || node.last().id()!=tnode.id){
                        node.append(tnode);
                        flag=1;
                    }
                }else if(before){
                    node=basePrf.getRoot();
                    if(node.prev().isEmpty() || node.prev().id()!=tnode.id){
                        node.addPrev(tnode);
                        flag=1;
                        
                        var i1=_.arr.subIndexOf(items,'0',basePrf),
                            i2=_.arr.subIndexOf(items,'0',prf);
                        if(i1!=-1){
                            var item=items[i2];
                            _.arr.removeFrom(items, i2);
                            _.arr.insertAny(items, item, i1, true);
                        }
                    }
                }else{
                    node=basePrf.getRoot();
                    if(node.next().isEmpty() || node.next().id()!=tnode.id){
                        node.addNext(tnode);
                        flag=1;

                        var i1=_.arr.subIndexOf(items,'0',basePrf),
                            i2=_.arr.subIndexOf(items,'0',prf);
                        if(i1!=-1 && i1 > items.length){
                            var item=items[i2];
                            _.arr.removeFrom(items, i2);
                            _.arr.insertAny(items, item, i1+1, true);
                        }
                    }
                }

                if(flag && profile.onRelayout)this.onRelayout(profile);
            }
            return this;
        },
        append:function(target,subId){
            var p=this.get(0).properties;
            if(subId=subId||(p.items && p.items[0] && p.items[0].id))
                arguments.callee.upper.call(this, target, subId);
            return this;
        }
    },
    Static:{
        Templates:{
            tagName:'div',
            style:'{_style}',
            className:'{_className}',
            ITEMS:{
               $order:10,
               tagName:'div',
               text:"{items}"
            },
            COVER:{
                tagName:'div'
            },
            $submap:{
                items:{
                    ITEM:{
                        tagName:'div',
                        style:'width:{width}',
                        MOVE:{
                            // must be first one
                            $order:1,
                            tagName:'div',
                            style:'{_display}'
                        },
                        PANEL:{
                            $order:2,
                            tagName:'div',
                            text:linb.UI.$childTag
                        }
                    }
                }
            }
        },
        Appearances:{
            KEY:{
                position:'absolute',
                'overflow-x':'hidden',
                'overflow-y':'auto',
                border:'none',
                zoom:linb.browser.ie6?1:null
            },            
            ITEMS:{
                position:'relative',
                overflow:'hidden',
                border:'none',
                zoom:linb.browser.ie6?1:null
            },
            COVER:{
                position:'absolute',
                left:0,
                top:0,
                width:'100%',
                height:'100%',
                display:'none',
                'z-index':10,
                background: linb.browser.ie?'url('+linb.ini.img_bg+')':null
            },
            MOVE:{
                $order:0,
                position:'relative',
                'float':'right',
                width:'4px',
                height:'200px',
                cursor:'e-resize',
                'background-color':'#f4f4f4',
                'border-width':linb.browser.opr?'0':null,
                'font-size':linb.browser.ie?0:'',
                'line-height':linb.browser.ie?0:''
            },
            'MOVE-mouseover':{
                $order:1,
                'background-color': '#f0f0f0'
            },
            ITEM:{
                position:'static',
                'float':'left',
                overflow:'hidden',
                'border-width':'0',
                'font-size':linb.browser.ie?0:'',
                'line-height':linb.browser.ie?0:''
            },
            PANEL:{
                position:'static',
                overflow:'hidden',
                zoom:linb.browser.ie6?1:null,
                /*for opera, opera defalut set border to 3 ;( */
                'border-width':linb.browser.opr?'0':null,
                'font-size':linb.browser.ie?0:'',
                'line-height':linb.browser.ie?0:''
            }
        },
        Behaviors:{
            HoverEffected:{MOVE:'MOVE'},
            DroppableKeys:['KEY'],
            MOVE:{
                onMousedown:function(profile, e, src){
                    if(linb.Event.getBtn(e)!="left")return;
                    var pro=profile.properties;
                    if(pro.disabled)return;
                    
                    var    min=pro.minWidth,
                        cursor=linb.use(src).css('cursor'),
                        pre=profile._pre=linb.use(src).parent(),
                        preW=profile._preW=pre.offsetWidth(),
                        next=profile._next=pre.next(),
                        nextW=profile._nextW=next.offsetWidth(),
                        offset1 = preW-min,
                        offset2 = nextW-min;

                        if(offset1<0)offset1=0;
                        if(offset2<0)offset2=0;

                    profile._bg=null;
                    profile._limited=0;
                    linb.use(src).startDrag(e,{
                        dragType:'copy',
                        targetReposition:false,
                        targetCSS:{background:"none"},
                        horizontalOnly:true,
                        widthIncrement:10,
                        maxLeftOffset:offset1,
                        maxRightOffset:offset2,
                        dragCursor:cursor
                    });
                    
                },
                onDrag:function(profile, e, src){
                    var p=linb.DragDrop.getProfile();
                    if(p.x<=p.restrictedLeft || p.x>=p.restrictedRight){
                        if(!profile._limited){
                            profile._bg=linb.use(src).css('backgroundColor');
                            linb.use(src).css('backgroundColor','#ff6600');
                            profile._limited=true;
                        }
                    }else{
                        if(profile._limited){
                            linb.use(src).css('backgroundColor',profile._bg);
                            profile._limited=0;
                        }
                    }
                    profile._pre.width(profile._preW + p.offset.x);
                    profile._next.width(profile._nextW - p.offset.x);
                },
                onDragstop:function(profile, e, src){
                    var arr=profile.getSubNode('ITEM',true).get(),
                        n=linb.use(src),
                        l=profile.getSubNode('ITEMS').width(),
                        a=[],t,
                        k=0;

                    _.arr.each(arr,function(o,i){
                        if(i!=arr.length-1)
                            a[i]=linb([o]).offsetWidth();
                    });
                    _.arr.each(arr,function(o,i){
                        if(i!=arr.length-1){
                            t=((a[i]/l)*100).toFixed(4);
                            k += +t;
                            a[i]=o.style.width = t + '%';
                        }
                    });
                    a[arr.length-1]=arr[arr.length-1].style.width = (99-k).toFixed(4) + '%';
                    
                    if(profile._limited){
                        n.css('backgroundColor',profile._bg);
                        profile._limited=0;
                    }
                    if(profile.onColResize)profile.boxing().onColResize(profile, a);
                }
            },
            onMousemove:function(profile,e){
                if(profile.$$ondrag){
                    var prop=profile.properties;
                    if(prop.disabled)return;
                    
                    if(linb.DragDrop.getProfile().isWorking){
                        var box=profile.box,
                            height=profile.$$height,
                            dragid = profile.$$dragitemid,
                            rst=box._checkpos(profile,linb.Event.getPos(e));
                        if(rst){
                            var col=rst[0],
                                row=rst[1],
                                rowup=rst[2];
                            if(col){
                                if(row)
                                    profile.$$droppable=box._checkDroppable(profile, rowup?2:3, linb(row), height, dragid);
                                else
                                    profile.$$droppable=box._checkDroppable(profile, 1, linb(col), height, dragid);
                            }else{
                                box._setNoDroppable(profile);
                                delete profile.$$droppable;
                            }
                        }
                    }
                }
            }
        },
        DataModel:{
            position:'absolute',
            dock:'fill',
            listKey:null,
            width:200,
            height:200,
            minWidth:150,
            disabled:{
                ini:false,
                action: function(v){
                    // no ui 
                }
            },
            items:[
                {id:'1',width:'30.4%'},
                {id:'2',width:'30.4%'},
                {id:'3',width:'38.2%',_display:'display:none'}
            ]
        },
        EventHandlers:{
            onColResize:function(profile, sizes){},
            onRelayout:function(profile){}
        },
        _preparePosSizeEtc:function(profile){
            var root=profile.getRoot(),
                items=profile.getSubNode('ITEM',true),
                w=0,h=0,ns,i,t,

                rootPos=root.offset(),
                rootSize=root.cssSize(),
                colsWidthData=[],
                rowsHeightData=[];

            // gets contrl's pos / size, and inner widgets' cols/rows data for dragDrop
            items.each(function(o){
                w=w+linb(o).offsetWidth();
                colsWidthData.push([w, o.lastChild.id]);
                //get panel's children
                ns=o.lastChild.childNodes;
                h=0;
                rowsHeightData.push([]);
                for(i=0;t=ns[i];i++){
                    //ignore node without id/not uiprovile/
                    if(!t.id || !linb.UIProfile.getFromDom(t) || !t.style || t.style.display=='none' || t.style.visibility=='hidden')continue;
                    h=h+t.offsetHeight;
                    rowsHeightData[rowsHeightData.length-1].push([h,t.id]);
                }
            });
            profile._cachePosSizeData = [rootPos, rootSize, colsWidthData, rowsHeightData];
            
            profile._ddup=profile._ddid=profile._ddincol=profile._ddi==null;
        },
        _checkpos:function(profile, pos, force){
            var _data=profile._cachePosSizeData,
                rootPos=_data[0],
                rootSize=_data[1],
                colsWidthData=_data[2],
                rowsHeightData=_data[3],
                
                changed;

            var col,
                left = pos.left-rootPos.left,
                top = pos.top-rootPos.top,
                i=0, temp,
                t, to=0,
                arr;

            while(t=colsWidthData[i++]){
                if(left<t[0]){
                    if(profile._ddincol===t[1])
                        break;
                    changed=true;
                    profile._ddi=i-1;
                    profile._ddincol=t[1];
                    //if col changed, clear row vars
                    profile._ddid=profile._ddup=null;
                    break;
                }
            }
            if(profile._ddi!==null){
                col=profile._ddincol;
                arr=rowsHeightData[profile._ddi];
                i=0;
                while(t=arr[i++]){
                    if(top<t[0]){
                        //if raw changed, clear pos
                        if(profile._ddid!==t[1])
                            profile._ddup=null;
                        j=(top < (to+(t[0]-to)/2));
                        if(profile._ddid===t[1] && profile._ddup===j)
                            break;
                        profile._ddid=t[1];
                        profile._ddup=j;
                        changed=true;
                        break;
                    }
                    to=t[0];
                }
                if(changed || force)
                    return [col,profile._ddid,profile._ddup];
            }else{
                if(changed || force)
                    return [null];
                else
                    return;
            }
        },
        _checkDroppable:function(profile, type, node, height, dragid){
            var self=this,
                candrop=false,
                proxy= profile._proxy || (profile._proxy=linb.create('<div style="border:1px dashed #FF0000;">'));

            proxy.height(height||20);
            if(node.isEmpty())return;
            if(type===1){
                if(node.last().isEmpty() || node.last().id()!=dragid){
                    node.append(proxy);
                    candrop=true;
                }
            }else if(type===2){
                if(node.id()!=dragid){
                    if(node.prev().isEmpty() || node.prev().id()!=dragid){
                        node.addPrev(proxy);
                        candrop=true;
                    }
                }
            }else{
                if(node.id()!=dragid){
                    if(node.next().isEmpty() || node.next().id()!=dragid){
                        node.addNext(proxy);
                        candrop=true;
                    }
                }
            }
            if(candrop){
                linb.DragDrop.setDragIcon('add');
                return true;
            }else{
                self._setNoDroppable(profile);
                return false;
            }
        },
        _setNoDroppable:function(profile){
            if(profile._proxy){
                profile._proxy.remove();
                delete profile._proxy;
            }
            profile._ddup=profile._ddid=profile._ddincol=profile._ddi==null;
            linb.DragDrop.setDropFace();
        },
        
        _onDropMarkShow:function(){ 
            return false;
        },
        _onDropMarkClear:function(profile){
            profile.box._setNoDroppable(profile);
        },
        _onDragEnter:function(profile,e,src){
            var ddId=linb.DragDrop.getProfile().$id;
            if(profile.$$ddfalg != ddId){
                profile.$$ddfalg = ddId;
                profile.box._preparePosSizeEtc(profile);
            }
            
            var targetPrf = linb.DragDrop.getProfile().dragData.profile;

            // inner panel
            if(targetPrf &&  targetPrf.parent==profile){
                profile.$$dragitemid=linb.DragDrop.getProfile().dragData.profile.domId;
                profile.$$height=linb.DragDrop.getProfile().dragData.profile.getRoot().offsetHeight();
            }
            profile.getSubNode('COVER').css({display:'block'});
            profile.$$ondrag=true;

            delete profile.$$dropalbe;
        },
        _onDragLeave:function(profile){
            profile.getSubNode('COVER').css({display:'none'});
            delete profile.$$dragitemid;
            delete profile.$$height;
            delete profile.$$ondrag;
        },
        _onDrop:function(profile, e){
            if(profile.$$droppable){
                var rst=profile.box._checkpos(profile, linb.Event.getPos(e), true),
                    ddd=linb.DragDrop.getProfile().dragData,
                    targetPrf=ddd.profile,
                    exists = targetPrf.parent==profile;

                if(rst && rst[0]){
                    var col=profile.getItemIdByDom(rst[0]),
                        base=linb.UIProfile.getFromDom(rst[1]),
                        before=rst[2];
                    if(col){
                        if(exists){
                            // move only
                            profile.boxing().movePanel(targetPrf,col,base,before);
                        }else{
                            // add
                            profile.boxing().addPanel(ddd.data.properties,ddd.data.events,col,base,before);
                        }
                    }
                }
            }
            profile.getSubNode('COVER').css({display:'none'});
            profile.box._setNoDroppable(profile);
            delete profile._cachePosSizeData;
            delete profile.$$height;
            delete profile.$$ondrag;
        },

        _prepareData:function(profile){
            profile.properties.dropKeys = profile.box.KEY+":"+profile.$linbid;
            return arguments.callee.upper.call(this, profile);
        },
        _onresize:function(profile,width,height){
        }
    }
});
//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');

                    /*if(itemId){
                        var o = getN("ROW",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'||p.selMode=='multibycheckbox'){
                    uiv = uiv?(''+uiv).split(p.valueSeparator):[];
                    value = value?(''+value).split(p.valueSeparator):[];
                    //check all
                    _.arr.each(uiv,function(o){
                        getN(k, getI(o)).tagClass('-checked',false)
                    });
                    _.arr.each(value,function(o){
                        getN(k, getI(o)).tagClass('-checked')
                    });
                    // clear the header's row handler checkbox
                    if(value.length===0){
                        getN("HFMARK").tagClass('-checked',false);
                        delete profile._$checkAll;
                    }
                }
            });
        },
        /*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._inited)return;
            }
            if(!arr)
                arr=[];

            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;

            _.breakO(profile.colMap,2);

            if(!header)
                header=[];

            header=profile.box._adjustHeader(header);

            var arr = profile.box._prepareHeader(profile, header);

            pro.header = header;
            this.removeAllRows();
            profile.getSubNode('HCELL', true).remove();
            if(arr.length)
                profile.getSubNode('HCELLS').append(profile._buildItems('header', arr));

            profile.box._ajdustBody(profile);

            // clear collist cache
            if(profile.$col_pop){
                profile.$col_pop.destroy();
                delete profile.$col_pop;
            }
            //clear editor cache
            _.each(profile.$cache_editor,function(o){
                o.destroy();
            });
            profile.$cache_editor={};
        },
        _toggleRows:function(rows, expend){
            var self=this;
            if(rows && rows.length)
                _.arr.each(rows,function(o){
                    self.toggleRow(o.id, expend);
                });
        },
        autoRowHeight:function(rowId){
            return this.each(function(prf){
                if(prf.renderId ){
                    if(rowId && prf.rowMap2[rowId])
                        prf.getSubNode('FHANDLER',prf.rowMap2[rowId]).onDblclick(true);
                    else
                        _.each(prf.rowMap,function(o,i){
                            prf.getSubNode('FHANDLER',i).onDblclick(true);
                        });
                }
            });
        },
        autoColWidth:function(colId){
            return this.each(function(prf){
                if(prf.renderId){
                    if(colId && prf.colMap2[colId])
                        prf.getSubNode('HHANDLER',prf.colMap2[colId]).onDblclick(true);
                    else
                        _.each(prf.colMap,function(o,i){
                            prf.getSubNode('HHANDLER',i).onDblclick(true);
                        });
                }
            });
        },
        addHotRow:function(){
            var prf=this.get(0);
            if(prf.renderId)
                prf.box._addTempRow(prf);
            return this;
        },
        removeHotRow:function(){
            var profile=this.get(0);
            profile.box._sethotrowoutterblur(profile,true);
            delete profile.__hastmpRow;
            this.removeRows([profile.box._temprowid]);
            return this;
        },
        isDirtied:function(){
            var dirty=false;
            _.each(this.get(0).cellMap,function(v){
                if(v.oValue!==v.value){
                    dirty=true;
                    return false;
                }
            });
            return dirty;
        },
        _getObjByDom:function(src, type){
            var prf=this.get(0),
                subId=prf.getSubId(typeof src=='string'
                    ? src.charAt(0)=='!'
                        ? ((src=linb.use(src).get(0))&&src.id)
                        : src
                    : src.id );
            return prf[type=="row"?"rowMap":type=="col"?"colMap":"cellMap"][subId];
        },
        getRowByDom:function(src){
            return this._getObjByDom(src, "row");
        },
        getHeaderByDom:function(src){
            return this._getObjByDom(src, "col");
        },
        getCellByDom:function(src){
            return this._getObjByDom(src, "cell");
        },
        /*rows related*/
        //type: 'original', 'data', 'min'
        getRows:function(type){
            var v=this.get(0).properties.rows,a,b;
            if(type=='data'||type=='min'){
                a=_.clone(v,true);

                if(a&&a.length&&a[a.length-1]&&a[a.length-1].id==this.constructor._temprowid)
                    a.pop();

                if(type=='min'){
                    _.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;
        },
        getRowbyRowId:function(rowId, type){
            var profile=this.get(0),v=profile.rowMap2[rowId];
            v=v?profile.rowMap[v]:null;
            if(v){
                if(type=='data')
                    return _.clone(v,true);
                else if(type=='min'){
                    var a=_.clone(v,true),b;
                    _.each(b=a=a.cells,function(v,j){
                        b[j] = v.value;
                    });
                    return a;
                }else
                    return v;
            }
        },
        getRowbyCell:function(cell, type){
            var v=cell._row;
            if(v){
                if(type=='data')
                    return _.clone(v,true);
                else if(type=='min'){
                    var a=_.clone(v,true),b;
                    _.each(b=a=a.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);
            return this;

        },
        updateRow:function(rowId,options){
            var ns=this, profile=ns.get(0), orow=ns.getRowbyRowId(rowId), nid;
            if(orow){
                var rid=orow._serialId, t,tt;
                if(typeof options!='object') options={caption:options};
                else _.filter(options,true);
                
                // [[modify id
                if(_.isSet(options.id))options.id+="";
                if(options.id && options.id!==rowId){
                    nid=options.id;
                    var m2=profile.rowMap2, v;
                    if(!m2[nid]){
                        if(v=m2[rowId]){
                            m2[nid]=v;
                            delete m2[rowId];
                            profile.rowMap[v].id=nid;
                            // modify cells link
                            _.each(profile.colMap,function(o){
                                if(o=o._cells){
                                    o[nid]=o[rowId];
                                    delete o[rowId];
                                }
                            });
                        }
                    }
                }else{
                    options.id=rowId; 
                }
                // modify id only
                if(_.isEmpty(options))
                    return ns;
                //]]

                // need to refresh
                if(('group' in options && options.group!=orow.group) ||
                    'cells' in options ||
                    ('sub' in options && 
                    // only try to show/hide toggle icon
                    !((options.sub===true && !orow.sub) || (!options.sub && orow.sub===true)))
                ){
                    var id="__special",pid=orow._pid?profile.rowMap[orow._pid].id:null;
                    // change id in rowMap
                    orow.id=id;
                    // change link in rowMap2
                    profile.rowMap2[id]=profile.rowMap2[nid||rowId];
                    delete profile.rowMap2[nid||rowId];
                    // remove cells link
                    _.each(profile.colMap,function(o){
                        if(o=o._cells)
                            delete o[nid||rowId];
                    });
                    // make sure data
                    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]);
                    
                    if(profile.properties.activeMode=='row'){
                        var uiv=profile.properties.$UIvalue||"", arr=(''+uiv).split(profile.properties.valueSeparator);
                        if(arr.length && _.arr.indexOf(arr, rowId)!=-1){
                            if(nid)
                                _.arr.removeValue(arr, rowId);
                            ns.setUIValue(arr.join(profile.properties.valueSeparator), true);
                        }
                    }
                    
                }else{
                    if('sub' in options){
                        t=ns.getSubNode('ROWTOGGLE',rid);
                        if(options.sub)
                            t.removeClass('linb-uicmd-empty').addClass('linb-uicmd-toggle2')
                        else
                            t.removeClass('linb-uicmd-toggle2').addClass('linb-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(options.hasOwnProperty('disabled')){
                        var cls=profile.getClass('CELLS', '-disabled');
                        if(options.disabled)
                            ns.getSubNode('CELLS',rid).addClass(cls);
                        else
                            ns.getSubNode('CELLS',rid).removeClass(cls);
                    }
                    if(options.hasOwnProperty('readonly')){
                        var cls=profile.getClass('CELLS', '-readonly');
                        if(options.readonly)
                            ns.getSubNode('CELLS',rid).addClass(cls);
                        else
                            ns.getSubNode('CELLS',rid).removeClass(cls);
                    }
                    if(t=options.firstCellStyle)
                        (tt=ns.getSubNode('FCELL',rid)).fisrt().attr('style',tt.attr('style')+";"+t);
                    if(t=options.firstCellClass)
                        ns.getSubNode('FCELL',rid).fisrt().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');
                }
            }else{
                var rst=ns.get(0).queryItems(ns.getRows(),function(o){return typeof o=='object'?o.id===rowId:o==rowId},true,true,true);
                if(rst.length)
                    _.merge(rst[0][0], options, 'all');
            }
            return ns;
        },
        //pid,base are id
        insertRows:function(arr, pid, base ,before){
            if(!arr || !_.isArr(arr) || arr.length<1)return this;

            var c=this.constructor, 
                profile=this.get(0), 
                pro=profile.properties, 
                row_m=profile.rowMap2, 
                b=profile.rowMap,
                tar, t, k;

            pid = row_m[pid];

            base = row_m[base];
            if(base){
                t=profile.rowMap[base];
                if(t)pid=t._pid;
            }
            arr=c._adjustRows(arr);
            if(!pid)
                tar = (pro.rows || (pro.rows=[]));
            else{
                k=b[pid];
                tar = _.isArr(k.sub)?k.sub:(k.sub=[]);
            }

            //1
            var rows;
            if(profile.renderId){
                // if insert to root, or the parent node is inited
                if(!pid || k._inited){
                    //prepareData(add links)
                    rows = c._prepareItems(profile, arr, pid);
                    this._insertRowsToDom(profile, rows, pid, base, before);
                }
            }
            //2
            //must be here
            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));
            }
            //3
            if(profile.renderId){
                if(!pro.iniFold)
                    profile.boxing()._toggleRows(rows,true);
                profile.box._asy(profile);
            }

            // if hot row exists, ensure it's the last one
            if(profile.renderId&&profile.__hastmpRow){
                var rows=profile.properties.rows;
                if(rows[rows.length-1].id!=profile.box._temprowid)
                    profile.box.__ensurehotrow(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[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 UI value
            if(v=p.$UIvalue){
                if((v=(''+v).split(p.valueSeparator)).length>1){
                    _.filter(v,function(o){
                        return _.arr.indexOf(ids,o)==-1;
                    });
                    p.$UIvalue=v.join(p.valueSeparator);
                }else{
                    if(_.arr.indexOf(ids,p.$UIvalue)!=-1)
                        p.$UIvalue=null;
                }
            }
            linb(nodes).remove();

            // remove activerow/cell
            if(profile.$activeCell && !linb.Dom.byId(profile.$activeCell))
                delete profile.$activeCell;
            if(profile.$activeRow && !linb.Dom.byId(profile.$activeRow))
                delete profile.$activeRow;

            //clear rows cache
            delete profile.$allrowscache;
            
            profile.box._asy(profile);
            
            if(profile.renderId&&profile.__hastmpRow){
                profile.box.__ensurehotrow(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={};

            // remove activerow/cell
            delete profile.$activeCell;
            delete profile.$activeRow;

            profile.properties.rows.length=0;
            if(profile.renderId){
                profile.getSubNode('BODY').empty();
                profile.getSubNode('SCROLL').scrollTop(0).scrollLeft(0);
                // ensure the column header scroll to zero
                // code must same to the SCROLL->onScroll event
                if(profile.$sl!=0)
                    profile.getSubNode('HEADER').get(0).scrollLeft=profile.$sl=0;
            }
            //clear rows cache
            delete profile.$allrowscache;
            profile.properties.$UIvalue=null;

            if(profile.renderId&&profile.__hastmpRow){
                profile.box.__ensurehotrow(profile);
            }
            
            return this;
        },
        resetRowValue:function(rowId){
            var profile=this.get(0),row=this.getRowbyRowId(rowId),arr=[],prop=profile.properties;
            _.arr.each(row.cells,function(o){
                if(o.oValue!==o.value){
                    o.oValue=o.value;
                    delete o.dirty;
                    if(prop.dirtyMark)
                        arr.push(profile.getSubNode('CELLA',o._serialId).get(0));
                }
            });
            if(prop.dirtyMark && prop.showDirtyMark)
                linb(arr).removeClass('linb-ui-dirty');
        },
        resetColValue:function(colId){
            var profile=this.get(0),col=this.getHeaderByColId(colId),arr=[],prop=profile.properties;
            _.arr.each(col.cells,function(o){
                if(o.oValue!==o.value){
                    o.oValue=o.value;
                    delete o.dirty;
                    if(prop.dirtyMark)
                        arr.push(profile.getSubNode('CELLA',o._serialId).get(0));
                }
            });
            if(prop.dirtyMark && prop.showDirtyMark)
                linb(arr).removeClass('linb-ui-dirty');
        },
        getActiveRow:function(){
            var ar,profile=this.get(0);
            if(profile.properties.activeMode!='row')return;
            if(!(ar=profile.$activeRow))return;
            ar=profile.rowMap[profile.getSubId(ar)];
            if(ar && ar.id && ar.id==profile.box._temprowid){
                ar=null;
            }
            return ar;
        },
        setActiveRow:function(rowId){
            var dr, row, profile=this.get(0);            
            if(profile.properties.activeMode!='row')return;
            // deative first
            profile.box._activeRow(profile, false);

            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;
        },
        getHeaderByColId:function(colId, type){
            var v=this.get(0).properties.header,
                i=_.arr.subIndexOf(v,"id",colId);
            return i==-1?null:
                type=='data'?_.clone(v[i],true):
                type=='min'?v[i].id:
                v[i];
        },
        getHeaderByCell:function(cell, type){
            var v=cell._col;
            return !v?null:
                type=='data'?_.clone(v,true):
                type=='min'?v.id:
                v;
        },

        updateHeader:function(colId,options){
            var ns=this, colh=ns.getHeaderByColId(colId);
            if(colh){
                var hid=colh._serialId, t, tt;

                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');
                }

                //  Forward-compatible with 'visibility'
                if(options.hasOwnProperty('visibility') && !options.hasOwnProperty('hidden'))
                    options.hidden=!options.visibility;

                if('hidden' in options){
                    var  b = !!options.hidden;
                    if(b){
                        if(colh.hidden!==true){
                            ns.showColumn(colId, false);
                        }
                    }else{
                        if(colh.hidden===true){
                            ns.showColumn(colId, true);
                        }
                    }
                }

                _.merge(colh, options, 'all');
            }
            return ns;
        },
        showColumn:function(colId, flag){
            var profile=this.get(0),
                map=profile.colMap2,
                    cols=profile.colMap,
                    col,
                    sid,
                    cells,
                    n=[];
                if(col=cols[sid=map[colId]]){
                if(profile.beforeColShowHide && false===profile.boxing().beforeColShowHide(profile,colId,flag))
                    return false;

                    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.hidden=(flag===false?true:false))?'none':'');
                
                if(profile.afterColShowHide)
                    profile.boxing().afterColShowHide(profile,colId,flag);
                }
                profile.box._ajdustBody(profile);
            return true;
        },
        sortColumn:function(colId, desc, sortby){
            var prf=this.get(0), sId=prf.colMap2[colId],col=prf.colMap[sId];
            if(sId && col){
                if(_.isBool(desc))
                    col._order=!desc;
                if(_.isFun(sortby))
                    col.sortby=sortby;
                prf.getSubNode("HCELLA",sId).onClick();
            }
            return this;
        },
        /*cell realted*/
        getCell:function(cellId, type){
            var self=this,profile=this.get(0),v;
            _.each(profile.cellMap,function(o){
                if(o.id && o.id===cellId){
                    cellId=o._serialId;
                    return false;
                }
            });
            v=profile.cellMap[cellId];
            return !v?null:
                    type=='data'? _.merge({rowId:v._row.id, colId:v._col.id},_.clone(v,true)):
                    type=='min'? v.value:
                    v;
        },
        getCellbyRowCol:function(rowId, colId, type){
            var profile=this.get(0),v;
            v=_.get(profile.rowMap,[profile.rowMap2[rowId], '_cells',colId]);
            v=v && profile.cellMap[v];
            return !v?null:
                    type=='data'? _.merge({rowId:v._row.id, colId:v._col.id},_.clone(v,true)):
                    type=='min'? v.value:
                    v;
        },
        getCells:function(rowId, colId, type){
            var map={};
            _.each(this.get(0).cellMap,function(v){
                if((rowId?(rowId==v._row.id):1) && (colId?(colId==v._col.id):1)){
                    map[v.id]= type=='data'?_.merge({rowId:v._row.id, colId:v._col.id},_.clone(v,true)):
                               type=='min' ? v.value:
                               v;
                }
            });
            //dont return inner value
            return map;
        },

        updateCellByRowCol:function(rowId, colId, options, dirtyMark, triggerEvent){
            var t,self=this,con=self.constructor;
            if(t=con._getCellId(self.get(0), rowId, colId))
                con._updCell(self.get(0), t, options, dirtyMark, triggerEvent);
            return self;
        },
        updateCell:function(cellId, options, dirtyMark, triggerEvent){
            var self=this,profile=this.get(0);
            _.each(profile.cellMap,function(o){
                if(o.id && o.id===cellId){
                    cellId=o._serialId;
                    return false;
                }
            });
            self.constructor._updCell(profile,cellId,options, dirtyMark, triggerEvent);
            return self;
        },
        editCellbyRowCol:function(rowId, colId){
            var profile=this.get(0),con=profile.box;
            con._editCell(profile, con._getCellId(profile, rowId, colId));
            return this;
        },
        editCell:function(cell){
            this.constructor._editCell(this.get(0), cell);
            return this;
        },
        offEditor:function(){
            var profile=this.get(0),editor;
            if(profile&&profile.$curEditor){
                editor=profile.$curEditor;
                _.tryF(editor.undo,[],editor);
            }
        },
        focusCellbyRowCol:function(rowId, colId){
            var profile=this.get(0),con=profile.box,
                cellId=con._getCellId(profile, rowId, colId);
            profile.getSubNode('CELLA', cellId).focus(true);
            return this;
        },
        focusCell:function(cell){
            var cellId=cell._serialId;
            this.get(0).getSubNode('CELLA', cellId).focus(true);
            return this;
        },
        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;
            // deative first
            profile.box._activeCell(profile, false);

            if(typeof rowId=='object')
                cell=rowId;
            else
                cell=this.getCellbyRowCol(rowId, colId);
            
            if(!cell)
                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){
                var prop=profile.properties;
                _.each(profile.cellMap,function(v){
                    v.oValue=v.value;
                    delete v.dirty;
                });
                if(prop.dirtyMark && prop.showDirtyMark)
                    profile.getSubNode('CELLA',true).removeClass('linb-ui-dirty');
            })
        },
        getDirtied:function(rowId, colId){
            var map={};
            _.each(this.get(0).cellMap,function(v){
                if(v.oValue!==v.value &&(rowId?(rowId==v._row.id):1) &&(colId?(colId==v._col.id):1)){
                    map[v.id]={rowId:v._row.id, colId:v._col.id, value:v.value, oValue:v.oValue};
                }
            });
            //dont return inner value
            return map;
        },
        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}',
            className:'{_className}',
            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};',
                                    className:'{cellCls}',
                                    HCELLA:{
                                        style:'{firstCellStyle};',
                                        className:'{firstCellClass}',
                                        HHANDLER:{
                                            tagName:'div',
                                            style:'{colDDDisplay}'
                                        },
                                        FHANDLER:{
                                            tagName:'div',
                                            style:'{rowDDDisplay}'
                                        },
                                        HFMARK:{
                                            className:"linb-uicmd-check",
                                            style:'{_rowMarkDisplay}'
                                        },
                                        GRIDCAPTION:{
                                            $order:2,
                                            text:'{gridHandlerCaption}'
                                        },
                                        SORT:{
                                            style:'{sortDisplay}'
                                        }
                                    }
                                },
                                OTHERHCELLS:{
                                    $order:1,
                                    tagName:'text',
                                    text:'{header}'
                                }
                            }
                        }
                    },
                    SCROLL:{
                        $order:1,
                        tagName:'div',
                        className:'linb-uibg-base ',
                        BODY:{
                            tagName:'div',
                            text:'{rows}'
                        }
                    },
                    FOOTER:{
                        $order:2
                    },
                    COLLIST:{
                        tagName:'div'
                    },
                    ARROW:{}
                }
            },
            $submap : {
                /*the other header in table header*/
                header:{
                    HCELL:{
                        style:"width:{width}px;{colDisplay};",
                        className:'{cellCls}',
                        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};',
                                className:'{cellCls}',
                                CELLA:{
                                    tabindex: '{_tabindex}',
                                    style:'{cellStyle}{firstCellStyle}',
                                    className:'{cellClass}{firstCellClass}',
                                    ROWLRULER:{
                                        style:'{_treeMode};width:{_rulerW}px'
                                    },
                                    ROWTOGGLE:{
                                        $order:2,
                                        style:'{_treeMode};',
                                        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:{
                            className:'{cellClass}',
                            style:'{bgcolor};{color};{cellStyle}',
                            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:{
                            className:'{cellClass}',
                            style:'{cellStyle}',
                            tabindex: '{_tabindex}',
                            CHECKBOX:{
                                className:'{checkboxCls}'
                            }
                        }
                    }
                },
                'rows.cells.progress':{
                    CELL:{
                        style:'width:{width}px;{cellDisplay}',
                        className:'{cellCls}',
                        CELLA:{
                            className:'{cellClass}',
                            style:'{cellStyle}',
                            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'
            },
            ARROW:{
                position:'absolute',
                'z-index':'20',
                left:0,
                top:0,
                display:'none',
                width:'14px',
                height:'18px',
                background:  linb.UI.$bg('icons.gif', 'no-repeat -72px -270px', true)
            },
            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',
                'padding-bottom':'1px',
                left:0,
                top:'0',
                'font-size':0,
                'line-height':0
            },
            '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.img_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:{
                'border-bottom': '1px solid #A2BBD9'
            },
            'CELLS-group':{
                $order:1,
                'border-right': '1px solid #A2BBD9'
            },
            'CELLS-group FCELL':{
                'border-right':0,
                'padding-right':'1px',
                overflow:'visible'
            },
            'CELLS-group FCELLCAPTION, CELLS-group CELLA, CELLS-group FCELLINN':{
                'font-weight':'bold',
                color:'#3764A0',
                overflow:'visible'
            },
            'PREVIEW,SUMMARY':{
                position:'relative',
                display:'none',
                'padding-left':'16px',
                'border-right': '1px solid #A2BBD9'
            },
            PREVIEW:{
                $order:4,
                'border-bottom': '1px solid #A2BBD9'
            },
            SUMMARY:{
                $order:4,
                'border-bottom': '1px solid #A2BBD9'
            },
           'CELLS-mouseover':{
                $order:4,
                'background-color':'#DFE8F6'
            },
            
            'CELLS-readonly CELLA':{
                 $order:5,
                 color:'#808080'
            },            
            'CELL-readonly CELLA':{
                 $order:6,
                 color:'#808080'
            },
            'CELLS-disabled':{
                 $order:7,
                 'background-color':'#EBEADB'
            },
            'CELLS-disabled CELLA':{
                 $order:7,
                 color:'#808080'
            },
            'CELL-disabled':{
                 $order:8,
                 'background-color':'#EBEADB'
            },
            'CELL-disabled CELLA':{
                 $order:8,
                 color:'#808080'
            },
            
            'CELLS-active, CELL-active':{
                 $order:5,
                 'background-color':'#A3BAE9'
            },
            "CELLS-hot":{
                $order:6,
                'background-color':'#FFE97F'
            },
            'CELLS-checked, CELL-checked, CELLS-checked CELLA, CELL-checked CELLA':{
                 $order:6,
                'background-color':'#7199E8',
                color:'#fff'
            },
            "FCELL CELLA":{
                'text-align': 'left'
            },
            "HFCELL HCELLA":{
                'text-align': 'center'
            },
            FHANDLER:{
                position:'absolute',
                'height':'4px',
                left:'0px',
                width:'100%',
                bottom:'0px',
                cursor:'n-resize',
                'z-index':10,
                'font-size':0,
                'line-height':0
            },
            'FCELLCAPTION, FCELLINN':{
                'vertical-align':'middle',
                overflow:'hidden'
            },
            'HFCELL, HCELL':{
               background:  linb.UI.$bg('head.gif', '#CAE3FF repeat-x left top'),
               height:'100%',
               'border-left':'1px solid #fff',
               'border-top':'1px solid #fff',
               'border-right':'1px solid #A2BBD9',
               'border-bottom':'1px solid #A2BBD9',
               padding:0,
               'vertical-align':'top',
                'font-size':'12px',
                'line-height':'14px'
            },
            'HFCELL-mouseover, 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,
                '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, CELL-spin, CELL-currency':{
                'text-align':'right'
            },
            'CELL-checkbox':{
                'text-align':'center'
            },
            'CELL-button CELLA':{
                width:'100%'
            },
            'CELL-mouseover':{
                $order:5,
                'background-color':'#DFE8F6'
            },
            'FCELL CELLA, HCELLA':{
                position:'relative'
            },
            HCELLA:{
                'text-align': 'center'
            },
            'HCELLA, CELLA':{
                display:'block',
                overflow:'hidden',
                '-moz-box-flex':'1',
                'outline-offset':'-1px',
                '-moz-outline-offset':(linb.browser.gek && parseInt(linb.browser.ver)<3)?'-1px !important':null,
                height:'100%',
                color:'#000',
                //ie need this
                width:linb.browser.ie?'100%':'',
                'line-height':'20px'
            },
            'CELLA-inline':{
                $order:5,
                display:linb.$inlineBlock,
                width:'auto',
                '-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:linb.browser.ie?1:null,
                height:0,
                position:'relative',
                overflow:'hidden',
                'font-size':'1px',
                //1px for ie8
                'line-height':'1px'
            }
        },
        _objectProp:{tagVar:1,rowOptions:1,colOptions:1},
        Behaviors:{
            HoverEffected:{ROWTOGGLE:'ROWTOGGLE', HCELL:'HCELL', HFCELL:'HFCELL'},
            ClickEffected:{ROWTOGGLE:'ROWTOGGLE', CELL:'CELL', HCELL:'HCELL'},
            DroppableKeys:['SCROLL','CELLS','ROWTOGGLE'],
            DraggableKeys:['FCELL'],

            onSize:linb.UI.$onSize,
            HFMARK:{
                onClick:function(profile,e,src){
                    if(profile.properties.selMode!='multi'&&profile.properties.selMode!='multibycheckbox')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(profile.properties.valueSeparator));
                    }
                    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){
                    if(linb.Event.getBtn(e)!='left')return;
                    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)];

                    if(profile.beforeColResized && false===profile.boxing().beforeColResized(profile,col?col.id:null,w)){
                        profile._limited=0;
                        return;
                    }

                    o.width(w);
                    if(col)col.width=w;

                    //collect cell id
                    var ids=[],ws=[];
                    if(profile.getKey(linb.use(src).parent(2).id())==profile.keys.HFCELL){
                        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);
                    }

                    if(profile.afterColResized)
                        profile.boxing().afterColResized(profile,col?col.id:null,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(2).id())==profile.keys.HFCELL){
                        profile.box._setRowHanderW(profile,true);
                        return;
                    }
                    if(profile.getRootNode().clientHeight<=0)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;

                    if(profile.beforeColResized && false===profile.boxing().beforeColResized(profile,header?header.id:null,w))
                        return;

                    linb(ns).parent().width(w);
                    linb.use(src).parent(2).width(header.width=w);
                    linb(ns).removeClass(cls);

                    if(profile.afterColResized)
                        profile.boxing().afterColResized(profile,header.id,w);

                    profile.box._ajdustBody(profile);
                    return false;
                }
            },
            //row resizer
            FHANDLER:{
                onMousedown:function(profile, e, src){
                    if(linb.Event.getBtn(e)!='left')return;
                    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;
                    
                    if(profile.beforeRowResized && false===profile.boxing().beforeRowResized(profile, row?row.id:null, h)){
                        profile._limited=0;
                        return;
                    }

                    o.height(h);
                    if(profile.getKey(linb.use(src).parent(2).id())==profile.keys.HFCELL){
                        profile.properties.headerHeight=h;
                        linb.UI.$tryResize(profile,null,profile.getRoot().height(),true);
                    }else
                        row.height=h;
                        
                    if(profile.afterRowResized)
                        profile.boxing().afterRowResized(profile, row?row.id:null, h);

                    profile._limited=0;
                },
                onDblclick:function(profile, e, src){
                    var p = profile.properties,
                        sid = profile.getSubId(src),
                        row,cells;
                    if(profile.getRootNode().clientHeight<=0)return;
            
                    if(sid){
                        row=profile.rowMap[sid];
                        cells=profile.getSubNode('CELLS', sid);
                        var h=cells.height('auto').height();
                        
                        if(profile.beforeRowResized && false===profile.boxing().beforeRowResized(profile, row.id, h))
                            return;

                        cells.height(row.height=h);
                    }else{
                        cells=profile.getSubNode('HCELLS');
                        var h=cells.height('auto').height();
                    
                        if(profile.beforeRowResized && false===profile.boxing().beforeRowResized(profile, null, h))
                            return;

                        cells.height(profile.properties.headerHeight=h);
                        
                        linb.UI.$tryResize(profile,null,profile.getRoot().height(),true);
                    }

                    if(profile.afterRowResized)
                        profile.boxing().afterRowResized(profile, row?row.id:null, h);
                    
                    return false;
                },
                onClick:function(){return false}
            },
            //mark click for tree build
            ROWTOGGLE:{
                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;
                }
            },
            //HCELLA handler dragdrop
            HCELLA:{
                onClick:function(profile, e, src){
                    var p=profile.properties,
                    id = profile.getSubId(src),
                    col = profile.colMap[id];

                    if(!col){
                        if(profile.onClickGridHandler)
                            profile.boxing().onClickGridHandler(profile,e,src);

                        if(p.disabled)return false;
                        if(!p.colSortable)return;
                    }else{
                        if(p.disabled || col.disabled)return false;
                        if(!(col.hasOwnProperty('colSortable')?col.colSortable:p.colSortable))return;
                    }
                    
                    if(profile.beforeColSorted && false===profile.boxing().beforeColSorted(profile, col))
                        return;
                        
                    var order = (col ? col._order : profile._order) || false,
                    type = (col ? col.type : null) || 'input',
                    sortby = col ? col.sortby : null,
                    index = col ? _.arr.indexOf(p.header,col) :-1,
                    me=arguments.callee,
                    fun = me.fun||(me.fun = function(profile, subNode, index, type, sortby,order,lastrownode){
                        var rows,parent,self=arguments.callee;
                        if(subNode){
                            rows = subNode.sub;
                            parent = profile.getSubNode('SUB', subNode._serialId).get(0);
                        }else{
                            subNode={_inited: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, null);
                             //for short input
                             a1[a1.length]= index==-1 
                                ? row.caption 
                                : (t=row.cells)?(t=t[index])?t.value:'':row[index];
                             a2[a2.length]=a2.length;
                        });
                        if(typeof sortby!='function'){
                            switch(type){
                                case 'number':
                                case 'spin':
                                case 'currency':
                                    ff=function(n){return parseFloat(n)||0};
                                    break;
                                case 'datetime':
                                case 'date':
                                    ff=function(n){return _.isDate(n)?n.getTime():_.isFinite(n)?parseInt(n):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 = subNode._inited, 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);
                                
                            if(lastrownode)
                                parent.insertBefore(fragment, lastrownode);
                            else
                                parent.appendChild(fragment);
                        }
                    });

                    var lastrow,lastrownode;
                    if(profile.__hastmpRow){
                        lastrow=profile.properties.rows.pop();
                        lastrownode=profile.getSubNode('BODY').get(0).lastChild;
                    }

                    fun(profile, null, index, type, sortby,order, lastrownode);

                    if(profile.__hastmpRow)
                        profile.properties.rows.push(lastrow);

                    //show sort mark
                    profile.getSubNode('SORT', true).css('display','none');
                    var node = (col ? profile.getSubNode('SORT', col._serialId) : profile.getSubNode('SORT')).css('display','');
                    node.tagClass('-checked', col ? (!(col._order = !col._order)) : (!(profile._order = !profile._order)));

                    profile.box._asy(profile);

                    //clear rows cache
                    delete profile.$allrowscache;
                    
                    if(profile.afterColSorted)
                        profile.boxing().afterColSorted(profile, col);

                    return false;
                },
                onMousedown:function(profile, e, src){
                    if(linb.Event.getBtn(e)!='left')return;
                    var p=profile.properties;
                    if(p.disabled)return;
                    var col=profile.colMap[profile.getSubId(src)];
                    if(!col)return;
                    if(p.disabled || col.disabled)return false;
                    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:o.parent(),
                        dragCursor:'pointer',
                        targetLeft:pos.left+12,
                        targetTop:pos.top+12,
                        targetReposition:false,
                        dragDefer: 2,
                        dragKey:profile.$linbid + ":col",
                        dragData:o.parent().id()
                    });
                },
                onDragbegin:function(profile, e, src){
                    linb(src).parent().onMouseout(true,{$force:true});
                    linb(src).onMouseup(true);
                },
                beforeMouseover:function(profile, e, src){
                    var p=profile.properties,
                        id = profile.getSubId(src),
                        col = profile.colMap[id];
                    if(!col)return;
                    if(p.disabled || col.disabled)return false;

                    var data=linb.DragDrop.getProfile().dragData;
                    if(!data||data.dragKey!=profile.$linbid + ":col")return;

                    var psrc=linb.use(src).parent().linbid();
                    if(false===profile.box._colDragCheck(profile,psrc))return;
                    linb.DragDrop.setDropElement(src).setDropFace(src,'move');
                    profile.getSubNode("ARROW")
                        .left(linb.use(psrc).get(0).offsetLeft-8)
                        .top(linb.use(psrc).get(0).offsetHeight)
                        .css("display","block");
                },
                beforeMouseout:function(profile, e, src){
                    var p=profile.properties,
                        id = profile.getSubId(src),
                        col = profile.colMap[id];
                    if(!col)return;
                    if(p.disabled || col.disabled)return false;

                    var data=linb.DragDrop.getProfile().dragData;
                    if(!data||data.dragKey!=profile.$linbid + ":col")return;

                    var psrc=linb.use(src).parent().linbid();
                    linb.DragDrop.setDropElement(null).setDropFace(null,'none');
                    if(false===profile.box._colDragCheck(profile, psrc))return;
                    profile.getSubNode("ARROW").css("display","none");
                },
                onDrop:function(profile, e, src){
                    var p=profile.properties,
                    id = profile.getSubId(src),
                    col = profile.colMap[id];
                    if(!col)return;
                    if(p.disabled || col.disabled)return false;

                    var psrc=linb.use(src).parent().linbid();
                    profile.getSubNode("ARROW").css("display","none");
                    if(false===profile.box._colDragCheck(profile, psrc))return;

                    //check dragData
                    var data=linb.DragDrop.getProfile().dragData,
                        fromId = data && profile.getSubId(data),
                        toId = profile.getSubId(psrc);

                    //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(psrc,'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];
                    // 1. insert to right pos
                    _.arr.insertAny(p.header,temp,toIndex);
                    // 2. then, remove
                    _.arr.removeFrom(p.header,fromIndex+(fromIndex>toIndex?1:0));
                    //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,
                    id = profile.getSubId(src),
                    col = profile.colMap[id];

                    if(col){
                        if(p.disabled || col.disabled)return false;
                        if(!(col.hasOwnProperty('colHidable')?col.colHidable:p.colHidable))return;
                    }else{
                        if(p.disabled)return false;
                        if(!p.colHidable)return;
                    }

                    _.resetRun(profile.$linbid+':collist',null);
                    var region={},
                        pos=linb.use(src).parent().offset(null,profile.getSubNode('BOX')),
                        size=linb.use(src).parent().cssSize();
                    if(size.width<16)return;
                    region.height=size.height;
                    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,
                    id = profile.getSubId(src),
                    col = profile.colMap[id];

                    if(col){
                        if(p.disabled || col.disabled)return false;
                        if(!(col.hasOwnProperty('colHidable')?col.colHidable:p.colHidable))return;
                    }else{
                        if(p.disabled)return false;
                        if(!p.colHidable)return;
                    }

                    _.resetRun(profile.$linbid+':collist',function(){
                        profile.getSubNode('COLLIST').css({visibility:'hidden',left:0,top:0});
                    });
                },
                onContextmenu:function(profile, e, src){
                    if(profile.onContextmenu){
                        var sid=profile.getSubId(src);
                        return profile.boxing().onContextmenu(profile, e, src, sid?profile.colMap[sid]:null)!==false;
                    }
                }
            },
            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:o.hidden!==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){
                    var p=profile.properties;
                    if(p.disabled)return;
                    if(p.disableHoverEffect)return;
                    if(p.activeMode=='row')
                        linb.use(src).tagClass('-mouseover');
                },
                afterMouseout:function(profile, e, src){
                    var p=profile.properties;
                    if(p.disabled)return;
                    if(p.disableHoverEffect)return;
                    if(p.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,
                        subid = profile.getSubId(src),
                        ks=profile.keys,
                        row = profile.rowMap[subid],
                        ck=profile.getKey(linb.Event.getSrc(e).id||"");
                    if(p.disabled || row.disabled)return false;
                    if(ck==ks.ROWTOGGLE || ck==ks.MARK) return false;
                    if(row.group) profile.getSubNode('ROWTOGGLE',row._serialId).onClick();
                }
            },
            CELL:{
                afterMouseover:function(profile, e, src){
                    var p=profile.properties;
                    if(p.disabled)return;
                    if(p.disableHoverEffect)return;
                    if(p.activeMode=='cell')
                        linb.use(src).tagClass('-mouseover');
                },
                afterMouseout:function(profile, e, src){
                    var p=profile.properties;
                    if(p.disabled)return;
                    if(p.disableHoverEffect)return;
                    if(p.activeMode=='cell')
                        linb.use(src).tagClass('-mouseover',false);
                }
            },
            CELLA:{
                onDblclick:function(profile, e, src){
                    var cell = profile.cellMap[profile.getSubId(src)];
                    if(!cell)return;
                    if(profile.properties.disabled)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);
                        // stop to trigger row's onDblclick event
                        if(type=='button')
                            return false;
                    }
                },
                onClick:function(profile, e, src){
                    var p = profile.properties,
                        box=profile.box,
                        getPro=box.getCellPro,
                        cell = profile.cellMap[profile.getSubId(src)],
                        id;
                    if(cell){
                        if(profile.properties.disabled)return;
                        var type=getPro(profile, cell, 'type'),
                            disabled=getPro(profile, cell, 'disabled'),
                            readonly=getPro(profile, cell, 'readonly'),
                            event=getPro(profile, cell, 'event'),
                            mode = p.activeMode,
                            editable=getPro(profile, cell, 'editable');
    
                        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;
                        }
                        // checkbox is special for editor
                        if(!disabled && !readonly && type=='checkbox')
                            if(editable){
                                box._updCell(profile, cell, !cell.value, p.dirtyMark, true);
                            
                            profile.box._trycheckrowdirty(profile,cell);
                            
                            var ishotrow=cell._row.id==profile.box._temprowid
                            if(ishotrow){
                                profile.__needchecktmprow=true;
                                profile.box._sethotrowoutterblur(profile);
                            }
                        }
                                                        
                        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(3).id();
                                box._sel(profile, 'row', src, id, e);
                            }
                        }
                    // handler CELL
                    }else{
                        var row = profile.rowMap[profile.getSubId(src)];
                        if(p.disabled || row.disabled)
                            return false;

                        if(p.activeMode=='row'){
                            id = linb(src).parent(3).id();
                            box._sel(profile, 'row', src, id, e);
                        }                            
                    }
                    profile.box._focuscell(profile, e, src); 
                    
                    //in some browsers: if CELLA has a child 'span', you click 'span' will not tigger to focus CELLA
                    profile.$_focusbyclick=1;
                    linb.use(src).focus();
                    delete profile.$_focusbyclick;
                },
                onFocus:function(profile, e, src){
                    var ins=profile.boxing(),
                        prop=profile.properties;
                    // ensure call _focuscell once when click
                    if(profile.$_focusbyclick)
                        delete profile.$_focusbyclick;
                    else
                        profile.box._focuscell(profile, e, src); 

                    if(profile.afterCellFocused){
                        var cell=profile.cellMap[profile.getSubId(src)],row;
                        if(cell)
                            row=cell._row;
                        else
                            row=profile.rowMap[profile.getSubId(src)];
                        ins.afterCellFocused(profile, cell, row);
                        
                    }
                    // to check hot row
                    if(prop.hotRowMode!='none'){
                        var cell=profile.cellMap[profile.getSubId(src)],row;
                        if(cell)
                            row=cell._row;
                        else
                            row=profile.rowMap[profile.getSubId(src)];
                        if(profile.__hastmpRow && profile.__needchecktmprow && row.id!==profile.box._temprowid)
                            profile.box._checkNewLine(profile,'focuscell');
                    }
                },
                onKeydown:function(profile, e, src){
                    var p = profile.properties,
                        keys=linb.Event.getKey(e),
                        key = keys.key,
                        shift=keys.shiftKey,
                        ctrl=keys.ctrlKey,
                        cur = linb(src),
                        body = profile.getSubNode('BODY'),
                        first = body.nextFocus(true, true, false),
                        last = body.nextFocus(false, true, false);
                    switch(key){
                    case 'enter':
                        linb(src).onClick();
                    break;
                    //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(ctrl){
                            var cell=profile.cellMap[profile.getSubId(src)],row;
                            if(cell)
                                row=cell._row
                            else
                                row=profile.rowMap[profile.getSubId(src)];
                            if(row && !(p.disabled || row.disabled) && (row.group||row.sub)){
                                profile.getSubNode('ROWTOGGLE',row._serialId).onClick();
                                return false;
                            }
                        }
                        if(cur.get(0)==first.get(0)){
                            last.focus();
                            return;
                        }
                   case 'down':
                        if(ctrl){
                            var cell=profile.cellMap[profile.getSubId(src)],row;
                            if(cell)
                                row=cell._row
                            else
                                row=profile.rowMap[profile.getSubId(src)];
                            if(row && !(p.disabled || row.disabled) &&  (row.group||row.sub)){
                                profile.getSubNode('ROWTOGGLE',row._serialId).onClick();
                                return false;
                            }
                        }

                        //get no.
                        var count=1,
                            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)
                            profile.box._cacheRows(profile);

                        //get index
                        var index = _.arr.indexOf(profile.$allrowscache,temp),
                            rowLen = profile.$allrowscache.length,
                            newLine=0;

                        //adjust index
                        if(key=='up'){
                            index--;
                            if(index==-1){
                                index = rowLen-1;
                                count--;
                                if(count==0)count=max;
                            }
                        }else{
                            index++;
                            if(index==rowLen){
                                newLine=1;
                                index=0;
                                count++;
                                if(count==max+1)count=1;
                            }
                        }
                        if(newLine && p.hotRowMode!='none'){
                            var cell=profile.cellMap[profile.getSubId(src)],
                                colId;
                            if(!cell){
                                var row=profile.rowMap[profile.getSubId(src)];
                                if(!row)return false;    
                            }else
                                colId=cell._col.id;

                            var addhotrow=true,
                                cacheAll=profile.$allrowscache;
                            // if it's just the active row
                            if(profile.__hastmpRow){
                                // if it's invalid, dont add new row
                                addhotrow=profile.box._checkNewLine(profile,'keydown');

                                if(!profile.$allrowscache)
                                    profile.box._cacheRows(profile);
                            }

                            if(addhotrow){
                                profile.box._addTempRow(profile,colId);
                                // dont focus to next cell
                                return false;
                            }
                        }
                        //get node
                        var node = linb(profile.$allrowscache[index]).first(),
                            node2=node;
                        // it's normal cell
                        if(count>1)
                            node2=node2.next(count-1);
                        // no normal cell(group)
                        if(node2.isEmpty())
                            node2=node;
                        // get CELLA
                        if(node2 && !node2.isEmpty())
                            node2=node2.first();
                        // focus
                        if(!node2.isEmpty())
                            node2.focus();
                        
                        return false;
                        break;
                    }
                },
                onContextmenu:function(profile, e, src){
                    if(profile.onContextmenu){
                        var sid=profile.getSubId(src);
                        // cell or row
                        return profile.boxing().onContextmenu(profile, e, src,sid?(profile.cellMap[sid]||profile.rowMap[sid]):null)!==false;
                    }
                }
            }
        },
        DataModel:{
            directInput:true,
            listKey:null,
            currencyTpl:"$ *",
            valueSeparator:";",
            selMode:{
                ini:'none',
                listbox:['single','none','multi','multibycheckbox'],
                action:function(value){
                    this.getSubNodes(['HFMARK','MARK'],true).css('display',(value=='multi'||value=='multibycheckbox')?'':'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.clientHeight){
                                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){
// for perfomance: remove this
//                            if(o.parentNode.clientHeight){
                                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;
                                row._autoNumber=f(tag+i);
                                temp=row.rowNumber||row._autoNumber;
                                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){
                    v=(_.isSet(v)?v:"")+"";
                    this.getSubNode('GRIDCAPTION').html(linb.adjustRes(v,true));
                }
            },
            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);
                    //use copy to avoid outer memory link
                    else
                        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;
                    }
                }
            },

            rowOptions:{
                ini:{}
            },
            colOptions:{
                ini:{}
            },
            treeMode:{
                ini:true,
                action:function(value){
                    this.getSubNodes(['ROWLRULER', 'ROWTOGGLE'],true).css('display',value?'':'none');
                }
            },
            hotRowMode:{
                ini:'none',
                listbox:['none','auto','show'],
                action:function(value){
                    if(this.renderId){
                        if(value=='none')
                            this.boxing().removeHotRow();
                        else
                            this.box.__ensurehotrow(this);
                    }
                }
            },
            hotRowNumber:'[*]',
            noCtrlKey:true
        },
        EventHandlers:{
            afterCellFocused:function(profile, cell, row){},

            beforeInitHotRow:function(profile){},
            onInitHotRow:function(profile){},
            beforeHotRowAdded:function(profile, row, leaveGrid){},
            afterHotRowAdded:function(profile, row){},
            
            onGetContent:function(profile, row, callback){},
            onRowSelected:function(profile, row, e, src, type){},

            beforeColDrag:function(profile, colId){},
            beforeColMoved:function(profile, colId, toId){},
            afterColMoved:function(profile, colId, toId){},
            beforeColSorted:function(profile, col){},
            afterColSorted:function(profile, col){},

            beforeColShowHide:function(profile,colId,flag){},
            afterColShowHide:function(profile,colId,flag){},
            beforeColResized:function(profile,colId,width){},
            afterColResized:function(profile,colId,width){},
            beforeRowResized:function(profile, rowId, height){},
            afterRowResized:function(profile, rowId, height){},

            beforeRowActive:function(profile, row){},
            afterRowActive:function(profile, row){},
            beforeCellActive:function(profile, cell){},
            afterCellActive:function(profile, cell){},

            beforeIniEditor:function(profile, cell, cellNode, pNode){},
            onBeginEdit:function(profile, cell, editor){},
            onEndEdit:function(profile, cell, editor){},
            
            beforeCellUpdated:function(profile, cell, options, isHotRow){},
            afterCellUpdated:function(profile, cell, options, isHotRow){},
            
            onRowDirtied:function(profile, row){},

            onDblclickRow:function(profile, row, e, src){},
            beforeComboPop: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._toggleRows(pro.rows,true);
            ns.box._asy(ns);
            ns.box._ajdustBody(ns);
            
            ns.box.__ensurehotrow(ns);
        },
        __ensurehotrow:function(profile){
            var prop=profile.properties,box=profile.box;
            // add a temp row
            switch(prop.hotRowMode){
                case 'auto':
                    if(!prop.rows||prop.rows.length===0)
                        box._addTempRow(profile);
                break;
                case 'show':
                    box._addTempRow(profile);
                break;
            }
        },
        _temprowid:'_ r _temp_',
        _addTempRow:function(profile,coId){
            // clear first, ensure only one
            profile.box._sethotrowoutterblur(profile,true);
            delete profile.__hastmpRow;
            profile.boxing().removeRows([this._temprowid]);
            
            if(profile.beforeInitHotRow && false===profile.boxing().beforeInitHotRow(profile))
                return false;            
            
            profile.__needchecktmprow=true;
            
            var row=[],
                ins=profile.boxing();
            if(profile.onInitHotRow)
                row=ins.onInitHotRow(profile);

            if(_.isArr(row))
                row={cells:row};
            else if(!_.isHash(row))
                row={cells:[row]};

            // gives a special id
            row.id = this._temprowid;
            row.rowNumber=profile.properties.hotRowNumber;
            row.rowClass=profile.getClass('CELLS', '-hot');

            ins.insertRows([row]);
            
            // focus to next cell
            ins.focusCellbyRowCol(this._temprowid, coId||profile.properties.header[0].id);
    
            profile.__hastmpRow=true;
            
            profile.box._sethotrowoutterblur(profile);
        },

        _checkNewLine:function(profile,trigger){
            var prop=profile.properties;
            profile.box._sethotrowoutterblur(profile,true);
            
            // checked already
            if(!profile.__hastmpRow)
                return;

            delete profile.__needchecktmprow;

            var ins=profile.boxing(),
                rowId=this._temprowid,
                tempRow=ins.getRowbyRowId(rowId),
                result=prop.hotRowMode=='show'
                    ?trigger=='keydown'?true:null
                    :trigger?true:false;

            if(profile.beforeHotRowAdded){
                var result2=ins.beforeHotRowAdded(profile, tempRow, !trigger);
                if(_.isDefined(result2))
                    result=result2;
            }
            
            // do nothing
            if(result===null){
                if(prop.hotRowMode=='auto'){
                    profile.box._sethotrowoutterblur(profile);
                }
                return false;
            }
            // remove the hot row
            else if(result===false){
                if(prop.hotRowMode=='auto'){
                    delete profile.__hastmpRow;
                    ins.removeRows([rowId]);
                    if(prop.rows.length===0)
                        this._addTempRow(profile);
                }
                // dont add new hot row
                return false;
            }
            // add a new row
            else if(result===true){
                var newrow=_.clone(tempRow,true);
                // remove CELLS-hot;
                var hotcls=profile.getClass('CELLS', '-hot');
                if(hotcls==newrow.rowClass)delete newrow.rowClass;
                else newrow.rowClass=newrow.rowClass.replace(hotcls,'');
                
                delete profile.__hastmpRow;
                ins.removeRows([rowId]);

                if(newrow.id==rowId)
                    delete newrow.id;
                if(newrow.rowNumber==prop.hotRowNumber)
                    delete newrow.rowNumber;

                ins.insertRows([newrow]);
                
                if(profile.afterHotRowAdded)
                    ins.afterHotRowAdded(profile, prop.rows[prop.rows.length-1]);
                if(prop.hotRowMode=='show'){
                    this._addTempRow(profile);
                }
                return true;
            }
            // focus the invalid cell, and keep this hot row
            else{
                profile.__needchecktmprow=true;
                // if returns cell
                if(_.isHash(result))
                    ins.focusCell(result);
                // if return cell id
                else
                    ins.focusCell(ins.getCell(result));
                    
                profile.box._sethotrowoutterblur(profile);
                // dont add new hot row
                return false;
            }
        },
        _sethotrowoutterblur:function(profile, clear){
            profile.getSubNode('BODY').setBlurTrigger(profile.$domId+':BODY',clear?null:function(pos,e){
                var trigger = linb.Event.getSrc(e)==profile.getSubNode('SCROLL').get(0)?'focusin':null;
                profile.__tmpRowBlurTrigger=_.asyRun(function(){
                    if(profile.box)
                        profile.box._checkNewLine(profile,trigger);
                });
            },null,null,true);
            if(clear){
                if(profile.__tmpRowBlurTrigger){
                    clearTimeout(profile.__tmpRowBlurTrigger);
                    delete profile.__tmpRowBlurTrigger;
                }
            }
        },
        _cacheRows:function(profile){
            var all=profile.getSubNode('CELLS',true).get();
            //filter dispaly==none
            _.filter(all,function(o){
                return !!o.clientHeight;
            });
            profile.$allrowscache = all;
        },
        _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.offsetHeight>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(w<=0)return;
                if(pro.rowHandlerWidth!=w){
                    hcell.width(pro.rowHandlerWidth=w);
                    profile.getSubNode('FCELL',true).width(w);
                    profile.getSubNode('ROWLRULER',true).each(function(o){
                        n=map[profile.getSubId(o.id)];
                        o.style.width=(4+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.ROWTOGGLE && !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.ROWTOGGLE) && 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.sortDisplay=NONE;
            data.headerHeight=data.headerHeight?('height:'+data.headerHeight+'px;'):'';
            data._rowMarkDisplay=(pro.selMode=="multi"||pro.selMode=="multibycheckbox")?"":"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';

                //  Forward-compatible with 'visibility'
                if(o.hasOwnProperty('visibility') && !o.hasOwnProperty('hidden'))
                    o.hidden=!o.visibility;

                t.colDisplay = o.hidden===true?'display:none':'';

                t.firstCellStyle=pro.colOptions.firstCellStyle||'';
                t.firstCellClass=pro.colOptions.firstCellClass||'';

                if(!o.type)o.type='input';
                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')),
                rcls=me._rcls||(me._rcls=profile.getClass('CELL', '-readonly')),
                //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 (
                        // priority 1
                        typeof cell._$caption=='string'? cell._$caption: 
                        // priority 2
                        typeof ncell.caption =='string'? ncell.caption: 
                        // priority 3
                        typeof (cell.renderer||cell._renderer)=='function'? (cell.renderer||cell._renderer).call(profile,cell) : 
                        // priority 4
                        typeof fun=='function'?fun(cell.value, profile, cell):
                        // priority 5
                        (_.isSet(cell.value)?String(cell.value):
                        // priority 6
                        "")
                    // default value
                    ) || ""}),
                f0=me._f0=(me._f0=function(v,profile,cell){
                    return v ? linb.Date.getText(v, getPro(profile, cell, 'dateEditorTpl')||'ymdhn') : "";
                }),
                f1=me._f1=(me._f1=function(v,profile,cell){
                    return v ? linb.Date.getText(v, getPro(profile, cell, 'dateEditorTpl')||'ymd') : "";
                }),
                f2=me._f2=(me._f2=function(v){return v?(v+'').replace(reg1,'&lt;').replace(/\t/g,'&nbsp;&nbsp;&nbsp;&nbsp;').replace(/ /g,'&nbsp;').replace(/(\r\n|\n|\r)/g,"<br />"):""}),
                f3=me._f3=(me._f3=function(v){return (v||v===0) ? ((v.toFixed(4)*100)+'%') : ""}),
                f5=me._f5=(me._f5=function(v,profile,cell){
                    if(v||v===0){
                        v=parseFloat(v);
                        var precision=getPro(profile, cell, 'precision');
                        if(_.isNumb(precision))
                            v=v.toFixed(precision);
                        return v+"";
                    }else 
                        return "";
                }),
                f4=me._f4=(me._f4=function(v,profile,cell){
                    if(v||v===0){
                        v=parseFloat(v);
                        var precision=getPro(profile, cell, 'precision');
                        if(_.isNumb(precision))
                            v=v.toFixed(precision);
                        else v=v+"";

                        v= (''+v).split(".");
                        v[0]=(''+v[0]).split("").reverse().join("").replace(/(\d{3})(?=\d)/g, "$1,").split("").reverse().join("");
                        return v.join(".")
                    }else 
                        return "";
               }),
               f6=me._f6=(me._f6=function(v,profile,cell){
                    var t=getPro(profile,cell,'editorListItems');
                    if(!t)
                        if(t=getPro(profile,cell,'editorListKey'))
                           t=linb.UI.getCachedData(t); 
                    if(t && t.length)
                        for(var i=0,l=t.length;i<l;i++)
                            if(t[i].id===v)
                                return t[i].caption||v;
                    return v;
               })
            ;

            switch(type){
                case 'number':
                case 'spin':
                    var v=parseFloat(cell.value);
                    cell.value=(v||v===0)?v:null;
                    caption= capOut ||ren(profile,cell,ncell,f5);
                    if(dom)
                        node.html(caption,false);
                break;
                case 'currency':
                    var v=parseFloat((cell.value+"").replace(/[^\d.-]/g,''));
                    cell.value=(v||v===0)?v:null;
                    //  Note that cell value has true numeric value, while caption has currency format with commas.
                    caption= capOut ||ren(profile,cell,ncell,f4);
                    var tpl = getPro(profile, cell, 'currencyTpl');
                    if(tpl && caption!=="")
                        caption = tpl.replace("*", caption);
                    if(dom)
                        node.html(caption,false);
                break;
                case 'date':
                case 'datepicker':
                    cell.value= _.isDate(cell.value)?cell.value:_.isFinite(cell.value)?new Date(parseInt(cell.value)):null;
                    caption= capOut || ren(profile,cell,ncell,f1);
                    if(dom)
                        node.html(caption, false);
                break;
                case 'datetime':
                    cell.value= _.isDate(cell.value)?cell.value:_.isFinite(cell.value)?new Date(parseInt(cell.value)):null;
                    caption= capOut || ren(profile,cell,ncell,f0);
                    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 'color':
                case 'colorpicker':
                    cell.value=cell.value?("#"+linb.UI.ColorPicker._ensureValue(0,cell.value)):"";
                    caption= capOut ||ren(profile,cell,ncell);
                    if(cell.value){
                        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+';';
                        }
                    }else{
                        if(dom){
                            node.html(caption,false);
                            node.css('color','#000').css('backgroundColor',"#fff");
                        }else{
                            node.color='color:#000;';
                            node.bgcolor='background-color:#fff;';
                        }
                    }
                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;
                case 'listbox':
                    cell.value=cell.hasOwnProperty("value")?cell.value:"";
                    caption= capOut ||ren(profile,cell,ncell,f6);
                    if(dom)node.html((caption===null||caption===undefined)?cell.value:caption,false);
                break;
                default:
                    cell.value=cell.hasOwnProperty("value")?cell.value:"";
                    caption= capOut ||ren(profile,cell,ncell);
                    if(dom)node.html((caption===null||caption===undefined)?cell.value:caption,false);
            }

            cell._$tips=caption;

            var t2=cell.disabled || cell._row.disabled || cell._col.disabled,
                t3=cell.readonly || cell._row.readonly || cell._col.readonly;
            if(!dom){
/*
cellStyle
cellClass
cellRenderer

renderer
type
disabled
readonly
precision
dateEditorTpl
editable
value
caption
sortby [for column only]

customEditor -> an object for custom editor. or the below prop

editorListKey
editorListItems
editorFormat
editorMask
editorProperties
editorEvents
editorReadonly
editorDropListWidth
editorDropListHeight

*/
                node.cellCls=profile.getClass('CELL', '-'+type) + (t2?(' '+dcls):'') + (t3?(' '+rcls):'');
                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[pid]?(b[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++){
                // give id (avoid conflicts)
                if(!arr[i].id || a[arr[i].id]){
                    while(a[t=ider.next()]);
                    arr[i].id=t;
                }

                row = arr[i];

                // give _serialId
                temp='r_'+profile.pickSubId('row');
                row[SubID]=temp;
                b[temp]=row;

                //#
                row._pid = pid;
                row._cells={};
                row._layer=_layer;

                row._tabindex=pro.tabindex;
                row._rowMarkDisplay=(pro.selMode=="multi"||pro.selMode=="multibycheckbox")?"":NONE;

                row._treeMode=pro.treeMode?'':NONE;

                t={id: row.id};

                t.rowCls = ""
                if(row.disabled)
                    t.rowCls += profile.getClass('CELLS', '-disabled');
                if(row.readonly)
                    t.rowCls += profile.getClass('CELLS', '-readonly');
                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=4+_layer*mm;

                t.rowHeight=row.height||pro.rowHeight;
                t.rowHandlerDisplay=pro.rowHandler?'':NONE;
                t.rowDDDisplay=(('rowResizer' in row)?row.rowResizer:pro.rowResizer)?'':NONE;

                t.firstCellStyle=pro.rowOptions.firstCellStyle||'';
                t.firstCellClass=pro.rowOptions.firstCellClass||'';

                cells = t.cells = [];

                t[SubID]=temp;
                t.subClass = row.sub?'linb-uicmd-toggle2':'linb-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');
                        // give default id
                        g.id=g.id||g[SubID];

                        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);

            if(!uicell.width)uicell.width=col.width;
            uicell._tabindex=pro.tabindex;
            uicell.cellDisplay=col.hidden===true?'display:none;':'';

            self._renderCell(profile, cell, uicell);

            //next
            cell.oValue=cell.value;
        },
        _setSub:function(profile, item, flag){
            var id=profile.domId,
                pro=profile.properties,
                serialId = profile.rowMap2[item.id],
                markNode = profile.getSubNode('ROWTOGGLE', 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,function(){
                            subNs.css({display:'none'})
                        }, 100, 5, 'expoIn', profile.key+profile.id).start();
                    else
                        subNs.css({
                            display:'none',
                            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._inited){
                            delete item.sub;
                            //before insertRows
                            item._inited=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]},function(){
                                subNs.css({display:''})
                            },function(){
                                subNs.css({height:'auto'})
                            }, 100, 5, 'expoOut', profile.key+profile.id).start();
                        else
                            subNs.css({display:'',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){
                            //return true: continue UI changing
                            if(r===true)
                                item._inited=true;
                            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, triggerEvent){
            var box=profile.box,
                prop=profile.properties,
                pdm=prop.dirtyMark,
                psdm=prop.showDirtyMark,
                sc=linb.absObj.$specialChars,
                cell,node,ishotrow;

            if(typeof cellId == 'string')
                cell = profile.cellMap[cellId];
            else{
                cell = cellId;
                cellId = cell._serialId;
            }
            if(!cell)return;
            ishotrow=cell._row.id==box._temprowid;

            if(!_.isHash(options))options={value:options};
            options=_.filter(options,function(o,i){return !sc[i.charAt(0)] || i=='_$caption' });

            if(triggerEvent){
                if(profile.beforeCellUpdated && false === profile.boxing().beforeCellUpdated(profile, cell, options,ishotrow))
                    return;
            }

            // * remove cell's caption first
            delete cell.caption;
            delete cell._$caption;
            delete cell._$tips;

            _.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);

            //if update value
            if('value' in options){
                if(!pdm || dirtyMark===false)
                    cell.oValue=cell.value;
                else{
                    if(cell.value===cell.oValue){
                        if(psdm)
                            node.removeClass('linb-ui-dirty');
                        delete cell.dirty;
                    }else{
                        if(psdm)
                            node.addClass('linb-ui-dirty');
                        cell.dirty=true;
                    }
                }
            }

            if(triggerEvent){
                if(profile.afterCellUpdated)
                    profile.boxing().afterCellUpdated(profile,cell, options,ishotrow);            
            }    
        },
        _ensureValue:function(profile,value){
            if(profile.properties.selMode=='multi'||profile.properties.selMode=='multibycheckbox'){
                var arr = (value?(''+value):'').split(profile.properties.valueSeparator);
                // ignore hot row
                _.arr.removeValue(arr,this._temprowid);
                arr.sort();
                return arr.join(profile.properties.valueSeparator);
            }else{
                // ignore hot row
                return value==this._temprowid?null: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;
            switch(mode){
            case 'none':
                box.onRowSelected(profile, targetItem, e, src, 0);
                break;
            case 'multibycheckbox':
                if(profile.keys.MARK){
                    var ck=profile.getKey(linb.Event.getSrc(e).id||""),
                        clickMark=ck==profile.keys.MARK;
                    if(!clickMark){
                        box.onRowSelected(profile, targetItem, e, src, 0);
                        break;
                    }
                }
            case 'multi':
                var value = box.getUIValue(),
                    arr = value?(''+value).split(properties.valueSeparator):[],
                    checktype=1;
                if(arr.length&&(ks.ctrlKey||ks.shiftKey||properties.noCtrlKey)){
                    //todo: give cell multi selection function
                    if(ks.shiftKey && 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);
                            checktype=-1;
                        }else
                            arr.push(sid);
                    }

                    arr.sort();
                    value = arr.join(properties.valueSeparator);

                    //update string value only for setCtrlValue
                    if(box.getUIValue() != value){
                        box.setUIValue(value);
                        if(box.get(0) && box.getUIValue() == value)
                            box.onRowSelected(profile, targetItem, e, src, checktype);
                    }
                    break;
                }
            case 'single':
                if(box.getUIValue() != sid){
                    profile.$firstV=targetItem;
                    box.setUIValue(sid);
                    if(box.get(0) && box.getUIValue() == sid)
                        box.onRowSelected(profile, targetItem, e, src, 1);
                }
                break;
            }
        },
        _activeCell:function(profile, id){
            if(profile.properties.activeMode!='cell')return;
            if(profile.$activeCell == id)return;
            var targetCell=null;
            if(profile.$activeCell){
                linb(profile.$activeCell).tagClass('-active', false);
                delete profile.$activeCell;
            }
            if(id!==false){
                var targetId = profile.getSubId(id),
                    map = profile.cellMap;
                targetCell=map[targetId];
                if(profile.beforeCellActive && (false===profile.boxing().beforeCellActive(profile, targetCell)))return;                
                linb(profile.$activeCell = id).tagClass('-active');
            }
            if(profile.afterCellActive)profile.boxing().afterCellActive(profile, targetCell);
        },
        _activeRow:function(profile, id){
            if(profile.properties.activeMode!='row')return;
            if(profile.$activeRow == id)return;
            var targetRow=null;
            if(profile.$activeRow){
               linb(profile.$activeRow).tagClass('-active', false);
               delete profile.$activeRow;
            }
            if(id!==false){
                var targetId = profile.getSubId(id),
                    map = profile.rowMap;
                targetRow=map[targetId];
                //before event
                if(profile.beforeRowActive && (false===profile.boxing().beforeRowActive(profile, targetRow)))return;
                linb(profile.$activeRow = id).tagClass('-active');
            }
            //after event
            if(profile.afterRowActive)profile.boxing().afterRowActive(profile, targetRow);
        },
        getCellPro:function(profile, cell, key){
            var t=cell,p=profile.properties;
            return (t && t.hasOwnProperty(key)&&_.isSet(t[key]))?t[key]
                    :((t=cell._row)&&t.hasOwnProperty(key)&&_.isSet(t[key]))? t[key]
                    :((t=p.rowOptions)&&t.hasOwnProperty(key)&&_.isSet(t[key]))? t[key]
                    :((t=cell._col)&&t.hasOwnProperty(key)&&_.isSet(t[key]))?t[key]
                    :((t=p.colOptions)&&t.hasOwnProperty(key)&&_.isSet(t[key]))?t[key]
                    :((t=p)&&t.hasOwnProperty(key)&&_.isSet(t[key]))?t[key]:null;
        },
        _trycheckrowdirty:function(profile,cell){
            if(!cell || !cell._row)return;

            _.resetRun(profile.key+":"+profile.$linbid+":"+cell._row.id,function(){
                var lc=profile.$cellInEditor;
                if(cell._row && (!lc || (lc._row && lc._row!=cell._row))){
                    var dirty=false;
                    _.arr.each(cell._row.cells,function(v){
                        if(v.oValue!==v.value){
                            dirty=true;
                            return false;
                        }
                    });
                    if(dirty && cell._row.id !=profile.box._temprowid && profile.onRowDirtied)
                        profile.boxing().onRowDirtied(profile,cell._row);
                }
            },100);
        },
        _editCell:function(profile, cellId){
            var cell = typeof cellId=='string'?profile.cellMap[cellId]:cellId;
            if(!cell)return;
            if(profile.box.getCellPro(profile, cell,'disabled') || profile.box.getCellPro(profile, cell,'readonly'))return ;
            
            // real cellId
            cellId=cell._serialId;
            var cellNode = profile.getSubNode('CELL', cellId),
                colId = cell._col.id,
                ishotrow=cell._row.id==profile.box._temprowid;

            //clear the prev editor
            var editor = profile.$curEditor;
            if(editor)_.tryF(editor.undo,[],editor);
            editor=null;

            var grid = this,
                baseNode = profile.getSubNode('SCROLL'),
                box=profile.box,
                getPro=function(key){return box.getCellPro(profile, cell, key)};

            // 1. customEditor in cell/row or header
            editor = profile.box.getCellPro(profile, cell,'customEditor');
            if(editor && typeof editor.iniEditor=='function'){
                editor.iniEditor(profile, cell, cellNode);
                _.tryF(editor.activate,[],editor);
                if(profile.onBeginEdit)
                    profile.boxing().onBeginEdit(profile, cell, editor);
            }else{
                // 2. beforeIniEditor
                //      returns an editor(linb.UI object)
                //      or, sets $editorValue
                if(profile.beforeIniEditor){
                    editor=profile.boxing().beforeIniEditor(profile, cell, cellNode, baseNode);
                    // if return false, dont set $curEditor
                    if(editor===false)
                        return;
                }

                // if beforeIniEditor doesnt return an editor
                if(!editor || !editor['linb.UI']){
                    var type=getPro('type')||'input',
                        editorProperties = getPro('editorProperties'),
                        editorEvents = getPro('editorEvents'),
                        editorFormat = getPro('editorFormat'),
                        editorMask = getPro('editorMask'),
                        editorReadonly = getPro('editorReadonly'),
                        editorDropListWidth = getPro('editorDropListWidth'),
                        editorDropListHeight = getPro('editorDropListHeight'),
                        t,oldProp;
                    
                    // 3. for checkbox/lable,button type
                    if(type=='checkbox'){
                        cellNode.first().focus();
                        return;
                    }else if(type=='button'||type=='label')
                        return;
    
                    // 4. try to get editor from cache
                    if(profile.$cache_editor[type])
                        editor=profile.$cache_editor[type];
                    // 5. create a ComboInput Editor, and cache it
                    else{
                        var precision=getPro('precision'),
                            dateEditorTpl=getPro('dateEditorTpl');
                        editor=new linb.UI.ComboInput({dirtyMark:false,cachePopWnd:false,left:-1000,top:-1000,position:'absolute',visibility:'hidden',zIndex:100});
                        switch(type){
                            case 'number':
                            case 'spin':
                            case 'currency':
                                editor.setType(type);
                                if(_.isSet(precision))
                                    editor.setPrecision(precision);
                                break;
                            case 'progress':
                                editor.setType('spin').setMax(1).setMin(0).setPrecision(4).setIncrement(0.01);
                                break;
                            case 'input':
                                editor.setType('none');
                                break;
                            case 'textarea':
                                editor.setType('none').setMultiLines(true).setCommandBtn('save').onCommand(function(p){
                                    p.boxing().hide();
                                });
                                _.tryF(editor.setResizer,[true],editor);
                                break;
                            case 'date':
                            case 'datepicker':
                            case 'datetime':
                                if(dateEditorTpl)
                                    editor.setDateEditorTpl(dateEditorTpl);
                            case 'listbox':
                            case 'combobox':
                            case 'helpinput':
                            case 'time':
                            case 'timepicker':
                            case 'color':
                            case 'colorpicker':
                            case 'getter':
                            case 'popbox':
                            case 'cmdbox':
                                editor.setType(type).beforeComboPop(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().beforeComboPop(profile, cell, pro, pos, e, src);
                                });
                                break;
                        }
                        baseNode.append(editor);
                        //cache the stantdard editor
                        profile.$cache_editor[type] = editor;
                    }

                    if(editor.setInputReadonly && editorReadonly)
                        editor.setInputReadonly(true);
                    if(editor.setDropListWidth && editorDropListWidth)
                        editor.setDropListWidth(editorDropListWidth);
                    if(editor.setDropListHeight && editorDropListHeight)
                        editor.setDropListHeight(editorDropListHeight);
                    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);
                    if(editorProperties){
                        oldProp={}
                        var h=profile.getProperties();
                        _.each(editorProperties,function(o,i){
                            oldProp=h[i];
                        });
                        editor.setProperties(editorProperties);
                    }
                    if(editorEvents)
                        editor.setEvents(editorEvents);
    
                    // clear for valueFormat, setValue maybe cant set value because of valueFormat
                    editor.resetValue();
    
                    //set properities
                    switch(type){
                        case 'listbox':
                        case 'combobox':
                        case 'helpinput':
                            // set properties
                            if(t=getPro('editorListItems')){
                                editor.setListKey(null);
                                editor.setItems(t);
                            }else if(t=getPro('editorListKey')) {
                                editor.setItems(null);
                                editor.setListKey(t);
                            }
                            break;
                        case 'cmdbox':
                        case 'popbox':
                            // reset Caption
                            if(editor.setCaption)
                                editor.setCaption(cell.caption||"");
                    }

                    // must set value here, after setItems/setListKey
                    //$editorValue must be set in beforeIniEditor
                    editor.setValue(cell.$editorValue||cell.value,true);
                    delete cell.$editorValue;

                    //$tag for compatible
                    if(cell.$tag){
                        if(editor.setCaption)editor.setCaption(cell.$tag);
                        else if(editor.setValue)editor.setValue(cell.$tag);
                    }
                    //give a reference
                    editor.get(0).$cell = cell;
                    editor.get(0)._smartnav=true;
    
                    //undo function is a must
                    editor.undo=function(){
                        var editor=this;
                        // for ie's setBlurTrigger doesn't trigger onchange event
                        editor.getSubNode('INPUT').onBlur(true);
                        
                        // row dirty alert
                        profile.box._trycheckrowdirty(profile,profile.$cellInEditor);

                        profile.$curEditor=null;
                        profile.$cellInEditor=null;
                        
                        editor.getRoot().setBlurTrigger(profile.$linbid+":editor");
                        if(!profile.properties.directInput){
                            editor.afterUIValueSet(null).beforeNextFocus(null).onCancel(null);                    
                            editor.setValue('',true);
                        }
                        // clear those setting
                        if(editorFormat){
                            if(editor.beforeFormatCheck)editor.beforeFormatCheck(null);
                            if(editor.setValueFormat)editor.setValueFormat('');
                        }
                        if(editorMask)
                            if(editor.setMask)editor.setMask('');
                        if(editorReadonly)
                            if(editor.setInputReadonly)editor.setInputReadonly(false);
                        if(editorDropListWidth)
                            if(editor.setDropListWidth)editor.setDropListWidth(0);
                        if(editorDropListHeight)
                            if(editor.setDropListHeight)editor.setDropListHeight(0);
                        if(oldProp){
                            editor.setProperties(oldProp);
                            oldProp=null;
                        }
                        if(editorEvents){
                            var h={};
                            _.each(editorEvents,function(o,i){
                                h[i]=null;
                            });
                            editor.setEvents(h);
                        }
                        
                        delete editor.get(0).$cell;
                        delete editor.get(0)._smartnav;
                        //don't use disply:none, firfox has many bugs about Caret or renderer
                        editor.setVisibility('hidden');
                        
                        // execute once
                        editor.undo=null;
                        if(profile.onEndEdit)
                            profile.boxing().onEndEdit(profile, cell, editor);
                    };
        
                    //editor change value, update cell value
                    editor
                    .afterUIValueSet(function(pro,oV,nV){
                        var type=getPro('type'),_$caption;
                        switch(type){
                            case 'number':
                            case 'spin':
                            case 'progress':
                                nV=parseFloat(nV);
                                nV=(nV||nV===0)?nV:null;
                                break;
                            case 'currency':
                                nV=parseFloat((''+nV).replace(/[^\d.-]/g,''));
                                nV=(nV||nV===0)?nV:null;
                                break;
                            case 'cmdbox':
                            case 'popbox':
                            case 'combobox':
                            case 'listbox':
                            case 'helpinput':
                                _$caption=pro.boxing().getShowValue();
                                break;
                        }
                        var options={value:nV};
        
                        if(_.isDefined(_$caption))
                            options.caption=options._$caption=_$caption;
        
                        if(pro.properties.hasOwnProperty("tagVar"))
                            options.tagVar=pro.properties.tagVar;
        
                        grid._updCell(profile, cellId, options, profile.properties.dirtyMark, true);
                    })
                    .beforeNextFocus(function(pro, 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;
                    })
                    .onCancel(function(){
                        if(editor)
                            _.tryF(editor.undo,[],editor);                
                    })
                    .getRoot().setBlurTrigger(profile.$linbid+":editor", 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');
                    }
                    editor.setVisibility("visible");
        
                    if(profile.onBeginEdit)
                        profile.boxing().onBeginEdit(profile, cell, editor);
                    //activate editor
                    _.asyRun(function(){
                        _.tryF(editor&&editor.activate,[],editor);
                    });
                }
            }

            //give a reference
            profile.$curEditor=editor;
            profile.$cellInEditor=cell;
            
            if(ishotrow){
                profile.__needchecktmprow=true;
                profile.box._sethotrowoutterblur(profile);
            }
        },
        _ajdustBody:function(profile){
            _.resetRun(profile.$linbid+'4',function(){
                var body=profile.getSubNode('BODY'),
                    header=profile.getSubNode('HCELLS'),
                    t,l,last,keys=profile.keys,ww;
                if(body.get(0).clientHeight){
                    if(header.get(0).clientHeight){
                        if(t=header.get(0).childNodes){
                            l=t.length;
                            while(l){
                                if(t[l-1].clientHeight){
                                    last=t[l-1];
                                    break;
                                }
                                --l;
                            }
                        }
                        ww=last?(last.offsetWidth+last.offsetLeft+100):0;
                        //set HI node
                        header.parent().width(ww);
                        body.width(ww);
                    }else{
                        if(t=body.get(0).childNodes){
                            l=t.length;
                            while(l){
                                if(t[l-1].clientHeight){
                                    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].clientHeight){
                                            last=t[l-1];
                                            break;
                                        }
                                        --l;
                                    }
                                }
                            }
                        }
                    }
                }

                if(last){
                    body.width(last.offsetWidth+last.offsetLeft);
                }else{
                    var prop = profile.properties,hd=prop.header,rows=prop.rows,
                    //defult
                    w = prop.rowHandler?(prop.rowHandlerWidth+2):0;
                    _.each(hd,function(o){
                        if(o.hidden!==true)
                            w += o.width + 2;
                    });
                    body.width(w);
                }
                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){
                    //It's a hash
                    if(!!o && typeof o == 'object' && o.constructor == Object)
                        m[i]=_.copy(o);
                    // not a hash
                    else
                        m[i]={value:o};
                })
            });
            return a;
        },
         _focuscell:function(profile, e, src){
            if(profile.properties.disabled||profile.properties.readonly)return;
                        
            var p = profile.properties,
                box=profile.box,
                getPro=box.getCellPro,
                cell = profile.cellMap[profile.getSubId(src)],
                mode = p.activeMode, id;
            
            if(cell){
                var edit=false;
                if(getPro(profile, cell, 'editable')){
                    if(getPro(profile, cell, 'disabled')||getPro(profile, cell, 'readonly')){
                        edit=false;
                    }else{
                        edit=true;
                        box._editCell(profile, cell._serialId);
                        _.asyRun(function(){
                            linb.use(src).parent().onMouseout(true,{$force:true})
                                      .parent().onMouseout(true,{$force:true});
                        });
                    }
                }
                // if not in edit mode
                if(!edit){
                    if(cell && mode=='cell'){
                        id = linb.use(src).parent().id();
                        box._activeCell(profile, id);
                    }
                }else{
                    if(cell && mode=='cell'){
                        box._activeCell(profile, false);
                    }
                }
            }
            if(mode=='row'){
                id = linb.use(src).parent(2).id();
                box._activeRow(profile, id);
            }
        },
        _showTips:function(profile, node, pos){
            if(profile.properties.disableTips)return;
            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 arguments.callee.upper.apply(this,['BOX']);
        }
    },
    Static:{
        Templates:{
            style:'{_style}',
            className:'{_className}',
            BOX:{
                tagName:'div',
                className:'{_cls}',
                BG:{
                    tagName:'div'
                },
                RULER:{
                    $order:1,
                    tagName:'div',
                    RULERLEFT:{},
                    RULERRIGHT:{}
                },
                IND:{
                    $order:2,
                    IND1:{
                        style:'{_showD}',
                        tabindex:'{tabindex}'
                    },
                    IND2:{
                        style:'{_showD2}',
                        tabindex:'{tabindex}'
                    }
                },
                DECREASE:{
                    style:'{_showDes}',
                    tabindex:'{tabindex}'
                },
                INCREASE:{
                    style:'{_showIns}',
                    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,
                cursor:'e-resize',
                '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,
                cursor:'n-resize',
                '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;
                    if(p.disabled || p.readonly)return;
                    var 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;
                    if(p.disabled || p.readonly)return;
                    var type=p.type=='vertical',
                        key=linb.Event.getKey(e).key;
                    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){
                    if(linb.Event.getBtn(e)!="left")return;
                    var p=profile.properties;
                    if(p.disabled || p.readonly)return;
                    var 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;
                    if(p.disabled || p.readonly)return;
                    var type=p.type=='vertical',
                        key=linb.Event.getKey(e).key;
                    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){
                    if(linb.Event.getBtn(e)!="left")return;
                    var p=profile.properties;
                    if(p.disabled || p.readonly)return;
                    var 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;
                    if(p.disabled || p.readonly)return;
                    var 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){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    profile.box._auto(profile, false);
                },
                onMouseout:function(profile){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMouseup:function(profile){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    linb.Thread.abort(profile.$linbid+':auto');
                }
            },
            INCREASE:{
                onMousedown:function(profile){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    profile.box._auto(profile, true);
                },
                onMouseout:function(profile){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    linb.Thread.abort(profile.$linbid+':auto');
                },
                onMouseup:function(profile){
                    if(profile.properties.disabled || profile.properties.readonly)return;
                    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 p.isRange?b.join(':'):(b[0]+'');
        },
        _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:{
        showModal:function(parent, left, top){
            this.show(parent, true, left, top);
        },
        show:function(parent, modal, left, top){
            parent = parent || linb('body');
            return this.each(function(profile){
                var t,
                    p=profile.properties,
                    ins = 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();
                        
                        var tt=profile._$rs_args;
                        // resize immidiately here, maybe max here
                        linb.UI.$doResize(profile, (tt&&tt[1])||p.width, (tt&&tt[2])||p.height);
                        root.show(left?(parseInt(left)||0)+'px':null, top?(parseInt(top)||0)+'px':null);

                        if(p.iframeAutoLoad||p.ajaxAutoLoad)
                            linb.UI.Div._applyAutoLoad(profile);

                        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=p.fromRegion)
                    linb.Dom.animate({border:'dashed 1px #ff0000'},{left:[t.left,p.left],top:[t.top,p.top],width:[t.width,p.width],height:[t.height,p.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,{
            TABSTOP1:{$order:-1},
            TBAR:{
                tagName:'div',
                className:'linb-uibar-top',
                TBART:{
                    cellpadding:"0",
                    cellspacing:"0",
                    width:'100%',
                    border:'0',
                    tagName:'table',
                    className:'linb-uibar-t',
                    TBARTR:{
                        tagName:'tr',
                        TBARTDL:{
                            tagName:'td',
                            className:'linb-uibar-tdl'
                        },
                        TBARTDM:{
                            $order:1,
                            width:'100%',
                            tagName:'td',
                            className:'linb-uibar-tdm'
                        },
                        TBARTDR:{
                            $order:2,
                            tagName:'td',
                            className:'linb-uibar-tdr'
                        }
                    }
                },
                BARCMDL:{
                    $order:1,
                    tagName: 'div',
                    className:'linb-uibar-cmdl',
                    ICON:{
                        $order:0,
                        className:'linb-ui-icon {imageClass}',
                        style:'{backgroundImage} {backgroundPosition} {backgroundRepeat} {imageDisplay}'
                    },
                    CAPTION:{
                        $order:1,
                        text:'{caption}'
                    }
                },
                BARCMDR:{
                    $order:2,
                    tagName: 'div',
                    className:'linb-uibar-cmdr',
                    INFO:{
                        className:'linb-uicmd-info',
                        style:'{infoDisplay}',
                        $order:1
                    },
                    OPT:{
                        className:'linb-uicmd-opt',
                        style:'{optDisplay}',
                        $order:1
                    },
                    PIN:{
                        $order:2,
                        className:'linb-uicmd-pin',
                        style:'{pinDisplay}'
                    },
                    LAND:{
                        $order:3,
                        className:'linb-uicmd-land',
                        style:'{landDisplay}'
                    },
                    REFRESH:{
                        className:'linb-uicmd-refresh',
                        style:'{refreshDisplay}',
                        $order:4
                    },
                    MIN:{
                        $order:5,
                        className:'linb-uicmd-min',
                        style:'{minDisplay}'
                    },
                    RESTORE:{
                        $order:6,
                        className:'linb-uicmd-restore',
                        style:'display:none;'
                    },
                    MAX:{
                        $order:7,
                        className:'linb-uicmd-max',
                        style:'{maxDisplay}'
                    },
                    CLOSE:{
                        $order:8,
                        className:'linb-uicmd-close ',
                        style:'{closeDisplay}'
                    }
                }
            },
            MAIN:{
                $order:2,
                tagName:'div',
                className:'linb-uicon-main',
                MAINI:{
                    tagName:'div',
                    className:'linb-uicon-maini',
                    PANEL:{
                        tagName:'div',
                        style:"{_overflow};",
                        text:'{html}'+linb.UI.$childTag
                    }
                }
            },
            BBAR:{
                $order:3,
                tagName:'div',
                className:'linb-uibar-bottom',
                BBART:{
                    cellpadding:"0",
                    cellspacing:"0",
                    width:'100%',
                    border:'0',
                    tagName:'table',
                    className:'linb-uibar-t',
                    BBARTR:{
                        tagName:'tr',
                        BBARTDL:{
                            tagName:'td',
                            className:'linb-uibar-tdl'
                        },
                        BBARTDM:{
                            $order:1,
                            width:'100%',
                            tagName:'td',
                            className:'linb-uibar-tdm'
                        },
                        BBARTDR:{
                            $order:2,
                            tagName:'td',
                            className:'linb-uibar-tdr'
                        }
                    }
                }
            },
            TABSTOP2:{$order:9}
        },'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'
            },
            "TABSTOP1,TABSTOP2":{
                height:0,
                width:"16px",
                display:'inline',
                position:'absolute'
            },
            PANEL:{
                position:'relative',
                overflow:'auto',
                'font-size':'12px',
                'line-height':'14px'
            },
            CAPTION:{
                'font-size':'12px',
                display:'inline',
                'vertical-align':linb.browser.ie6?'baseline':'middle'
            },
            BORDER:{
                position:'relative',
                'font-size':0,
                'line-height':0
            }
        },
        Behaviors:{
            DroppableKeys:['PANEL'],
            PanelKeys:['PANEL'],
            DraggableKeys:['LAND'],
            HoverEffected:{INFO:'INFO', OPT:'OPT', PIN:'PIN',MIN:'MIN',MAX:'MAX',RESTORE:'RESTORE',CLOSE:'CLOSE',REFRESH:'REFRESH',LAND:'LAND'},
            ClickEffected:{INFO:'INFO', OPT:'OPT', PIN:'PIN',MIN:'MIN',MAX:'MAX',RESTORE:'RESTORE',CLOSE:'CLOSE',REFRESH:'REFRESH',LAND:'LAND'},
            onMousedown:function(profile, e){
                profile.box._active(profile);
            },
            afterKeydown:function(profile, e){
                var keys = linb.Event.getKey(e);
                if((e.$key || e.keyCode || e.charCode)==9){
// hack for ie tab event
if(linb.browser.ie){
    var id="linb::_specialforietab";
    if(!linb.Dom.byId(id))
        linb('body').append("<div style='display:none;position:absolute;' id="+id+"></div>");
    linb.Dom.byId(id).innerHTML=_()+"";
}
                    var n1=profile.getSubNode("TABSTOP1").get(0),
                        n2=profile.getSubNode("TABSTOP2").get(0),
                        m=linb.Event.getSrc(e),t;
                    if(keys.shiftKey){
                        if(m!==n1)
                            n1.tabIndex = m.tabIndex;
                        n2.removeAttribute("tabIndex");
                    }else{
                        if(m!==n2)
                            n2.tabIndex = m.tabIndex;
                        n1.removeAttribute("tabIndex");
                    }
                    n1=n2=m=null;
                }
            },
            onDragstop:function(profile){
                var pos = profile.getRoot().cssPos(),p=profile.properties,l=null,t=null;
                if(p.left !== pos.left)
                    p.left = l = pos.left;
                if(p.top !== pos.top)
                    p.top = t = pos.top;

                if(profile.onMove && (l!==null||t!==null))
                    profile.boxing().onMove(profile,l,t,null,null);
            },
            TABSTOP1:{
                onFocus:function(profile,e,src){
                    var tabindex = parseInt(linb.use(src).get(0).tabIndex||1 +"")-1;
                    var children = profile.getRoot().get(0).getElementsByTagName('*'),t,n;
                    for(var i=0,l=children.length,o;o=children[i];i++){
                        if(o.nodeType==1){
                            //cant set tabIndex to zero
                            if(o.tabIndex && o.tabIndex<=tabindex){
                                if(!t)t=(n=o).tabIndex;
                                if(o.tabIndex>t)t=(n=o).tabIndex;
                                if(t===tabindex)break;
                            }
                        }
                    }
                    if(o){
                        linb(o).focus();
                        linb.use(src).get(0).tabIndex=o.tabIndex;
                    }
                    else{
                        o=profile.getRoot().nextFocus(false,true,false);
                        linb(o).focus();
                        linb.use(src).get(0).tabIndex=o.get(0).tabIndex;
                    }
                    children=o=null;
                }
            },
            TABSTOP2:{
                onFocus:function(profile,e,src){
                    var tabindex = parseInt(linb.use(src).get(0).tabIndex||1 +"")+1;
                    var children = profile.getRoot().get(0).getElementsByTagName('*'),t,n;
                    for(var i=0,l=children.length,o;o=children[i];i++){
                        if(o.nodeType==1){
                            //cant set tabIndex to zero
                            if(o.tabIndex && o.tabIndex>=tabindex){
                                if(!t)t=(n=o).tabIndex;
                                if(o.tabIndex<t)t=(n=o).tabIndex;
                                if(t===tabindex)break;
                            }
                        }
                    }
                    if(o){
                        linb(o).focus();
                        linb.use(src).get(0).tabIndex=o.tabIndex;
                    }
                    else{
                        o=profile.getRoot().nextFocus(true,true,false);
                        linb(o).focus();
                        linb.use(src).get(0).tabIndex=o.get(0).tabIndex;
                    }
                    children=o=null;
                }
            },
            TBAR:{
                onMousedown:function(profile, e, src){
                    if(linb.Event.getBtn(e)!="left")return;
                    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);
                }
            },
            INFO:{
                onClick:function(profile, e, src){
                    profile.boxing().onShowInfo(profile, e, src);
                }
            },
            OPT:{
                onClick:function(profile, e, src){
                    profile.boxing().onShowOptions(profile, e, src);
                }
            },
            REFRESH:{
                onClick:function(profile, e, src){
                    profile.boxing().onRefresh(profile);
                }
            },
            CLOSE:{
                onClick:function(profile, e, src){
                    profile.boxing().close();
                }
            },
            LAND:{
                onClick:function(profile, e, src){
                    profile.boxing().onLand(profile, e, src);
                }
            }
        },
        DataModel:{
            selectable:true,
            tips:null,
            border:null,
            disabled:null,
            dock:{
                hidden:true
            },
            iframeAutoLoad:"",
            ajaxAutoLoad:"",
            html:{
                action:function(v){
                    this.getSubNode('PANEL').html(v);
                }
            },
            overflow:{
                ini:undefined,
                action:function(v){
                    this.getSubNode('PANEL').css('overflow',v||'');
                }
            },
            // setCaption and getCaption
            caption:{
                ini:undefined,
                // ui update function when setCaption
                action: function(v){
                    v=(_.isSet(v)?v:"")+"";
                    this.getSubNode('CAPTION').html(linb.adjustRes(v,true));
                }
            },
            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');
                }
            },
            infoBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('INFO').css('display',v?'':'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');
                }
            },
            refreshBtn:{
                ini:false,
                action:function(v){
                    this.getSubNode('REFRESH').css('display',v?'':'none');
                }
            },
            pinBtn:{
                ini:false,
                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:{
            onRefresh:function(profile){},
            onShow:function(profile){},
            beforeClose:function(profile){},
            onShowInfo:function(profile, e, src){},
            onShowOptions:function(profile, e, src){},
            onLand: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.infoDisplay = data.infoBtn?'':nodisplay;
            data.optDisplay = data.optBtn?'':nodisplay;
            data.closeDisplay = data.closeBtn?'':nodisplay;
            data.pinDisplay = data.pinBtn?'':nodisplay;
            data.landDisplay = data.landBtn?'':nodisplay;
            data.refreshDisplay= data.refreshBtn?'':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;
            if(_.isStr(data.overflow))
                data._overflow = data.overflow.indexOf(':')!=-1?(data.overflow):("overflow:"+data.overflow);
            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;

            t.status='normal';

            // if from max
            if(status=='max')box._unMax(profile);
            if(status=='min')box._unMin(profile);

            // hide restore button
            profile.getSubNode('RESTORE').css('display','none');

        },
        _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){
                    cover = profile.$modalDiv;
                    if(!cover || !cover.get(0) || !cover.get(0).parentNode)
                        cover = profile.$modalDiv = linb.create("<div style='left:0;top:0;position:absolute;overflow:hidden;display:block;z-index:0;cursor:wait;background-image:url("+linb.ini.img_bg+")'></div>");
                    p.append(cover);

                    // attach onresize event
                    if(p.get(0)===document.body || p.get(0)===document || p.get(0)===window)
                        p=linb.win;

                    cover.css({
                        display:'block',width:Math.max(p.width(),p.scrollWidth())+'px',height:Math.max(p.height(),p.scrollHeight())+'px'
                    })
                    .onMousedown(function(){return false})
                    .topZindex(true);

                    p.onSize(function(p){
                        p=linb(p);
                        // set widht/height first
                        cover.width(p.width()).height(p.height());
                        _.asyRun(function(){
                            cover.width(Math.max(p.width(),p.scrollWidth()));
                            cover.height(Math.max(p.height(),p.scrollHeight()));
                        });
                    },"dialog:"+profile.serialId);

                    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(src,tabindex){
                        tabindex = parseInt(tabindex||1 +"");
                        var children = linb.use(src).get(0).getElementsByTagName('*'),t,n;
                        for(var i=0,l=children.length,o;o=children[i];i++){
                            if(o.nodeType==1){
                                if(o.tabIndex>=tabindex){
                                    if(!t)t=(n=o).tabIndex;
                                    if(o.tabIndex<t)t=(n=o).tabIndex;
                                    if(t===tabindex)break;
                                }
                            }
                        }
                        if(o)linb(o).focus();
                        else profile.getRoot().nextFocus();

                        children=o=null;
                    });
                    */

                    profile.$inModal=true;
                }
            }
        },
        _unModal:function(profile){
            if(profile.$inModal){
                // detach onresize event
                var p=profile.$modalDiv.parent();
                if(p.get(0)===document.body || p.get(0)===document || p.get(0)===window)
                    p=linb.win;

                p.onSize(null, "dialog:"+profile.serialId);

                profile.getRoot().css('zIndex',0);
                profile.getSubNode('BORDER').append(profile.$modalDiv.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,top: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');
            }
            n2.html("",false);
            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 + 40;
            h=size.height + 90;
            dialog.setCaption(caption).setWidth(w).setHeight(h);
            return {width:w, height:h};
        },
        alert:function(title, content, onClose, btnCap, left, top, parent, subId, noCache){
            var me=arguments.callee, dialog;
            if(noCache || !(dialog=me.dialog) || !dialog.get(0) || (!dialog.get(0).renderId)){
                dialog = new linb.UI.Dialog({
                    minBtn:false,
                    maxBtn:false,
                    pinBtn:false,
                    resizer:false
                },{
                    beforeClose:function(){
                        _.tryF(dialog._$onClose);
                        dialog._$onClose=null;
                        if(!noCache){
                            dialog.hide();
                            return false;
                        }
                    },
                    onHotKeydown:function(p,k){
                        if(k.key=='esc')
                            dialog.close();
                    }
                });

                var cmd = dialog.$cmd = new linb.UI.Div({
                    height:26,
                    dock:'bottom'
                },null,null,null,{KEY:"text-align:center;"}),

                btn = dialog.$btn = new linb.UI.SButton({
                    position:'relative',
                    tabindex:1
                },
                {
                    onClick:function(){
                        dialog.close();
                    },
                    onHotKeydown:function(p,k){
                        if(k.key=='enter')
                            dialog.close();
                    }
                },null,null,{KEY:'margin:0 4px'});
                cmd.append(btn);

                var div = dialog.$div = new linb.UI.Div({
                    left:10,
                    top:10
                });
                dialog.append(cmd).append(div).render();
                
                if(!noCache)
                    me.dialog = dialog;
            }
            dialog._$onClose=onClose;
            
            dialog.$btn.setCaption("&nbsp;&nbsp;"+(btnCap || linb.wrapRes('$inline.ok'))+"&nbsp;&nbsp;");

            var size=linb.UI.Dialog._adjust(dialog,title, content);

            if(parent && parent["linb.UI"])parent=parent.getContainer(subId);
            if(!_.isSet(parent))parent=linb('body');
            if(!_.isSet(left))left=((parent.get(0)==linb('body').get(0)?linb.win:parent).width()-size.width)/2;
            if(!_.isSet(top))top=((parent.get(0)==linb('body').get(0)?linb.win:parent).height()-size.height)/2;
            
            dialog.show(parent,true, left, top);
            _.resetRun("dlg_focus:"+dialog.get(0).$linbid,function(){
                dialog.$btn.activate();
            });
            return dialog;
        },
        confirm:function(title, caption, onYes, onNo, btnCapYes, btnCapNo, left, top, parent, subId, noCache){
            var me=arguments.callee, dialog;

            if(noCache || !(dialog=me.dialog) || !dialog.get(0) || (!dialog.get(0).renderId)){
                dialog = new linb.UI.Dialog({
                    minBtn:false,
                    maxBtn:false,
                    pinBtn:false,
                    resizer:false
                },{
                    beforeClose:function(){
                        if(!dialog._$_clicked)
                            _.tryF(dialog._$onNo,['close']);
                        else
                            delete dialog._$_clicked;
                        dialog._$onYes=dialog._$onNo=null;
                        if(!noCache){
                            dialog.hide();
                            return false;
                        }
                    }
                });

                var cmd = dialog.$cmd=new linb.UI.Div({
                    height:26,
                    dock:'bottom'
                },null,null,null,{KEY:"text-align:center;"}),
                btn = dialog.$btn1 = new linb.UI.SButton({
                    tabindex:1,
                    position:'relative'
                },
                {
                    onClick:function(){
                        _.tryF(dialog._$onYes);
                        dialog._$_clicked=1;
                        dialog.close();
                    }
                },null,null,{KEY:'margin:0 4px'});
                cmd.append(btn);

                btn = dialog.$btn2=new linb.UI.SButton({
                    tabindex:1,
                    position:'relative'
                },
                {
                    onClick:function(){
                        _.tryF(dialog._$onNo,['no']);
                        dialog._$_clicked=1;
                        dialog.close();
                    }
                },null,null,{KEY:'margin:0 4px'});
                cmd.append(btn);

                var div = dialog.$div=new linb.UI.Div({
                    left:10,
                    top:10
                });
                dialog.append(cmd).append(div).render();

                if(!noCache)
                    me.dialog = dialog;
            }
            dialog._$onYes=onYes;
            dialog._$onNo=onNo;
            delete dialog._$_clicked;
            dialog.$btn1.setCaption("&nbsp;&nbsp;"+(btnCapYes || linb.wrapRes('$inline.yes'))+"&nbsp;&nbsp;");
            dialog.$btn2.setCaption("&nbsp;&nbsp;"+(btnCapNo || linb.wrapRes('$inline.no'))+"&nbsp;&nbsp;");
            var size=linb.UI.Dialog._adjust(dialog, title, caption);

            if(parent && parent["linb.UI"])parent=parent.getContainer(subId);
            if(!_.isSet(parent))parent=linb('body');
            if(!_.isSet(left))left=((parent.get(0)==linb('body').get(0)?linb.win:parent).width()-size.width)/2;
            if(!_.isSet(top))top=((parent.get(0)==linb('body').get(0)?linb.win:parent).height()-size.height)/2;

            dialog.show(parent, true, left, top);
            _.resetRun("dlg_focus:"+dialog.get(0).$linbid,function(){
                dialog.$btn2.activate();
            });
            return dialog;
        },
        pop:function(title, content, btnCap, left, top, parent, subId){
            var dialog = new linb.UI.Dialog({
                minBtn:false,
                maxBtn:false,
                pinBtn:false,
                resizer:false
            },{
                onHotKeydown:function(p,k){
                    if(k.key=='esc')
                        dialog.close();
                }
            }),

            cmd = dialog.$cmd = new linb.UI.Div({
                    height:26,
                    dock:'bottom'
                },null,null,null,{KEY:"text-align:center;"})
            .append( dialog.$btn = new linb.UI.SButton({
                caption: "&nbsp;&nbsp;"+(btnCap || '$inline.ok')+"&nbsp;&nbsp;",
                tabindex:1,
                position:'relative'
            },
            {
                onClick:function(){
                    dialog.destroy();
                },
                onHotKeydown:function(p,k){
                    if(k.key=='enter')
                        dialog.close();
                }
            },null,null,{KEY:'margin:0 4px'})),

            div = dialog.$div = new linb.UI.Div({
                left:10,
                top:10,
                width:80
            }).setCustomStyle({
                KEY:'overflow:visible'
            });

            dialog.append(cmd).append(div).render();;

            var size=linb.UI.Dialog._adjust(dialog, title, content);

            if(parent && parent["linb.UI"])parent=parent.getContainer(subId);
            if(!_.isSet(parent))parent=linb('body');
            if(!_.isSet(left))left=((parent.get(0)==linb('body').get(0)?linb.win:parent).width()-size.width)/2;
            if(!_.isSet(top))top=((parent.get(0)==linb('body').get(0)?linb.win:parent).height()-size.height)/2;

            dialog.show(parent,false,left, top);

            _.resetRun("dlg_focus:"+dialog.get(0).$linbid,function(){
                dialog.$btn.activate();
            });
            return dialog;
        },
        prompt:function(title, caption, content, onYes, onNo, btnCapYes, btnCapNo, left, top, parent, subId, noCache){
            var dialog,
                me=arguments.callee;
            if(noCache || !(dialog=me.dialog) || !dialog.get(0) || (!dialog.get(0).renderId)){
                dialog = new linb.UI.Dialog({
                    minBtn:false,
                    maxBtn:false,
                    pinBtn:false,
                    resizer:false,
                    left:200,
                    top:200,
                    width:300,
                    height:130
                },{
                    beforeClose:function(){
                        if(!dialog._$_clickYes)
                        _.tryF(dialog._$onNo);
                        else
                            delete dialog._$_clickYes;

                        dialog._$inp.setValue('');
                        dialog._$onYes=dialog._$onNo=null;
                        if(!noCache){
                            dialog.hide();
                            return false;                        }
                    }
                });
                var con = dialog._$con = new linb.UI.Div({
                    top:4,
                    left:10,
                    width:270,
                    height:18
                }),
                cmd = new linb.UI.Div({
                    height:26,
                    dock:'bottom'
                },null,null,null,{KEY:"text-align:center;"})
                .append(dialog.$btn1 = new linb.UI.SButton({
                    position:'relative',
                    tabindex:1
                },
                {
                    onClick:function(){
                        if(false!==_.tryF(dialog._$onYes,[dialog._$inp.getUIValue()])){
                            dialog._$_clickYes=1;
                            dialog.close();
                        }
                    }
                },null,null,{KEY:'margin:0 4px'}));

                cmd.append(dialog.$btn2 = new linb.UI.SButton({
                    tabindex:1,
                    position:'relative'
                },
                {
                    onClick:function(){
                        dialog.close();
                    }
                },null,null,{KEY:'margin:0 4px'}));
                var inp=dialog._$inp=new linb.UI.Input({
                    left:10,
                    top:22,
                    width:270,
                    height:36,
                    multiLines:true
                })
                dialog.append(con).append(cmd).append(inp).render();
                if(!noCache)
                    me.dialog = dialog;
            }
            dialog.setCaption(title||'Prompt');
            dialog._$con.setHtml(caption||"");
            dialog._$inp.setValue(content||"",true);
            dialog._$onYes=onYes;
            dialog._$onNo=onNo;
            delete dialog._$_clickYes;
            dialog.$btn1.setCaption("&nbsp;&nbsp;"+(btnCapYes || linb.wrapRes('$inline.ok'))+"&nbsp;&nbsp;");
            dialog.$btn2.setCaption("&nbsp;&nbsp;"+(btnCapNo || linb.wrapRes('$inline.cancel'))+"&nbsp;&nbsp;");

            if(parent && parent["linb.UI"])parent=parent.getContainer(subId);
            if(!_.isSet(parent))parent=linb('body');
            if(!_.isSet(left))left=((parent.get(0)==linb('body').get(0)?linb.win:parent).width()-dialog.getWidth())/2;
            if(!_.isSet(top))top=((parent.get(0)==linb('body').get(0)?linb.win:parent).height()-dialog.getHeight())/2;

            dialog.show(parent, true, left, top);
            _.resetRun("dlg_focus:"+dialog.get(0).$linbid,function(){
                dialog._$inp.activate();
            });
            return dialog;
        },
        //
        _onresize:function(profile,width,height,force){
        		if(width && profile.properties.status=='min')
        			width=profile.properties.minWidth;

            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);
        }
    }
});

