All Downloads are FREE. Search and download functionalities are using the official Maven repository.

static.extjs.ext-all-debug.js Maven / Gradle / Ivy

/*
This file is part of Ext JS 4.2

Copyright (c) 2011-2013 Sencha Inc

Contact:  http://www.sencha.com/contact

Commercial Usage
Licensees holding valid commercial licenses may use this file in accordance with the Commercial
Software License Agreement provided with the Software or, alternatively, in accordance with the
terms contained in a written agreement between you and Sencha.

If you are unsure which license is appropriate for your use, please contact the sales department
at http://www.sencha.com/contact.

Build date: 2013-09-18 17:18:59 (940c324ac822b840618a3a8b2b4b873f83a1a9b1)
*/





var Ext = Ext || {};
Ext._startTime = new Date().getTime();
(function() {
    var global = this,
        objectPrototype = Object.prototype,
        toString = objectPrototype.toString,
        enumerables = true,
        enumerablesTest = {toString: 1},
        emptyFn = function () {},
        
        
        callOverrideParent = function () {
            var method = callOverrideParent.caller.caller; 
            return method.$owner.prototype[method.$name].apply(this, arguments);
        },
        i,
        nonWhitespaceRe = /\S/,
        ExtApp,
        iterableRe = /\[object\s*(?:Array|Arguments|\w*Collection|\w*List|HTML\s+document\.all\s+class)\]/;

    Ext.global = global;

    for (i in enumerablesTest) {
        enumerables = null;
    }

    if (enumerables) {
        enumerables = ['hasOwnProperty', 'valueOf', 'isPrototypeOf', 'propertyIsEnumerable',
                       'toLocaleString', 'toString', 'constructor'];
    }

    
    Ext.enumerables = enumerables;

    
    Ext.apply = function(object, config, defaults) {
        if (defaults) {
            Ext.apply(object, defaults);
        }

        if (object && config && typeof config === 'object') {
            var i, j, k;

            for (i in config) {
                object[i] = config[i];
            }

            if (enumerables) {
                for (j = enumerables.length; j--;) {
                    k = enumerables[j];
                    if (config.hasOwnProperty(k)) {
                        object[k] = config[k];
                    }
                }
            }
        }

        return object;
    };

    Ext.buildSettings = Ext.apply({
        baseCSSPrefix: 'x-'
    }, Ext.buildSettings || {});

    Ext.apply(Ext, {

        
        name: Ext.sandboxName || 'Ext',

        
        emptyFn: emptyFn,
        
        
        identityFn: function(o) {
            return o;
        },

        
        emptyString: new String(),

        baseCSSPrefix: Ext.buildSettings.baseCSSPrefix,

        
        applyIf: function(object, config) {
            var property;

            if (object) {
                for (property in config) {
                    if (object[property] === undefined) {
                        object[property] = config[property];
                    }
                }
            }

            return object;
        },

        
        iterate: function(object, fn, scope) {
            if (Ext.isEmpty(object)) {
                return;
            }

            if (scope === undefined) {
                scope = object;
            }

            if (Ext.isIterable(object)) {
                Ext.Array.each.call(Ext.Array, object, fn, scope);
            }
            else {
                Ext.Object.each.call(Ext.Object, object, fn, scope);
            }
        }
    });

    Ext.apply(Ext, {

        
        extend: (function() {
            
            var objectConstructor = objectPrototype.constructor,
                inlineOverrides = function(o) {
                for (var m in o) {
                    if (!o.hasOwnProperty(m)) {
                        continue;
                    }
                    this[m] = o[m];
                }
            };

            return function(subclass, superclass, overrides) {
                
                if (Ext.isObject(superclass)) {
                    overrides = superclass;
                    superclass = subclass;
                    subclass = overrides.constructor !== objectConstructor ? overrides.constructor : function() {
                        superclass.apply(this, arguments);
                    };
                }


                
                var F = function() {},
                    subclassProto, superclassProto = superclass.prototype;

                F.prototype = superclassProto;
                subclassProto = subclass.prototype = new F();
                subclassProto.constructor = subclass;
                subclass.superclass = superclassProto;

                if (superclassProto.constructor === objectConstructor) {
                    superclassProto.constructor = superclass;
                }

                subclass.override = function(overrides) {
                    Ext.override(subclass, overrides);
                };

                subclassProto.override = inlineOverrides;
                subclassProto.proto = subclassProto;

                subclass.override(overrides);
                subclass.extend = function(o) {
                    return Ext.extend(subclass, o);
                };

                return subclass;
            };
        }()),

        
        override: function (target, overrides) {
            if (target.$isClass) {
                target.override(overrides);
            } else if (typeof target == 'function') {
                Ext.apply(target.prototype, overrides);
            } else {
                var owner = target.self,
                    name, value;

                if (owner && owner.$isClass) { 
                    for (name in overrides) {
                        if (overrides.hasOwnProperty(name)) {
                            value = overrides[name];

                            if (typeof value == 'function') {

                                value.$name = name;
                                value.$owner = owner;
                                value.$previous = target.hasOwnProperty(name)
                                    ? target[name] 
                                    : callOverrideParent; 
                            }

                            target[name] = value;
                        }
                    }
                } else {
                    Ext.apply(target, overrides);
                }
            }

            return target;
        }
    });

    
    Ext.apply(Ext, {

        
        valueFrom: function(value, defaultValue, allowBlank){
            return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
        },

        
        typeOf: function(value) {
            var type,
                typeToString;
            
            if (value === null) {
                return 'null';
            }

            type = typeof value;

            if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') {
                return type;
            }

            typeToString = toString.call(value);

            switch(typeToString) {
                case '[object Array]':
                    return 'array';
                case '[object Date]':
                    return 'date';
                case '[object Boolean]':
                    return 'boolean';
                case '[object Number]':
                    return 'number';
                case '[object RegExp]':
                    return 'regexp';
            }

            if (type === 'function') {
                return 'function';
            }

            if (type === 'object') {
                if (value.nodeType !== undefined) {
                    if (value.nodeType === 3) {
                        return (nonWhitespaceRe).test(value.nodeValue) ? 'textnode' : 'whitespace';
                    }
                    else {
                        return 'element';
                    }
                }

                return 'object';
            }

        },

        
        coerce: function(from, to) {
            var fromType = Ext.typeOf(from),
                toType = Ext.typeOf(to),
                isString = typeof from === 'string';

            if (fromType !== toType) {
                switch (toType) {
                    case 'string':
                        return String(from);
                    case 'number':
                        return Number(from);
                    case 'boolean':
                        return isString && (!from || from === 'false') ? false : Boolean(from);
                    case 'null':
                        return isString && (!from || from === 'null') ? null : from;
                    case 'undefined':
                        return isString && (!from || from === 'undefined') ? undefined : from;
                    case 'date':
                        return isString && isNaN(from) ? Ext.Date.parse(from, Ext.Date.defaultFormat) : Date(Number(from));
                }
            }
            return from;
        },

        
        isEmpty: function(value, allowEmptyString) {
            return (value === null) || (value === undefined) || (!allowEmptyString ? value === '' : false) || (Ext.isArray(value) && value.length === 0);
        },

        
        isArray: ('isArray' in Array) ? Array.isArray : function(value) {
            return toString.call(value) === '[object Array]';
        },

        
        isDate: function(value) {
            return toString.call(value) === '[object Date]';
        },

        
        isObject: (toString.call(null) === '[object Object]') ?
        function(value) {
            
            return value !== null && value !== undefined && toString.call(value) === '[object Object]' && value.ownerDocument === undefined;
        } :
        function(value) {
            return toString.call(value) === '[object Object]';
        },

        
        isSimpleObject: function(value) {
            return value instanceof Object && value.constructor === Object;
        },
        
        isPrimitive: function(value) {
            var type = typeof value;

            return type === 'string' || type === 'number' || type === 'boolean';
        },

        
        isFunction:
        
        
        (typeof document !== 'undefined' && typeof document.getElementsByTagName('body') === 'function') ? function(value) {
            return !!value && toString.call(value) === '[object Function]';
        } : function(value) {
            return !!value && typeof value === 'function';
        },

        
        isNumber: function(value) {
            return typeof value === 'number' && isFinite(value);
        },

        
        isNumeric: function(value) {
            return !isNaN(parseFloat(value)) && isFinite(value);
        },

        
        isString: function(value) {
            return typeof value === 'string';
        },

        
        isBoolean: function(value) {
            return typeof value === 'boolean';
        },

        
        isElement: function(value) {
            return value ? value.nodeType === 1 : false;
        },

        
        isTextNode: function(value) {
            return value ? value.nodeName === "#text" : false;
        },

        
        isDefined: function(value) {
            return typeof value !== 'undefined';
        },

        
        isIterable: function(value) {
            
            if (!value || typeof value.length !== 'number' || typeof value === 'string' || Ext.isFunction(value)) {
                return false;
            }

            
            
            
            if (!value.propertyIsEnumerable) {
                return !!value.item;
            }

            
            
            if (value.hasOwnProperty('length') && !value.propertyIsEnumerable('length')) {
                return true;
            }

            
            return iterableRe.test(toString.call(value));
        }
    });

    Ext.apply(Ext, {

        
        clone: function(item) {
            var type,
                i,
                j,
                k,
                clone,
                key;
            
            if (item === null || item === undefined) {
                return item;
            }

            
            
            
            if (item.nodeType && item.cloneNode) {
                return item.cloneNode(true);
            }

            type = toString.call(item);

            
            if (type === '[object Date]') {
                return new Date(item.getTime());
            }


            
            if (type === '[object Array]') {
                i = item.length;

                clone = [];

                while (i--) {
                    clone[i] = Ext.clone(item[i]);
                }
            }
            
            else if (type === '[object Object]' && item.constructor === Object) {
                clone = {};

                for (key in item) {
                    clone[key] = Ext.clone(item[key]);
                }

                if (enumerables) {
                    for (j = enumerables.length; j--;) {
                        k = enumerables[j];
                        if (item.hasOwnProperty(k)) {
                            clone[k] = item[k];
                        }
                    }
                }
            }

            return clone || item;
        },

        
        getUniqueGlobalNamespace: function() {
            var uniqueGlobalNamespace = this.uniqueGlobalNamespace,
                i;

            if (uniqueGlobalNamespace === undefined) {
                i = 0;

                do {
                    uniqueGlobalNamespace = 'ExtBox' + (++i);
                } while (Ext.global[uniqueGlobalNamespace] !== undefined);

                Ext.global[uniqueGlobalNamespace] = Ext;
                this.uniqueGlobalNamespace = uniqueGlobalNamespace;
            }

            return uniqueGlobalNamespace;
        },
        
        
        functionFactoryCache: {},
        
        cacheableFunctionFactory: function() {
            var me = this,
                args = Array.prototype.slice.call(arguments),
                cache = me.functionFactoryCache,
                idx, fn, ln;
                
             if (Ext.isSandboxed) {
                ln = args.length;
                if (ln > 0) {
                    ln--;
                    args[ln] = 'var Ext=window.' + Ext.name + ';' + args[ln];
                }
            }
            idx = args.join('');
            fn = cache[idx];
            if (!fn) {
                fn = Function.prototype.constructor.apply(Function.prototype, args);
                
                cache[idx] = fn;
            }
            return fn;
        },
        
        functionFactory: function() {
            var me = this,
                args = Array.prototype.slice.call(arguments),
                ln;
                
            if (Ext.isSandboxed) {
                ln = args.length;
                if (ln > 0) {
                    ln--;
                    args[ln] = 'var Ext=window.' + Ext.name + ';' + args[ln];
                }
            }
     
            return Function.prototype.constructor.apply(Function.prototype, args);
        },

        
        Logger: {
            verbose: emptyFn,
            log: emptyFn,
            info: emptyFn,
            warn: emptyFn,
            error: function(message) {
                throw new Error(message);
            },
            deprecate: emptyFn
        }
    });

    
    Ext.type = Ext.typeOf;
    
    
    
    
    ExtApp = Ext.app;
    if (!ExtApp) {
        ExtApp = Ext.app = {};
    }
    Ext.apply(ExtApp, {
        namespaces: {},
        
        
        collectNamespaces: function(paths) {
            var namespaces = Ext.app.namespaces,
                path;
            
            for (path in paths) {
                if (paths.hasOwnProperty(path)) {
                    namespaces[path] = true;
                }
            }
        },

        
        addNamespaces: function(ns) {
            var namespaces = Ext.app.namespaces,
                i, l;

            if (!Ext.isArray(ns)) {
                ns = [ns];
            }

            for (i = 0, l = ns.length; i < l; i++) {
                namespaces[ns[i]] = true;
            }
        },

        
        clearNamespaces: function() {
            Ext.app.namespaces = {};
        },

        
        getNamespace: function(className) {
            var namespaces    = Ext.app.namespaces,
                deepestPrefix = '',
                prefix;

            for (prefix in namespaces) {
                if (namespaces.hasOwnProperty(prefix)    &&
                    prefix.length > deepestPrefix.length &&
                    (prefix + '.' === className.substring(0, prefix.length + 1))) {
                    deepestPrefix = prefix;
                }
            }

            return deepestPrefix === '' ? undefined : deepestPrefix;
        }
    });
}());


Ext.globalEval = Ext.global.execScript
    ? function(code) {
        execScript(code);
    }
    : function($$code) {
        
        
        (function(){
            
            
            
            var Ext = this.Ext;
            eval($$code);
        }());
    };






(function() {



var version = '4.2.2.1144',
    
    checkVerTemp = [''],
    endOfVersionRe = /([^\d\.])/,
    notDigitsRe = /[^\d]/g,
    plusMinusRe = /[\-+]/g,
    stripRe = /\s/g,
    underscoreRe = /_/g,
    Version;

    Ext.Version = Version = Ext.extend(Object, {
        isVersion: true,

        padModes: {
            '~': NaN,
            '^': Infinity
        },

        
        release: '',

        
        constructor: function (version, defaultMode) {
            var me = this,
                padModes = me.padModes,
                ch, i, pad, parts, release, releaseStartIndex, ver;

            if (version.isVersion) {
                return version;
            }

            me.version = ver = String(version).toLowerCase().
                                    replace(underscoreRe, '.').replace(plusMinusRe, '');

            ch = ver.charAt(0);
            if (ch in padModes) {
                ver = ver.substring(1);
                pad = padModes[ch];
            } else {
                pad = defaultMode ? padModes[defaultMode] : 0; 
            }
            me.pad = pad;

            releaseStartIndex = ver.search(endOfVersionRe);
            me.shortVersion = ver;

            if (releaseStartIndex !== -1) {
                me.release = release = ver.substr(releaseStartIndex, version.length);
                me.shortVersion = ver.substr(0, releaseStartIndex);
                release = Version.releaseValueMap[release] || release;
            }

            me.releaseValue = release || pad;
            me.shortVersion = me.shortVersion.replace(notDigitsRe, '');

            
            me.parts = parts = ver.split('.');
            for (i = parts.length; i--; ) {
                parts[i] = parseInt(parts[i], 10);
            }
            if (pad === Infinity) {
                
                parts.push(pad);
            }

            
            me.major = parts[0] || pad;

            
            me.minor = parts[1] || pad;

            
            me.patch = parts[2] || pad;

            
            me.build = parts[3] || pad;

            return me;
        },

        
        compareTo: function (other) {
             
             
            var me = this,
                lhsPad = me.pad,
                lhsParts = me.parts,
                lhsLength = lhsParts.length,
                rhsVersion = other.isVersion ? other : new Version(other),
                rhsPad = rhsVersion.pad,
                rhsParts = rhsVersion.parts,
                rhsLength = rhsParts.length,
                length = Math.max(lhsLength, rhsLength),
                i, lhs, rhs;

            for (i = 0; i < length; i++) {
                lhs = (i < lhsLength) ? lhsParts[i] : lhsPad;
                rhs = (i < rhsLength) ? rhsParts[i] : rhsPad;

                
                
                if (lhs < rhs) {
                    return -1;
                }
                if (lhs > rhs) {
                    return 1;
                }
            }

            
            lhs = me.releaseValue;
            rhs = rhsVersion.releaseValue;
            if (lhs < rhs) {
                return -1;
            }
            if (lhs > rhs) {
                return 1;
            }

            return 0;
        },

        
        toString: function() {
            return this.version;
        },

        
        valueOf: function() {
            return this.version;
        },

        
        getMajor: function() {
            return this.major;
        },

        
        getMinor: function() {
            return this.minor;
        },

        
        getPatch: function() {
            return this.patch;
        },

        
        getBuild: function() {
            return this.build;
        },

        
        getRelease: function() {
            return this.release;
        },

        
        getReleaseValue: function() {
            return this.releaseValue;
        },

        
        isGreaterThan: function(target) {
            return this.compareTo(target) > 0;
        },

        
        isGreaterThanOrEqual: function(target) {
            return this.compareTo(target) >= 0;
        },

        
        isLessThan: function(target) {
            return this.compareTo(target) < 0;
        },

        
        isLessThanOrEqual: function(target) {
            return this.compareTo(target) <= 0;
        },

        
        equals: function(target) {
            return this.compareTo(target) === 0;
        },

        
        match: function(target) {
            target = String(target);
            return this.version.substr(0, target.length) === target;
        },

        
        toArray: function() {
            var me = this;
            return [me.getMajor(), me.getMinor(), me.getPatch(), me.getBuild(), me.getRelease()];
        },

        
        getShortVersion: function() {
            return this.shortVersion;
        },

        
        gt: function (target) {
            return this.compareTo(target) > 0;
        },

        
        lt: function (target) {
            return this.compareTo(target) < 0;
        },

        
        gtEq: function (target) {
            return this.compareTo(target) >= 0;
        },

        
        ltEq: function (target) {
            return this.compareTo(target) <= 0;
        }
    });

    Ext.apply(Version, {
        
        releaseValueMap: {
            dev:   -6,
            alpha: -5,
            a:     -5,
            beta:  -4,
            b:     -4,
            rc:    -3,
            '#':   -2,
            p:     -1,
            pl:    -1
        },

        
        getComponentValue: function(value) {
            return !value ? 0 : (isNaN(value) ? this.releaseValueMap[value] || value : parseInt(value, 10));
        },

        
        compare: function (current, target) {
            var ver = current.isVersion ? current : new Version(current);
            return ver.compareTo(target);
        }
    });

    
    Ext.apply(Ext, {
        
        versions: {},

        
        lastRegisteredVersion: null,

        
        setVersion: function(packageName, version) {
            Ext.lastRegisteredVersion = Ext.versions[packageName] = new Version(version);
            return this;
        },

        
        getVersion: function(packageName) {
            if (packageName === undefined) {
                return Ext.lastRegisteredVersion;
            }

            return Ext.versions[packageName];
        },

        
        checkVersion: function (specs, matchAll) {
            var isArray = Ext.isArray(specs),
                compat = isArray ? specs : checkVerTemp,
                length = compat.length,
                versions = Ext.versions,
                frameworkVer = versions.ext || versions.touch,
                i, index, matches, minVer, maxVer, spec, range, ver;

            if (!isArray) {
                checkVerTemp[0] = specs;
            }

            for (i = 0; i < length; ++i) {
                if (!Ext.isString(spec = compat[i])) {
                    matches = Ext.checkVersion(spec.and || spec.or, !spec.or);
                    if (spec.not) {
                        matches = !matches;
                    }
                } else {
                    if (spec.indexOf(' ') >= 0) {
                        spec = spec.replace(stripRe, '');
                    }

                    
                    
                    index = spec.indexOf('@');
                    if (index < 0) {
                        range = spec;
                        ver = frameworkVer;
                    } else {
                        if (!(ver = versions[spec.substring(0, index)])) {
                            
                            
                            if (matchAll) {
                                return false;
                            }
                            
                            
                            continue;
                        }
                        range = spec.substring(index+1);
                    }

                    
                    index = range.indexOf('-');
                    if (index < 0) {
                        
                        if (range.charAt(index = range.length - 1) === '+') {
                            minVer = range.substring(0, index);
                            maxVer = null;
                        } else {
                            minVer = maxVer = range;
                        }
                    } else if (index > 0) {
                        
                        minVer = range.substring(0, index);
                        maxVer = range.substring(index+1); 
                    } else {
                        
                        minVer = null;
                        maxVer = range.substring(index+1);
                    }

                    matches = true;
                    if (minVer) {
                        minVer = new Version(minVer, '~'); 
                        matches = minVer.ltEq(ver);
                    }
                    if (matches && maxVer) {
                        maxVer = new Version(maxVer, '~'); 
                        matches = maxVer.gtEq(ver);
                    }
                } 

                if (matches) {
                    
                    if (!matchAll) {
                        return true;
                    }
                } else if (matchAll) {
                    
                    return false;
                }
            }

            
            
            
            
            return !!matchAll;
        },

        
        deprecate: function(packageName, since, closure, scope) {
            if (Version.compare(Ext.getVersion(packageName), since) < 1) {
                closure.call(scope);
            }
        }
    }); 

    Ext.setVersion('core', version);

}());







Ext.String = (function() {
    var trimRegex     = /^[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+|[\x09\x0a\x0b\x0c\x0d\x20\xa0\u1680\u180e\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u2028\u2029\u202f\u205f\u3000]+$/g,
        escapeRe      = /('|\\)/g,
        formatRe      = /\{(\d+)\}/g,
        escapeRegexRe = /([-.*+?\^${}()|\[\]\/\\])/g,
        basicTrimRe   = /^\s+|\s+$/g,
        whitespaceRe  = /\s+/,
        varReplace    = /(^[^a-z]*|[^\w])/gi,
        charToEntity,
        entityToChar,
        charToEntityRegex,
        entityToCharRegex,
        htmlEncodeReplaceFn = function(match, capture) {
            return charToEntity[capture];
        },
        htmlDecodeReplaceFn = function(match, capture) {
            return (capture in entityToChar) ? entityToChar[capture] : String.fromCharCode(parseInt(capture.substr(2), 10));
        },
        boundsCheck = function(s, other){
            if (s === null || s === undefined || other === null || other === undefined) {
                return false;
            }
            
            return other.length <= s.length; 
        };

    return {
        
        
        insert: function(s, value, index) {
            if (!s) {
                return value;
            }
            
            if (!value) {
                return s;
            }
            
            var len = s.length;
            
            if (!index && index !== 0) {
                index = len;
            }
            
            if (index < 0) {
                index *= -1;
                if (index >= len) {
                    
                    index = 0;
                } else {
                    index = len - index;
                }
            }
            
            if (index === 0) {
                s = value + s;
            } else if (index >= s.length) {
                s += value;
            } else {
                s = s.substr(0, index) + value + s.substr(index);
            }
            return s;
        },
        
        
        startsWith: function(s, start, ignoreCase){
            var result = boundsCheck(s, start);
            
            if (result) {
                if (ignoreCase) {
                    s = s.toLowerCase();
                    start = start.toLowerCase();
                }
                result = s.lastIndexOf(start, 0) === 0;
            }
            return result;
        },
        
        
        endsWith: function(s, end, ignoreCase){
            var result = boundsCheck(s, end);
            
            if (result) {
                if (ignoreCase) {
                    s = s.toLowerCase();
                    end = end.toLowerCase();
                }
                result = s.indexOf(end, s.length - end.length) !== -1;
            }
            return result;
        },

        
        createVarName: function(s) {
            return s.replace(varReplace, '');
        },

        
        htmlEncode: function(value) {
            return (!value) ? value : String(value).replace(charToEntityRegex, htmlEncodeReplaceFn);
        },

        
        htmlDecode: function(value) {
            return (!value) ? value : String(value).replace(entityToCharRegex, htmlDecodeReplaceFn);
        },
        
        
        hasHtmlCharacters: function(s) {
            return charToEntityRegex.test(s);
        },

        
        addCharacterEntities: function(newEntities) {
            var charKeys = [],
                entityKeys = [],
                key, echar;
            for (key in newEntities) {
                echar = newEntities[key];
                entityToChar[key] = echar;
                charToEntity[echar] = key;
                charKeys.push(echar);
                entityKeys.push(key);
            }
            charToEntityRegex = new RegExp('(' + charKeys.join('|') + ')', 'g');
            entityToCharRegex = new RegExp('(' + entityKeys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
        },

        
        resetCharacterEntities: function() {
            charToEntity = {};
            entityToChar = {};
            
            this.addCharacterEntities({
                '&'     :   '&',
                '>'      :   '>',
                '<'      :   '<',
                '"'    :   '"',
                '''     :   "'"
            });
        },

        
        urlAppend : function(url, string) {
            if (!Ext.isEmpty(string)) {
                return url + (url.indexOf('?') === -1 ? '?' : '&') + string;
            }

            return url;
        },

        
        trim: function(string) {
            return string.replace(trimRegex, "");
        },

        
        capitalize: function(string) {
            return string.charAt(0).toUpperCase() + string.substr(1);
        },

        
        uncapitalize: function(string) {
            return string.charAt(0).toLowerCase() + string.substr(1);
        },

        
        ellipsis: function(value, len, word) {
            if (value && value.length > len) {
                if (word) {
                    var vs = value.substr(0, len - 2),
                    index = Math.max(vs.lastIndexOf(' '), vs.lastIndexOf('.'), vs.lastIndexOf('!'), vs.lastIndexOf('?'));
                    if (index !== -1 && index >= (len - 15)) {
                        return vs.substr(0, index) + "...";
                    }
                }
                return value.substr(0, len - 3) + "...";
            }
            return value;
        },

        
        escapeRegex: function(string) {
            return string.replace(escapeRegexRe, "\\$1");
        },

        
        escape: function(string) {
            return string.replace(escapeRe, "\\$1");
        },

        
        toggle: function(string, value, other) {
            return string === value ? other : value;
        },

        
        leftPad: function(string, size, character) {
            var result = String(string);
            character = character || " ";
            while (result.length < size) {
                result = character + result;
            }
            return result;
        },

        
        format: function(format) {
            var args = Ext.Array.toArray(arguments, 1);
            return format.replace(formatRe, function(m, i) {
                return args[i];
            });
        },

        
        repeat: function(pattern, count, sep) {
            if (count < 1) {
                count = 0;
            }
            for (var buf = [], i = count; i--; ) {
                buf.push(pattern);
            }
            return buf.join(sep || '');
        },

        
        splitWords: function (words) {
            if (words && typeof words == 'string') {
                return words.replace(basicTrimRe, '').split(whitespaceRe);
            }
            return words || [];
        }
    };
}());


Ext.String.resetCharacterEntities();


Ext.htmlEncode = Ext.String.htmlEncode;



Ext.htmlDecode = Ext.String.htmlDecode;


Ext.urlAppend = Ext.String.urlAppend;







Ext.Number = new function() {

    var me = this,
        isToFixedBroken = (0.9).toFixed() !== '1',
        math = Math;

    Ext.apply(this, {
        
        constrain: function(number, min, max) {
            var x = parseFloat(number);

            
            

            
            
            
            
            
            return (x < min) ? min : ((x > max) ? max : x);
        },

        
        snap : function(value, increment, minValue, maxValue) {
            var m;

            
            
            if (value === undefined || value < minValue) {
                return minValue || 0;
            }

            if (increment) {
                m = value % increment;
                if (m !== 0) {
                    value -= m;
                    if (m * 2 >= increment) {
                        value += increment;
                    } else if (m * 2 < -increment) {
                        value -= increment;
                    }
                }
            }
            return me.constrain(value, minValue,  maxValue);
        },

        
        snapInRange : function(value, increment, minValue, maxValue) {
            var tween;

            
            minValue = (minValue || 0);

            
            if (value === undefined || value < minValue) {
                return minValue;
            }

            
            if (increment && (tween = ((value - minValue) % increment))) {
                value -= tween;
                tween *= 2;
                if (tween >= increment) {
                    value += increment;
                }
            }

            
            if (maxValue !== undefined) {
                if (value > (maxValue = me.snapInRange(maxValue, increment, minValue))) {
                    value = maxValue;
                }
            }

            return value;
        },

        
        toFixed: isToFixedBroken ? function(value, precision) {
            precision = precision || 0;
            var pow = math.pow(10, precision);
            return (math.round(value * pow) / pow).toFixed(precision);
        } : function(value, precision) {
            return value.toFixed(precision);
        },

        
        from: function(value, defaultValue) {
            if (isFinite(value)) {
                value = parseFloat(value);
            }

            return !isNaN(value) ? value : defaultValue;
        },

        
        randomInt: function (from, to) {
           return math.floor(math.random() * (to - from + 1) + from);
        },
        
        
        correctFloat: function(n) {
            
            
            
            return parseFloat(n.toPrecision(14));
        }
    });

    
    Ext.num = function() {
        return me.from.apply(this, arguments);
    };
};






(function() {

    var arrayPrototype = Array.prototype,
        slice = arrayPrototype.slice,
        supportsSplice = (function () {
            var array = [],
                lengthBefore,
                j = 20;

            if (!array.splice) {
                return false;
            }

            
            

            while (j--) {
                array.push("A");
            }

            array.splice(15, 0, "F", "F", "F", "F", "F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F","F");

            lengthBefore = array.length; 
            array.splice(13, 0, "XXX"); 

            if (lengthBefore+1 != array.length) {
                return false;
            }
            

            return true;
        }()),
        supportsForEach = 'forEach' in arrayPrototype,
        supportsMap = 'map' in arrayPrototype,
        supportsIndexOf = 'indexOf' in arrayPrototype,
        supportsEvery = 'every' in arrayPrototype,
        supportsSome = 'some' in arrayPrototype,
        supportsFilter = 'filter' in arrayPrototype,
        supportsSort = (function() {
            var a = [1,2,3,4,5].sort(function(){ return 0; });
            return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5;
        }()),
        supportsSliceOnNodeList = true,
        ExtArray,
        erase,
        replace,
        splice;

    try {
        
        if (typeof document !== 'undefined') {
            slice.call(document.getElementsByTagName('body'));
        }
    } catch (e) {
        supportsSliceOnNodeList = false;
    }

    function fixArrayIndex (array, index) {
        return (index < 0) ? Math.max(0, array.length + index)
                           : Math.min(array.length, index);
    }

    
    function replaceSim (array, index, removeCount, insert) {
        var add = insert ? insert.length : 0,
            length = array.length,
            pos = fixArrayIndex(array, index),
            remove,
            tailOldPos,
            tailNewPos,
            tailCount,
            lengthAfterRemove,
            i;

        
        if (pos === length) {
            if (add) {
                array.push.apply(array, insert);
            }
        } else {
            remove = Math.min(removeCount, length - pos);
            tailOldPos = pos + remove;
            tailNewPos = tailOldPos + add - remove;
            tailCount = length - tailOldPos;
            lengthAfterRemove = length - remove;

            if (tailNewPos < tailOldPos) { 
                for (i = 0; i < tailCount; ++i) {
                    array[tailNewPos+i] = array[tailOldPos+i];
                }
            } else if (tailNewPos > tailOldPos) { 
                for (i = tailCount; i--; ) {
                    array[tailNewPos+i] = array[tailOldPos+i];
                }
            } 

            if (add && pos === lengthAfterRemove) {
                array.length = lengthAfterRemove; 
                array.push.apply(array, insert);
            } else {
                array.length = lengthAfterRemove + add; 
                for (i = 0; i < add; ++i) {
                    array[pos+i] = insert[i];
                }
            }
        }

        return array;
    }

    function replaceNative (array, index, removeCount, insert) {
        if (insert && insert.length) {
            
            if (index === 0 && !removeCount) {
                array.unshift.apply(array, insert);
            }
            
            else if (index < array.length) {
                array.splice.apply(array, [index, removeCount].concat(insert));
            }
            
            else {
                array.push.apply(array, insert);
            }
        } else {
            array.splice(index, removeCount);
        }
        return array;
    }

    function eraseSim (array, index, removeCount) {
        return replaceSim(array, index, removeCount);
    }

    function eraseNative (array, index, removeCount) {
        array.splice(index, removeCount);
        return array;
    }

    function spliceSim (array, index, removeCount) {
        var pos = fixArrayIndex(array, index),
            removed = array.slice(index, fixArrayIndex(array, pos+removeCount));

        if (arguments.length < 4) {
            replaceSim(array, pos, removeCount);
        } else {
            replaceSim(array, pos, removeCount, slice.call(arguments, 3));
        }

        return removed;
    }

    function spliceNative (array) {
        return array.splice.apply(array, slice.call(arguments, 1));
    }

    erase = supportsSplice ? eraseNative : eraseSim;
    replace = supportsSplice ? replaceNative : replaceSim;
    splice = supportsSplice ? spliceNative : spliceSim;

    

    ExtArray = Ext.Array = {
        
        each: function(array, fn, scope, reverse) {
            array = ExtArray.from(array);

            var i,
                ln = array.length;

            if (reverse !== true) {
                for (i = 0; i < ln; i++) {
                    if (fn.call(scope || array[i], array[i], i, array) === false) {
                        return i;
                    }
                }
            }
            else {
                for (i = ln - 1; i > -1; i--) {
                    if (fn.call(scope || array[i], array[i], i, array) === false) {
                        return i;
                    }
                }
            }

            return true;
        },

        
        forEach: supportsForEach ? function(array, fn, scope) {
            array.forEach(fn, scope);
        } : function(array, fn, scope) {
            var i = 0,
                ln = array.length;

            for (; i < ln; i++) {
                fn.call(scope, array[i], i, array);
            }
        },

        
        indexOf: supportsIndexOf ? function(array, item, from) {
            return arrayPrototype.indexOf.call(array, item, from);
         } : function(array, item, from) {
            var i, length = array.length;

            for (i = (from < 0) ? Math.max(0, length + from) : from || 0; i < length; i++) {
                if (array[i] === item) {
                    return i;
                }
            }

            return -1;
        },

        
        contains: supportsIndexOf ? function(array, item) {
            return arrayPrototype.indexOf.call(array, item) !== -1;
        } : function(array, item) {
            var i, ln;

            for (i = 0, ln = array.length; i < ln; i++) {
                if (array[i] === item) {
                    return true;
                }
            }

            return false;
        },

        
        toArray: function(iterable, start, end){
            if (!iterable || !iterable.length) {
                return [];
            }

            if (typeof iterable === 'string') {
                iterable = iterable.split('');
            }

            if (supportsSliceOnNodeList) {
                return slice.call(iterable, start || 0, end || iterable.length);
            }

            var array = [],
                i;

            start = start || 0;
            end = end ? ((end < 0) ? iterable.length + end : end) : iterable.length;

            for (i = start; i < end; i++) {
                array.push(iterable[i]);
            }

            return array;
        },

        
        pluck: function(array, propertyName) {
            var ret = [],
                i, ln, item;

            for (i = 0, ln = array.length; i < ln; i++) {
                item = array[i];

                ret.push(item[propertyName]);
            }

            return ret;
        },

        
        map: supportsMap ? function(array, fn, scope) {
            return array.map(fn, scope);
        } : function(array, fn, scope) {
            var results = [],
                i = 0,
                len = array.length;

            for (; i < len; i++) {
                results[i] = fn.call(scope, array[i], i, array);
            }

            return results;
        },

        
        every: supportsEvery ? function(array, fn, scope) {
            return array.every(fn, scope);
        } : function(array, fn, scope) {
            var i = 0,
                ln = array.length;

            for (; i < ln; ++i) {
                if (!fn.call(scope, array[i], i, array)) {
                    return false;
                }
            }

            return true;
        },

        
        some: supportsSome ? function(array, fn, scope) {
            return array.some(fn, scope);
        } : function(array, fn, scope) {
            var i = 0,
                ln = array.length;

            for (; i < ln; ++i) {
                if (fn.call(scope, array[i], i, array)) {
                    return true;
                }
            }

            return false;
        },
        
        
        equals: function(array1, array2) {
            var len1 = array1.length,
                len2 = array2.length,
                i;
                
            
            if (array1 === array2) {
                return true;
            }
                
            if (len1 !== len2) {
                return false;
            }
            
            for (i = 0; i < len1; ++i) {
                if (array1[i] !== array2[i]) {
                    return false;
                }
            }
            
            return true;
        },

        
        clean: function(array) {
            var results = [],
                i = 0,
                ln = array.length,
                item;

            for (; i < ln; i++) {
                item = array[i];

                if (!Ext.isEmpty(item)) {
                    results.push(item);
                }
            }

            return results;
        },

        
        unique: function(array) {
            var clone = [],
                i = 0,
                ln = array.length,
                item;

            for (; i < ln; i++) {
                item = array[i];

                if (ExtArray.indexOf(clone, item) === -1) {
                    clone.push(item);
                }
            }

            return clone;
        },

        
        filter: supportsFilter ? function(array, fn, scope) {
            return array.filter(fn, scope);
        } : function(array, fn, scope) {
            var results = [],
                i = 0,
                ln = array.length;

            for (; i < ln; i++) {
                if (fn.call(scope, array[i], i, array)) {
                    results.push(array[i]);
                }
            }

            return results;
        },

        
        findBy : function(array, fn, scope) {
            var i = 0,
                len = array.length;

            for (; i < len; i++) {
                if (fn.call(scope || array, array[i], i)) {
                    return array[i];
                }
            }
            return null;
        },

        
        from: function(value, newReference) {
            if (value === undefined || value === null) {
                return [];
            }

            if (Ext.isArray(value)) {
                return (newReference) ? slice.call(value) : value;
            }

            var type = typeof value;
            
            
            if (value && value.length !== undefined && type !== 'string' && (type !== 'function' || !value.apply)) {
                return ExtArray.toArray(value);
            }

            return [value];
        },

        
        remove: function(array, item) {
            var index = ExtArray.indexOf(array, item);

            if (index !== -1) {
                erase(array, index, 1);
            }

            return array;
        },

        
        include: function(array, item) {
            if (!ExtArray.contains(array, item)) {
                array.push(item);
            }
        },

        
        clone: function(array) {
            return slice.call(array);
        },

        
        merge: function() {
            var args = slice.call(arguments),
                array = [],
                i, ln;

            for (i = 0, ln = args.length; i < ln; i++) {
                array = array.concat(args[i]);
            }

            return ExtArray.unique(array);
        },

        
        intersect: function() {
            var intersection = [],
                arrays = slice.call(arguments),
                arraysLength,
                array,
                arrayLength,
                minArray,
                minArrayIndex,
                minArrayCandidate,
                minArrayLength,
                element,
                elementCandidate,
                elementCount,
                i, j, k;

            if (!arrays.length) {
                return intersection;
            }

            
            arraysLength = arrays.length;
            for (i = minArrayIndex = 0; i < arraysLength; i++) {
                minArrayCandidate = arrays[i];
                if (!minArray || minArrayCandidate.length < minArray.length) {
                    minArray = minArrayCandidate;
                    minArrayIndex = i;
                }
            }

            minArray = ExtArray.unique(minArray);
            erase(arrays, minArrayIndex, 1);

            
            
            
            minArrayLength = minArray.length;
            arraysLength = arrays.length;
            for (i = 0; i < minArrayLength; i++) {
                element = minArray[i];
                elementCount = 0;

                for (j = 0; j < arraysLength; j++) {
                    array = arrays[j];
                    arrayLength = array.length;
                    for (k = 0; k < arrayLength; k++) {
                        elementCandidate = array[k];
                        if (element === elementCandidate) {
                            elementCount++;
                            break;
                        }
                    }
                }

                if (elementCount === arraysLength) {
                    intersection.push(element);
                }
            }

            return intersection;
        },

        
        difference: function(arrayA, arrayB) {
            var clone = slice.call(arrayA),
                ln = clone.length,
                i, j, lnB;

            for (i = 0,lnB = arrayB.length; i < lnB; i++) {
                for (j = 0; j < ln; j++) {
                    if (clone[j] === arrayB[i]) {
                        erase(clone, j, 1);
                        j--;
                        ln--;
                    }
                }
            }

            return clone;
        },

        
        
        slice: ([1,2].slice(1, undefined).length ?
            function (array, begin, end) {
                return slice.call(array, begin, end);
            } :
            
            function (array, begin, end) {
                
                
                if (typeof begin === 'undefined') {
                    return slice.call(array);
                }
                if (typeof end === 'undefined') {
                    return slice.call(array, begin);
                }
                return slice.call(array, begin, end);
            }
        ),

        
        sort: supportsSort ? function(array, sortFn) {
            if (sortFn) {
                return array.sort(sortFn);
            } else {
                return array.sort();
            }
         } : function(array, sortFn) {
            var length = array.length,
                i = 0,
                comparison,
                j, min, tmp;

            for (; i < length; i++) {
                min = i;
                for (j = i + 1; j < length; j++) {
                    if (sortFn) {
                        comparison = sortFn(array[j], array[min]);
                        if (comparison < 0) {
                            min = j;
                        }
                    } else if (array[j] < array[min]) {
                        min = j;
                    }
                }
                if (min !== i) {
                    tmp = array[i];
                    array[i] = array[min];
                    array[min] = tmp;
                }
            }

            return array;
        },

        
        flatten: function(array) {
            var worker = [];

            function rFlatten(a) {
                var i, ln, v;

                for (i = 0, ln = a.length; i < ln; i++) {
                    v = a[i];

                    if (Ext.isArray(v)) {
                        rFlatten(v);
                    } else {
                        worker.push(v);
                    }
                }

                return worker;
            }

            return rFlatten(array);
        },

        
        min: function(array, comparisonFn) {
            var min = array[0],
                i, ln, item;

            for (i = 0, ln = array.length; i < ln; i++) {
                item = array[i];

                if (comparisonFn) {
                    if (comparisonFn(min, item) === 1) {
                        min = item;
                    }
                }
                else {
                    if (item < min) {
                        min = item;
                    }
                }
            }

            return min;
        },

        
        max: function(array, comparisonFn) {
            var max = array[0],
                i, ln, item;

            for (i = 0, ln = array.length; i < ln; i++) {
                item = array[i];

                if (comparisonFn) {
                    if (comparisonFn(max, item) === -1) {
                        max = item;
                    }
                }
                else {
                    if (item > max) {
                        max = item;
                    }
                }
            }

            return max;
        },

        
        mean: function(array) {
            return array.length > 0 ? ExtArray.sum(array) / array.length : undefined;
        },

        
        sum: function(array) {
            var sum = 0,
                i, ln, item;

            for (i = 0,ln = array.length; i < ln; i++) {
                item = array[i];

                sum += item;
            }

            return sum;
        },

        
        toMap: function(array, getKey, scope) {
            var map = {},
                i = array.length;

            if (!getKey) {
                while (i--) {
                    map[array[i]] = i+1;
                }
            } else if (typeof getKey == 'string') {
                while (i--) {
                    map[array[i][getKey]] = i+1;
                }
            } else {
                while (i--) {
                    map[getKey.call(scope, array[i])] = i+1;
                }
            }

            return map;
        },

        
        toValueMap: function(array, getKey, scope) {
            var map = {},
                i = array.length;

            if (!getKey) {
                while (i--) {
                    map[array[i]] = array[i];
                }
            } else if (typeof getKey == 'string') {
                while (i--) {
                    map[array[i][getKey]] = array[i];
                }
            } else {
                while (i--) {
                    map[getKey.call(scope, array[i])] = array[i];
                }
            }

            return map;
        },


        
        erase: erase,

        
        insert: function (array, index, items) {
            return replace(array, index, 0, items);
        },

        
        replace: replace,

        
        splice: splice,

        
        push: function(array) {
            var len = arguments.length,
                i = 1,
                newItem;

            if (array === undefined) {
                array = [];
            } else if (!Ext.isArray(array)) {
                array = [array];
            }
            for (; i < len; i++) {
                newItem = arguments[i];
                Array.prototype.push[Ext.isIterable(newItem) ? 'apply' : 'call'](array, newItem);
            }
            return array;
        }
    };

    
    Ext.each = ExtArray.each;

    
    ExtArray.union = ExtArray.merge;

    
    Ext.min = ExtArray.min;

    
    Ext.max = ExtArray.max;

    
    Ext.sum = ExtArray.sum;

    
    Ext.mean = ExtArray.mean;

    
    Ext.flatten = ExtArray.flatten;

    
    Ext.clean = ExtArray.clean;

    
    Ext.unique = ExtArray.unique;

    
    Ext.pluck = ExtArray.pluck;

    
    Ext.toArray = function() {
        return ExtArray.toArray.apply(ExtArray, arguments);
    };
}());






Ext.Function = {

    
    flexSetter: function(fn) {
        return function(a, b) {
            var k, i;

            if (a === null) {
                return this;
            }

            if (typeof a !== 'string') {
                for (k in a) {
                    if (a.hasOwnProperty(k)) {
                        fn.call(this, k, a[k]);
                    }
                }

                if (Ext.enumerables) {
                    for (i = Ext.enumerables.length; i--;) {
                        k = Ext.enumerables[i];
                        if (a.hasOwnProperty(k)) {
                            fn.call(this, k, a[k]);
                        }
                    }
                }
            } else {
                fn.call(this, a, b);
            }

            return this;
        };
    },

    
    bind: function(fn, scope, args, appendArgs) {
        if (arguments.length === 2) {
            return function() {
                return fn.apply(scope, arguments);
            };
        }

        var method = fn,
            slice = Array.prototype.slice;

        return function() {
            var callArgs = args || arguments;

            if (appendArgs === true) {
                callArgs = slice.call(arguments, 0);
                callArgs = callArgs.concat(args);
            }
            else if (typeof appendArgs == 'number') {
                callArgs = slice.call(arguments, 0); 
                Ext.Array.insert(callArgs, appendArgs, args);
            }

            return method.apply(scope || Ext.global, callArgs);
        };
    },

    
    pass: function(fn, args, scope) {
        if (!Ext.isArray(args)) {
            if (Ext.isIterable(args)) {
                args = Ext.Array.clone(args);
            } else {
                args = args !== undefined ? [args] : [];
            }
        }

        return function() {
            var fnArgs = [].concat(args);
            fnArgs.push.apply(fnArgs, arguments);
            return fn.apply(scope || this, fnArgs);
        };
    },

    
    alias: function(object, methodName) {
        return function() {
            return object[methodName].apply(object, arguments);
        };
    },

    
    clone: function(method) {
        return function() {
            return method.apply(this, arguments);
        };
    },

    
    createInterceptor: function(origFn, newFn, scope, returnValue) {
        var method = origFn;
        if (!Ext.isFunction(newFn)) {
            return origFn;
        } else {
            returnValue = Ext.isDefined(returnValue) ? returnValue : null;
            return function() {
                var me = this,
                    args = arguments;
                    
                newFn.target = me;
                newFn.method = origFn;
                return (newFn.apply(scope || me || Ext.global, args) !== false) ? origFn.apply(me || Ext.global, args) : returnValue;
            };
        }
    },

    
    createDelayed: function(fn, delay, scope, args, appendArgs) {
        if (scope || args) {
            fn = Ext.Function.bind(fn, scope, args, appendArgs);
        }

        return function() {
            var me = this,
                args = Array.prototype.slice.call(arguments);

            setTimeout(function() {
                fn.apply(me, args);
            }, delay);
        };
    },

    
    defer: function(fn, millis, scope, args, appendArgs) {
        fn = Ext.Function.bind(fn, scope, args, appendArgs);
        if (millis > 0) {
            return setTimeout(Ext.supports.TimeoutActualLateness ? function () {
                fn();
            } : fn, millis);
        }
        fn();
        return 0;
    },

    
    createSequence: function(originalFn, newFn, scope) {
        if (!newFn) {
            return originalFn;
        }
        else {
            return function() {
                var result = originalFn.apply(this, arguments);
                newFn.apply(scope || this, arguments);
                return result;
            };
        }
    },

    
    createBuffered: function(fn, buffer, scope, args) {
        var timerId;

        return function() {
            var callArgs = args || Array.prototype.slice.call(arguments, 0),
                me = scope || this;

            if (timerId) {
                clearTimeout(timerId);
            }

            timerId = setTimeout(function(){
                fn.apply(me, callArgs);
            }, buffer);
        };
    },

    
    createThrottled: function(fn, interval, scope) {
        var lastCallTime, elapsed, lastArgs, timer, execute = function() {
            fn.apply(scope || this, lastArgs);
            lastCallTime = Ext.Date.now();
        };

        return function() {
            elapsed = Ext.Date.now() - lastCallTime;
            lastArgs = arguments;

            clearTimeout(timer);
            if (!lastCallTime || (elapsed >= interval)) {
                execute();
            } else {
                timer = setTimeout(execute, interval - elapsed);
            }
        };
    },


    
    interceptBefore: function(object, methodName, fn, scope) {
        var method = object[methodName] || Ext.emptyFn;

        return (object[methodName] = function() {
            var ret = fn.apply(scope || this, arguments);
            method.apply(this, arguments);

            return ret;
        });
    },

    
    interceptAfter: function(object, methodName, fn, scope) {
        var method = object[methodName] || Ext.emptyFn;

        return (object[methodName] = function() {
            method.apply(this, arguments);
            return fn.apply(scope || this, arguments);
        });
    }
};


Ext.defer = Ext.Function.alias(Ext.Function, 'defer');


Ext.pass = Ext.Function.alias(Ext.Function, 'pass');


Ext.bind = Ext.Function.alias(Ext.Function, 'bind');







(function() {


var TemplateClass = function(){},
    ExtObject = Ext.Object = {

    
    chain: Object.create || function (object) {
        TemplateClass.prototype = object;
        var result = new TemplateClass();
        TemplateClass.prototype = null;
        return result;
    },

    
    clear: function (object) {
        var keys = ExtObject.getKeys(object),
            n = keys.length;

        while (n--) {
            delete object[keys[n]];
        }

        return object;
    },

    
    toQueryObjects: function(name, value, recursive) {
        var self = ExtObject.toQueryObjects,
            objects = [],
            i, ln;

        if (Ext.isArray(value)) {
            for (i = 0, ln = value.length; i < ln; i++) {
                if (recursive) {
                    objects = objects.concat(self(name + '[' + i + ']', value[i], true));
                }
                else {
                    objects.push({
                        name: name,
                        value: value[i]
                    });
                }
            }
        }
        else if (Ext.isObject(value)) {
            for (i in value) {
                if (value.hasOwnProperty(i)) {
                    if (recursive) {
                        objects = objects.concat(self(name + '[' + i + ']', value[i], true));
                    }
                    else {
                        objects.push({
                            name: name,
                            value: value[i]
                        });
                    }
                }
            }
        }
        else {
            objects.push({
                name: name,
                value: value
            });
        }

        return objects;
    },

    
    toQueryString: function(object, recursive) {
        var paramObjects = [],
            params = [],
            i, j, ln, paramObject, value;

        for (i in object) {
            if (object.hasOwnProperty(i)) {
                paramObjects = paramObjects.concat(ExtObject.toQueryObjects(i, object[i], recursive));
            }
        }

        for (j = 0, ln = paramObjects.length; j < ln; j++) {
            paramObject = paramObjects[j];
            value = paramObject.value;

            if (Ext.isEmpty(value)) {
                value = '';
            } else if (Ext.isDate(value)) {
                value = Ext.Date.toString(value);
            }

            params.push(encodeURIComponent(paramObject.name) + '=' + encodeURIComponent(String(value)));
        }

        return params.join('&');
    },

    
    fromQueryString: function(queryString, recursive) {
        var parts = queryString.replace(/^\?/, '').split('&'),
            object = {},
            temp, components, name, value, i, ln,
            part, j, subLn, matchedKeys, matchedName,
            keys, key, nextKey;

        for (i = 0, ln = parts.length; i < ln; i++) {
            part = parts[i];

            if (part.length > 0) {
                components = part.split('=');
                name = decodeURIComponent(components[0]);
                value = (components[1] !== undefined) ? decodeURIComponent(components[1]) : '';

                if (!recursive) {
                    if (object.hasOwnProperty(name)) {
                        if (!Ext.isArray(object[name])) {
                            object[name] = [object[name]];
                        }

                        object[name].push(value);
                    }
                    else {
                        object[name] = value;
                    }
                }
                else {
                    matchedKeys = name.match(/(\[):?([^\]]*)\]/g);
                    matchedName = name.match(/^([^\[]+)/);


                    name = matchedName[0];
                    keys = [];

                    if (matchedKeys === null) {
                        object[name] = value;
                        continue;
                    }

                    for (j = 0, subLn = matchedKeys.length; j < subLn; j++) {
                        key = matchedKeys[j];
                        key = (key.length === 2) ? '' : key.substring(1, key.length - 1);
                        keys.push(key);
                    }

                    keys.unshift(name);

                    temp = object;

                    for (j = 0, subLn = keys.length; j < subLn; j++) {
                        key = keys[j];

                        if (j === subLn - 1) {
                            if (Ext.isArray(temp) && key === '') {
                                temp.push(value);
                            }
                            else {
                                temp[key] = value;
                            }
                        }
                        else {
                            if (temp[key] === undefined || typeof temp[key] === 'string') {
                                nextKey = keys[j+1];

                                temp[key] = (Ext.isNumeric(nextKey) || nextKey === '') ? [] : {};
                            }

                            temp = temp[key];
                        }
                    }
                }
            }
        }

        return object;
    },

    
    each: function(object, fn, scope) {
        for (var property in object) {
            if (object.hasOwnProperty(property)) {
                if (fn.call(scope || object, property, object[property], object) === false) {
                    return;
                }
            }
        }
    },

    
    merge: function(destination) {
        var i = 1,
            ln = arguments.length,
            mergeFn = ExtObject.merge,
            cloneFn = Ext.clone,
            object, key, value, sourceKey;

        for (; i < ln; i++) {
            object = arguments[i];

            for (key in object) {
                value = object[key];
                if (value && value.constructor === Object) {
                    sourceKey = destination[key];
                    if (sourceKey && sourceKey.constructor === Object) {
                        mergeFn(sourceKey, value);
                    }
                    else {
                        destination[key] = cloneFn(value);
                    }
                }
                else {
                    destination[key] = value;
                }
            }
        }

        return destination;
    },

    
    mergeIf: function(destination) {
        var i = 1,
            ln = arguments.length,
            cloneFn = Ext.clone,
            object, key, value;

        for (; i < ln; i++) {
            object = arguments[i];

            for (key in object) {
                if (!(key in destination)) {
                    value = object[key];

                    if (value && value.constructor === Object) {
                        destination[key] = cloneFn(value);
                    }
                    else {
                        destination[key] = value;
                    }
                }
            }
        }

        return destination;
    },

    
    getKey: function(object, value) {
        for (var property in object) {
            if (object.hasOwnProperty(property) && object[property] === value) {
                return property;
            }
        }

        return null;
    },

    
    getValues: function(object) {
        var values = [],
            property;

        for (property in object) {
            if (object.hasOwnProperty(property)) {
                values.push(object[property]);
            }
        }

        return values;
    },

    
    getKeys: (typeof Object.keys == 'function')
        ? function(object){
            if (!object) {
                return [];
            }
            return Object.keys(object);
        }
        : function(object) {
            var keys = [],
                property;

            for (property in object) {
                if (object.hasOwnProperty(property)) {
                    keys.push(property);
                }
            }

            return keys;
        },

    
    getSize: function(object) {
        var size = 0,
            property;

        for (property in object) {
            if (object.hasOwnProperty(property)) {
                size++;
            }
        }

        return size;
    },
    
    
    isEmpty: function(object){
        for (var key in object) {
            if (object.hasOwnProperty(key)) {
                return false;
            }
        }
        return true;    
    },
    
    
    equals: (function() {
        var check = function(o1, o2) {
            var key;
        
            for (key in o1) {
                if (o1.hasOwnProperty(key)) {
                    if (o1[key] !== o2[key]) {
                        return false;
                    }    
                }
            }    
            return true;
        };
        
        return function(object1, object2) {
            
            
            if (object1 === object2) {
                return true;
            } if (object1 && object2) {
                
                
                return check(object1, object2) && check(object2, object1);  
            } else if (!object1 && !object2) {
                return object1 === object2;
            } else {
                return false;
            }
        };
    })(),

    
    classify: function(object) {
        var prototype = object,
            objectProperties = [],
            propertyClassesMap = {},
            objectClass = function() {
                var i = 0,
                    ln = objectProperties.length,
                    property;

                for (; i < ln; i++) {
                    property = objectProperties[i];
                    this[property] = new propertyClassesMap[property]();
                }
            },
            key, value;

        for (key in object) {
            if (object.hasOwnProperty(key)) {
                value = object[key];

                if (value && value.constructor === Object) {
                    objectProperties.push(key);
                    propertyClassesMap[key] = ExtObject.classify(value);
                }
            }
        }

        objectClass.prototype = prototype;

        return objectClass;
    }
};


Ext.merge = Ext.Object.merge;


Ext.mergeIf = Ext.Object.mergeIf;


Ext.urlEncode = function() {
    var args = Ext.Array.from(arguments),
        prefix = '';

    
    if ((typeof args[1] === 'string')) {
        prefix = args[1] + '&';
        args[1] = false;
    }

    return prefix + ExtObject.toQueryString.apply(ExtObject, args);
};


Ext.urlDecode = function() {
    return ExtObject.fromQueryString.apply(ExtObject, arguments);
};

}());









Ext.Date = new function() {
  var utilDate = this,
      stripEscapeRe = /(\\.)/g,
      hourInfoRe = /([gGhHisucUOPZ]|MS)/,
      dateInfoRe = /([djzmnYycU]|MS)/,
      slashRe = /\\/gi,
      numberTokenRe = /\{(\d+)\}/g,
      MSFormatRe = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/'),
      code = [
        
        "var me = this, dt, y, m, d, h, i, s, ms, o, O, z, zz, u, v, W, year, jan4, week1monday, daysInMonth, dayMatched,",
            "def = me.defaults,",
            "from = Ext.Number.from,",
            "results = String(input).match(me.parseRegexes[{0}]);", 

        "if(results){",
            "{1}",

            "if(u != null){", 
                "v = new Date(u * 1000);", 
            "}else{",
                
                
                
                "dt = me.clearTime(new Date);",

                "y = from(y, from(def.y, dt.getFullYear()));",
                "m = from(m, from(def.m - 1, dt.getMonth()));",
                "dayMatched = d !== undefined;",
                "d = from(d, from(def.d, dt.getDate()));",
                
                
                
                
                
                
                
                
                "if (!dayMatched) {", 
                    "dt.setDate(1);",
                    "dt.setMonth(m);",
                    "dt.setFullYear(y);",
                
                    "daysInMonth = me.getDaysInMonth(dt);",
                    "if (d > daysInMonth) {",
                        "d = daysInMonth;",
                    "}",
                "}",

                "h  = from(h, from(def.h, dt.getHours()));",
                "i  = from(i, from(def.i, dt.getMinutes()));",
                "s  = from(s, from(def.s, dt.getSeconds()));",
                "ms = from(ms, from(def.ms, dt.getMilliseconds()));",

                "if(z >= 0 && y >= 0){",
                    
                    

                    
                    
                    "v = me.add(new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms), me.YEAR, y < 100 ? y - 100 : 0);",

                    
                    "v = !strict? v : (strict === true && (z <= 364 || (me.isLeapYear(v) && z <= 365))? me.add(v, me.DAY, z) : null);",
                "}else if(strict === true && !me.isValid(y, m + 1, d, h, i, s, ms)){", 
                    "v = null;", 
                "}else{",
                    "if (W) {", 
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        
                        "year = y || (new Date()).getFullYear(),",
                        "jan4 = new Date(year, 0, 4, 0, 0, 0),",
                        "week1monday = new Date(jan4.getTime() - ((jan4.getDay() - 1) * 86400000));",
                        "v = Ext.Date.clearTime(new Date(week1monday.getTime() + ((W - 1) * 604800000)));",
                    "} else {",
                        
                        
                        "v = me.add(new Date(y < 100 ? 100 : y, m, d, h, i, s, ms), me.YEAR, y < 100 ? y - 100 : 0);",
                    "}",
                "}",
            "}",
        "}",

        "if(v){",
            
            "if(zz != null){",
                
                "v = me.add(v, me.SECOND, -v.getTimezoneOffset() * 60 - zz);",
            "}else if(o){",
                
                "v = me.add(v, me.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
            "}",
        "}",

        "return v;"
      ].join('\n');

  
  
  
  function xf(format) {
      var args = Array.prototype.slice.call(arguments, 1);
      return format.replace(numberTokenRe, function(m, i) {
          return args[i];
      });
  }

  Ext.apply(utilDate, {
    
    now: Date.now || function() {
        return +new Date();
    },

    
    toString: function(date) {
        var pad = Ext.String.leftPad;

        return date.getFullYear() + "-"
            + pad(date.getMonth() + 1, 2, '0') + "-"
            + pad(date.getDate(), 2, '0') + "T"
            + pad(date.getHours(), 2, '0') + ":"
            + pad(date.getMinutes(), 2, '0') + ":"
            + pad(date.getSeconds(), 2, '0');
    },

    
    getElapsed: function(dateA, dateB) {
        return Math.abs(dateA - (dateB || utilDate.now()));
    },

    
    useStrict: false,

    
    formatCodeToRegex: function(character, currentGroup) {
        
        var p = utilDate.parseCodes[character];

        if (p) {
          p = typeof p == 'function'? p() : p;
          utilDate.parseCodes[character] = p; 
        }

        return p ? Ext.applyIf({
          c: p.c ? xf(p.c, currentGroup || "{0}") : p.c
        }, p) : {
            g: 0,
            c: null,
            s: Ext.String.escapeRegex(character) 
        };
    },

    
    parseFunctions: {
        "MS": function(input, strict) {
            
            
            var r = (input || '').match(MSFormatRe);
            return r ? new Date(((r[1] || '') + r[2]) * 1) : null;
        },
        "time": function(input, strict) {
            var num = parseInt(input, 10);
            if (num || num === 0) {
                return new Date(num);
            }
            return null;
        },
        "timestamp": function(input, strict) {
            var num = parseInt(input, 10);
            if (num || num === 0) {
                return new Date(num * 1000);
            }
            return null;
        }
    },
    parseRegexes: [],

    
    formatFunctions: {
        "MS": function() {
            
            return '\\/Date(' + this.getTime() + ')\\/';
        },
        "time": function(){
            return this.getTime().toString();
        },
        "timestamp": function(){
            return utilDate.format(this, 'U');
        }
    },

    y2kYear : 50,

    
    MILLI : "ms",

    
    SECOND : "s",

    
    MINUTE : "mi",

    
    HOUR : "h",

    
    DAY : "d",

    
    MONTH : "mo",

    
    YEAR : "y",

    
    defaults: {},

    
    
    dayNames : [
        "Sunday",
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday"
    ],
    

    
    
    monthNames : [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December"
    ],
    

    
    
    monthNumbers : {
        January: 0,
        Jan: 0,
        February: 1,
        Feb: 1,
        March: 2,
        Mar: 2,
        April: 3,
        Apr: 3,
        May: 4,
        June: 5,
        Jun: 5,
        July: 6,
        Jul: 6,
        August: 7,
        Aug: 7,
        September: 8,
        Sep: 8,
        October: 9,
        Oct: 9,
        November: 10,
        Nov: 10,
        December: 11,
        Dec: 11
    },
    
    
    
    
    defaultFormat : "m/d/Y",
    
    
    
    getShortMonthName : function(month) {
        return Ext.Date.monthNames[month].substring(0, 3);
    },
    

    
    
    getShortDayName : function(day) {
        return Ext.Date.dayNames[day].substring(0, 3);
    },
    

    
    
    getMonthNumber : function(name) {
        
        return Ext.Date.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
    },
    

    
    formatContainsHourInfo : function(format){
        return hourInfoRe.test(format.replace(stripEscapeRe, ''));
    },

    
    formatContainsDateInfo : function(format){
        return dateInfoRe.test(format.replace(stripEscapeRe, ''));
    },
    
    
    unescapeFormat: function(format) {
        
        
        
        return format.replace(slashRe, '');
    },

    
    formatCodes : {
        d: "Ext.String.leftPad(this.getDate(), 2, '0')",
        D: "Ext.Date.getShortDayName(this.getDay())", 
        j: "this.getDate()",
        l: "Ext.Date.dayNames[this.getDay()]",
        N: "(this.getDay() ? this.getDay() : 7)",
        S: "Ext.Date.getSuffix(this)",
        w: "this.getDay()",
        z: "Ext.Date.getDayOfYear(this)",
        W: "Ext.String.leftPad(Ext.Date.getWeekOfYear(this), 2, '0')",
        F: "Ext.Date.monthNames[this.getMonth()]",
        m: "Ext.String.leftPad(this.getMonth() + 1, 2, '0')",
        M: "Ext.Date.getShortMonthName(this.getMonth())", 
        n: "(this.getMonth() + 1)",
        t: "Ext.Date.getDaysInMonth(this)",
        L: "(Ext.Date.isLeapYear(this) ? 1 : 0)",
        o: "(this.getFullYear() + (Ext.Date.getWeekOfYear(this) == 1 && this.getMonth() > 0 ? +1 : (Ext.Date.getWeekOfYear(this) >= 52 && this.getMonth() < 11 ? -1 : 0)))",
        Y: "Ext.String.leftPad(this.getFullYear(), 4, '0')",
        y: "('' + this.getFullYear()).substring(2, 4)",
        a: "(this.getHours() < 12 ? 'am' : 'pm')",
        A: "(this.getHours() < 12 ? 'AM' : 'PM')",
        g: "((this.getHours() % 12) ? this.getHours() % 12 : 12)",
        G: "this.getHours()",
        h: "Ext.String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0')",
        H: "Ext.String.leftPad(this.getHours(), 2, '0')",
        i: "Ext.String.leftPad(this.getMinutes(), 2, '0')",
        s: "Ext.String.leftPad(this.getSeconds(), 2, '0')",
        u: "Ext.String.leftPad(this.getMilliseconds(), 3, '0')",
        O: "Ext.Date.getGMTOffset(this)",
        P: "Ext.Date.getGMTOffset(this, true)",
        T: "Ext.Date.getTimezone(this)",
        Z: "(this.getTimezoneOffset() * -60)",

        c: function() { 
            var c, code, i, l, e;
            for (c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
                e = c.charAt(i);
                code.push(e == "T" ? "'T'" : utilDate.getFormatCode(e)); 
            }
            return code.join(" + ");
        },
        

        U: "Math.round(this.getTime() / 1000)"
    },

    
    isValid : function(y, m, d, h, i, s, ms) {
        
        h = h || 0;
        i = i || 0;
        s = s || 0;
        ms = ms || 0;

        
        var dt = utilDate.add(new Date(y < 100 ? 100 : y, m - 1, d, h, i, s, ms), utilDate.YEAR, y < 100 ? y - 100 : 0);

        return y == dt.getFullYear() &&
            m == dt.getMonth() + 1 &&
            d == dt.getDate() &&
            h == dt.getHours() &&
            i == dt.getMinutes() &&
            s == dt.getSeconds() &&
            ms == dt.getMilliseconds();
    },

    
    parse : function(input, format, strict) {
        var p = utilDate.parseFunctions;
        if (p[format] == null) {
            utilDate.createParser(format);
        }
        return p[format].call(utilDate, input, Ext.isDefined(strict) ? strict : utilDate.useStrict);
    },

    
    parseDate: function(input, format, strict){
        return utilDate.parse(input, format, strict);
    },


    
    getFormatCode : function(character) {
        var f = utilDate.formatCodes[character];

        if (f) {
          f = typeof f == 'function'? f() : f;
          utilDate.formatCodes[character] = f; 
        }

        
        return f || ("'" + Ext.String.escape(character) + "'");
    },

    
    createFormat : function(format) {
        var code = [],
            special = false,
            ch = '',
            i;

        for (i = 0; i < format.length; ++i) {
            ch = format.charAt(i);
            if (!special && ch == "\\") {
                special = true;
            } else if (special) {
                special = false;
                code.push("'" + Ext.String.escape(ch) + "'");
            } else {
                code.push(utilDate.getFormatCode(ch));
            }
        }
        utilDate.formatFunctions[format] = Ext.functionFactory("return " + code.join('+'));
    },

    
    createParser : function(format) {
        var regexNum = utilDate.parseRegexes.length,
            currentGroup = 1,
            calc = [],
            regex = [],
            special = false,
            ch = "",
            i = 0,
            len = format.length,
            atEnd = [],
            obj;

        for (; i < len; ++i) {
            ch = format.charAt(i);
            if (!special && ch == "\\") {
                special = true;
            } else if (special) {
                special = false;
                regex.push(Ext.String.escape(ch));
            } else {
                obj = utilDate.formatCodeToRegex(ch, currentGroup);
                currentGroup += obj.g;
                regex.push(obj.s);
                if (obj.g && obj.c) {
                    if (obj.calcAtEnd) {
                        atEnd.push(obj.c);
                    } else {
                        calc.push(obj.c);
                    }
                }
            }
        }

        calc = calc.concat(atEnd);

        utilDate.parseRegexes[regexNum] = new RegExp("^" + regex.join('') + "$", 'i');
        utilDate.parseFunctions[format] = Ext.functionFactory("input", "strict", xf(code, regexNum, calc.join('')));
    },

    
    parseCodes : {
        
        d: {
            g:1,
            c:"d = parseInt(results[{0}], 10);\n",
            s:"(3[0-1]|[1-2][0-9]|0[1-9])" 
        },
        j: {
            g:1,
            c:"d = parseInt(results[{0}], 10);\n",
            s:"(3[0-1]|[1-2][0-9]|[1-9])" 
        },
        D: function() {
            for (var a = [], i = 0; i < 7; a.push(utilDate.getShortDayName(i)), ++i); 
            return {
                g:0,
                c:null,
                s:"(?:" + a.join("|") +")"
            };
        },
        l: function() {
            return {
                g:0,
                c:null,
                s:"(?:" + utilDate.dayNames.join("|") + ")"
            };
        },
        N: {
            g:0,
            c:null,
            s:"[1-7]" 
        },
        
        S: {
            g:0,
            c:null,
            s:"(?:st|nd|rd|th)"
        },
        
        w: {
            g:0,
            c:null,
            s:"[0-6]" 
        },
        z: {
            g:1,
            c:"z = parseInt(results[{0}], 10);\n",
            s:"(\\d{1,3})" 
        },
        W: {
            g:1,
            c:"W = parseInt(results[{0}], 10);\n",
            s:"(\\d{2})" 
        },
        F: function() {
            return {
                g:1,
                c:"m = parseInt(me.getMonthNumber(results[{0}]), 10);\n", 
                s:"(" + utilDate.monthNames.join("|") + ")"
            };
        },
        M: function() {
            for (var a = [], i = 0; i < 12; a.push(utilDate.getShortMonthName(i)), ++i); 
            return Ext.applyIf({
                s:"(" + a.join("|") + ")"
            }, utilDate.formatCodeToRegex("F"));
        },
        m: {
            g:1,
            c:"m = parseInt(results[{0}], 10) - 1;\n",
            s:"(1[0-2]|0[1-9])" 
        },
        n: {
            g:1,
            c:"m = parseInt(results[{0}], 10) - 1;\n",
            s:"(1[0-2]|[1-9])" 
        },
        t: {
            g:0,
            c:null,
            s:"(?:\\d{2})" 
        },
        L: {
            g:0,
            c:null,
            s:"(?:1|0)"
        },
        o: { 
            g: 1,
            c: "y = parseInt(results[{0}], 10);\n",
            s: "(\\d{4})" 

        },
        Y: {
            g:1,
            c:"y = parseInt(results[{0}], 10);\n",
            s:"(\\d{4})" 
        },
        y: {
            g:1,
            c:"var ty = parseInt(results[{0}], 10);\n"
                + "y = ty > me.y2kYear ? 1900 + ty : 2000 + ty;\n", 
            s:"(\\d{1,2})"
        },
        
        
        a: {
            g:1,
            c:"if (/(am)/i.test(results[{0}])) {\n"
                + "if (!h || h == 12) { h = 0; }\n"
                + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
            s:"(am|pm|AM|PM)",
            calcAtEnd: true
        },
        
        
        A: {
            g:1,
            c:"if (/(am)/i.test(results[{0}])) {\n"
                + "if (!h || h == 12) { h = 0; }\n"
                + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
            s:"(AM|PM|am|pm)",
            calcAtEnd: true
        },
        
        g: {
            g:1,
            c:"h = parseInt(results[{0}], 10);\n",
            s:"(1[0-2]|[0-9])" 
        },
        G: {
            g:1,
            c:"h = parseInt(results[{0}], 10);\n",
            s:"(2[0-3]|1[0-9]|[0-9])" 
        },
        h: {
            g:1,
            c:"h = parseInt(results[{0}], 10);\n",
            s:"(1[0-2]|0[1-9])" 
        },
        H: {
            g:1,
            c:"h = parseInt(results[{0}], 10);\n",
            s:"(2[0-3]|[0-1][0-9])" 
        },
        i: {
            g:1,
            c:"i = parseInt(results[{0}], 10);\n",
            s:"([0-5][0-9])" 
        },
        s: {
            g:1,
            c:"s = parseInt(results[{0}], 10);\n",
            s:"([0-5][0-9])" 
        },
        u: {
            g:1,
            c:"ms = results[{0}]; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n",
            s:"(\\d+)" 
        },
        O: {
            g:1,
            c:[
                "o = results[{0}];",
                "var sn = o.substring(0,1),", 
                    "hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60),", 
                    "mn = o.substring(3,5) % 60;", 
                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n" 
            ].join("\n"),
            s: "([+-]\\d{4})" 
        },
        P: {
            g:1,
            c:[
                "o = results[{0}];",
                "var sn = o.substring(0,1),", 
                    "hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60),", 
                    "mn = o.substring(4,6) % 60;", 
                "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))? (sn + Ext.String.leftPad(hr, 2, '0') + Ext.String.leftPad(mn, 2, '0')) : null;\n" 
            ].join("\n"),
            s: "([+-]\\d{2}:\\d{2})" 
        },
        T: {
            g:0,
            c:null,
            s:"[A-Z]{1,5}" 
        },
        Z: {
            g:1,
            c:"zz = results[{0}] * 1;\n" 
                  + "zz = (-43200 <= zz && zz <= 50400)? zz : null;\n",
            s:"([+-]?\\d{1,5})" 
        },
        c: function() {
            var calc = [],
                arr = [
                    utilDate.formatCodeToRegex("Y", 1), 
                    utilDate.formatCodeToRegex("m", 2), 
                    utilDate.formatCodeToRegex("d", 3), 
                    utilDate.formatCodeToRegex("H", 4), 
                    utilDate.formatCodeToRegex("i", 5), 
                    utilDate.formatCodeToRegex("s", 6), 
                    {c:"ms = results[7] || '0'; ms = parseInt(ms, 10)/Math.pow(10, ms.length - 3);\n"}, 
                    {c:[ 
                        "if(results[8]) {", 
                            "if(results[8] == 'Z'){",
                                "zz = 0;", 
                            "}else if (results[8].indexOf(':') > -1){",
                                utilDate.formatCodeToRegex("P", 8).c, 
                            "}else{",
                                utilDate.formatCodeToRegex("O", 8).c, 
                            "}",
                        "}"
                    ].join('\n')}
                ],
                i,
                l;

            for (i = 0, l = arr.length; i < l; ++i) {
                calc.push(arr[i].c);
            }

            return {
                g:1,
                c:calc.join(""),
                s:[
                    arr[0].s, 
                    "(?:", "-", arr[1].s, 
                        "(?:", "-", arr[2].s, 
                            "(?:",
                                "(?:T| )?", 
                                arr[3].s, ":", arr[4].s,  
                                "(?::", arr[5].s, ")?", 
                                "(?:(?:\\.|,)(\\d+))?", 
                                "(Z|(?:[-+]\\d{2}(?::)?\\d{2}))?", 
                            ")?",
                        ")?",
                    ")?"
                ].join("")
            };
        },
        U: {
            g:1,
            c:"u = parseInt(results[{0}], 10);\n",
            s:"(-?\\d+)" 
        }
    },

    
    
    dateFormat: function(date, format) {
        return utilDate.format(date, format);
    },

    
    isEqual: function(date1, date2) {
        
        if (date1 && date2) {
            return (date1.getTime() === date2.getTime());
        }
        
        return !(date1 || date2);
    },

    
    format: function(date, format) {
        var formatFunctions = utilDate.formatFunctions;

        if (!Ext.isDate(date)) {
            return '';
        }

        if (formatFunctions[format] == null) {
            utilDate.createFormat(format);
        }

        return formatFunctions[format].call(date) + '';
    },

    
    getTimezone : function(date) {
        
        
        
        
        
        
        
        
        
        
        
        
        return date.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,5})(?:[\-+][0-9]{4})?(?: -?\d+)?)$/, "$1$2").replace(/[^A-Z]/g, "");
    },

    
    getGMTOffset : function(date, colon) {
        var offset = date.getTimezoneOffset();
        return (offset > 0 ? "-" : "+")
            + Ext.String.leftPad(Math.floor(Math.abs(offset) / 60), 2, "0")
            + (colon ? ":" : "")
            + Ext.String.leftPad(Math.abs(offset % 60), 2, "0");
    },

    
    getDayOfYear: function(date) {
        var num = 0,
            d = Ext.Date.clone(date),
            m = date.getMonth(),
            i;

        for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
            num += utilDate.getDaysInMonth(d);
        }
        return num + date.getDate() - 1;
    },

    
    getWeekOfYear : (function() {
        
        var ms1d = 864e5, 
            ms7d = 7 * ms1d; 

        return function(date) { 
            var DC3 = Date.UTC(date.getFullYear(), date.getMonth(), date.getDate() + 3) / ms1d, 
                AWN = Math.floor(DC3 / 7), 
                Wyr = new Date(AWN * ms7d).getUTCFullYear();

            return AWN - Math.floor(Date.UTC(Wyr, 0, 7) / ms7d) + 1;
        };
    }()),

    
    isLeapYear : function(date) {
        var year = date.getFullYear();
        return !!((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
    },

    
    getFirstDayOfMonth : function(date) {
        var day = (date.getDay() - (date.getDate() - 1)) % 7;
        return (day < 0) ? (day + 7) : day;
    },

    
    getLastDayOfMonth : function(date) {
        return utilDate.getLastDateOfMonth(date).getDay();
    },


    
    getFirstDateOfMonth : function(date) {
        return new Date(date.getFullYear(), date.getMonth(), 1);
    },

    
    getLastDateOfMonth : function(date) {
        return new Date(date.getFullYear(), date.getMonth(), utilDate.getDaysInMonth(date));
    },

    
    getDaysInMonth: (function() {
        var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

        return function(date) { 
            var m = date.getMonth();

            return m == 1 && utilDate.isLeapYear(date) ? 29 : daysInMonth[m];
        };
    }()),

    
    
    getSuffix : function(date) {
        switch (date.getDate()) {
            case 1:
            case 21:
            case 31:
                return "st";
            case 2:
            case 22:
                return "nd";
            case 3:
            case 23:
                return "rd";
            default:
                return "th";
        }
    },
    

    
    clone : function(date) {
        return new Date(date.getTime());
    },

    
    isDST : function(date) {
        
        
        return new Date(date.getFullYear(), 0, 1).getTimezoneOffset() != date.getTimezoneOffset();
    },

    
    clearTime : function(date, clone) {
        if (clone) {
            return Ext.Date.clearTime(Ext.Date.clone(date));
        }

        
        var d = date.getDate(),
            hr,
            c;

        
        date.setHours(0);
        date.setMinutes(0);
        date.setSeconds(0);
        date.setMilliseconds(0);

        if (date.getDate() != d) { 
            
            

            
            for (hr = 1, c = utilDate.add(date, Ext.Date.HOUR, hr); c.getDate() != d; hr++, c = utilDate.add(date, Ext.Date.HOUR, hr));

            date.setDate(d);
            date.setHours(c.getHours());
        }

        return date;
    },

    
    add : function(date, interval, value) {
        var d = Ext.Date.clone(date),
            Date = Ext.Date,
            day, decimalValue, base = 0;
        if (!interval || value === 0) {
            return d;
        }

        decimalValue = value - parseInt(value, 10);
        value = parseInt(value, 10);

        if (value) {
            switch(interval.toLowerCase()) {
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                
                case Ext.Date.MILLI:
                    d.setTime(d.getTime() + value);
                    break;
                case Ext.Date.SECOND:
                    d.setTime(d.getTime() + value * 1000);
                    break;
                case Ext.Date.MINUTE:
                    d.setTime(d.getTime() + value * 60 * 1000);
                    break;
                case Ext.Date.HOUR:
                    d.setTime(d.getTime() + value * 60 * 60 * 1000);
                    break;
                case Ext.Date.DAY:
                    d.setDate(d.getDate() + value);
                    break;
                case Ext.Date.MONTH:
                    day = date.getDate();
                    if (day > 28) {
                        day = Math.min(day, Ext.Date.getLastDateOfMonth(Ext.Date.add(Ext.Date.getFirstDateOfMonth(date), Ext.Date.MONTH, value)).getDate());
                    }
                    d.setDate(day);
                    d.setMonth(date.getMonth() + value);
                    break;
                case Ext.Date.YEAR:
                    day = date.getDate();
                    if (day > 28) {
                        day = Math.min(day, Ext.Date.getLastDateOfMonth(Ext.Date.add(Ext.Date.getFirstDateOfMonth(date), Ext.Date.YEAR, value)).getDate());
                    }
                    d.setDate(day);
                    d.setFullYear(date.getFullYear() + value);
                    break;
            }
        }

        if (decimalValue) {
            switch (interval.toLowerCase()) {
                case Ext.Date.MILLI:    base = 1;               break;
                case Ext.Date.SECOND:   base = 1000;            break;
                case Ext.Date.MINUTE:   base = 1000*60;         break;
                case Ext.Date.HOUR:     base = 1000*60*60;      break;
                case Ext.Date.DAY:      base = 1000*60*60*24;   break;

                case Ext.Date.MONTH:
                    day = utilDate.getDaysInMonth(d);
                    base = 1000*60*60*24*day;
                    break;

                case Ext.Date.YEAR:
                    day = (utilDate.isLeapYear(d) ? 366 : 365);
                    base = 1000*60*60*24*day;
                    break;
            }
            if (base) {
                d.setTime(d.getTime() + base * decimalValue); 
            }
        }

        return d;
    },
    
    
    subtract: function(date, interval, value){
        return utilDate.add(date, interval, -value);
    },

    
    between : function(date, start, end) {
        var t = date.getTime();
        return start.getTime() <= t && t <= end.getTime();
    },

    
    compat: function() {
        var nativeDate = window.Date,
            p,
            statics = ['useStrict', 'formatCodeToRegex', 'parseFunctions', 'parseRegexes', 'formatFunctions', 'y2kYear', 'MILLI', 'SECOND', 'MINUTE', 'HOUR', 'DAY', 'MONTH', 'YEAR', 'defaults', 'dayNames', 'monthNames', 'monthNumbers', 'getShortMonthName', 'getShortDayName', 'getMonthNumber', 'formatCodes', 'isValid', 'parseDate', 'getFormatCode', 'createFormat', 'createParser', 'parseCodes'],
            proto = ['dateFormat', 'format', 'getTimezone', 'getGMTOffset', 'getDayOfYear', 'getWeekOfYear', 'isLeapYear', 'getFirstDayOfMonth', 'getLastDayOfMonth', 'getDaysInMonth', 'getSuffix', 'clone', 'isDST', 'clearTime', 'add', 'between'],
            sLen    = statics.length,
            pLen    = proto.length,
            stat, prot, s;

        
        for (s = 0; s < sLen; s++) {
            stat = statics[s];
            nativeDate[stat] = utilDate[stat];
        }

        
        for (p = 0; p < pLen; p++) {
            prot = proto[p];
            nativeDate.prototype[prot] = function() {
                var args = Array.prototype.slice.call(arguments);
                args.unshift(this);
                return utilDate[prot].apply(utilDate, args);
            };
        }
    }
  });
};






(function(flexSetter) {

var noArgs = [],
    Base = function(){},
    hookFunctionFactory = function(hookFunction, underriddenFunction, methodName, owningClass) {
        var result = function() {
            var result = this.callParent(arguments);
            hookFunction.apply(this, arguments);
            return result;
        };
        result.$name = methodName;
        result.$owner = owningClass;
        if (underriddenFunction) {
            result.$previous = underriddenFunction.$previous;
            underriddenFunction.$previous = result;
        }
        return result;
    };

    
    Ext.apply(Base, {
        $className: 'Ext.Base',

        $isClass: true,

        
        create: function() {
            return Ext.create.apply(Ext, [this].concat(Array.prototype.slice.call(arguments, 0)));
        },

        
        extend: function(parent) {
            var parentPrototype = parent.prototype,
                basePrototype, prototype, i, ln, name, statics;

            prototype = this.prototype = Ext.Object.chain(parentPrototype);
            prototype.self = this;

            this.superclass = prototype.superclass = parentPrototype;

            if (!parent.$isClass) {
                basePrototype = Ext.Base.prototype;

                for (i in basePrototype) {
                    if (i in prototype) {
                        prototype[i] = basePrototype[i];
                    }
                }
            }

            
            statics = parentPrototype.$inheritableStatics;

            if (statics) {
                for (i = 0,ln = statics.length; i < ln; i++) {
                    name = statics[i];

                    if (!this.hasOwnProperty(name)) {
                        this[name] = parent[name];
                    }
                }
            }

            if (parent.$onExtended) {
                this.$onExtended = parent.$onExtended.slice();
            }

            prototype.config = new prototype.configClass();
            prototype.initConfigList = prototype.initConfigList.slice();
            prototype.initConfigMap = Ext.clone(prototype.initConfigMap);
            prototype.configMap = Ext.Object.chain(prototype.configMap);
        },

        
        $onExtended: [],

        
        triggerExtended: function() {
        
            var callbacks = this.$onExtended,
                ln = callbacks.length,
                i, callback;

            if (ln > 0) {
                for (i = 0; i < ln; i++) {
                    callback = callbacks[i];
                    callback.fn.apply(callback.scope || this, arguments);
                }
            }
        },

        
        onExtended: function(fn, scope) {
            this.$onExtended.push({
                fn: fn,
                scope: scope
            });

            return this;
        },

        
        addConfig: function(config, fullMerge) {
            var prototype = this.prototype,
                configNameCache = Ext.Class.configNameCache,
                hasConfig = prototype.configMap,
                initConfigList = prototype.initConfigList,
                initConfigMap = prototype.initConfigMap,
                defaultConfig = prototype.config,
                initializedName, name, value;

            for (name in config) {
                if (config.hasOwnProperty(name)) {
                    if (!hasConfig[name]) {
                        hasConfig[name] = true;
                    }

                    value = config[name];

                    initializedName = configNameCache[name].initialized;

                    if (!initConfigMap[name] && value !== null && !prototype[initializedName]) {
                        initConfigMap[name] = true;
                        initConfigList.push(name);
                    }
                }
            }

            if (fullMerge) {
                Ext.merge(defaultConfig, config);
            }
            else {
                Ext.mergeIf(defaultConfig, config);
            }

            prototype.configClass = Ext.Object.classify(defaultConfig);
        },

        
        addStatics: function(members) {
            var member, name;

            for (name in members) {
                if (members.hasOwnProperty(name)) {
                    member = members[name];
                    if (typeof member == 'function' && !member.$isClass && member !== Ext.emptyFn && member !== Ext.identityFn) {
                        member.$owner = this;
                        member.$name = name;
                    }
                    this[name] = member;
                }
            }

            return this;
        },

        
        addInheritableStatics: function(members) {
            var inheritableStatics,
                hasInheritableStatics,
                prototype = this.prototype,
                name, member;

            inheritableStatics = prototype.$inheritableStatics;
            hasInheritableStatics = prototype.$hasInheritableStatics;

            if (!inheritableStatics) {
                inheritableStatics = prototype.$inheritableStatics = [];
                hasInheritableStatics = prototype.$hasInheritableStatics = {};
            }

            for (name in members) {
                if (members.hasOwnProperty(name)) {
                    member = members[name];
                    this[name] = member;

                    if (!hasInheritableStatics[name]) {
                        hasInheritableStatics[name] = true;
                        inheritableStatics.push(name);
                    }
                }
            }

            return this;
        },

        
        addMembers: function(members) {
            var prototype = this.prototype,
                enumerables = Ext.enumerables,
                names = [],
                i, ln, name, member;

            for (name in members) {
                names.push(name);
            }

            if (enumerables) {
                names.push.apply(names, enumerables);
            }

            for (i = 0,ln = names.length; i < ln; i++) {
                name = names[i];

                if (members.hasOwnProperty(name)) {
                    member = members[name];

                    if (typeof member == 'function' && !member.$isClass && member !== Ext.emptyFn && member !== Ext.identityFn) {
                        member.$owner = this;
                        member.$name = name;
                    }

                    prototype[name] = member;
                }
            }

            return this;
        },

        
        addMember: function(name, member) {            
            if (typeof member == 'function' && !member.$isClass && member !== Ext.emptyFn && member !== Ext.identityFn) {
                member.$owner = this;
                member.$name = name;
            }

            this.prototype[name] = member;
            return this;
        },

        
        implement: function() {
            this.addMembers.apply(this, arguments);
        },

        
        borrow: function(fromClass, members) {
            
            var prototype = this.prototype,
                fromPrototype = fromClass.prototype,
                i, ln, name, fn, toBorrow;

            members = Ext.Array.from(members);

            for (i = 0,ln = members.length; i < ln; i++) {
                name = members[i];

                toBorrow = fromPrototype[name];

                if (typeof toBorrow == 'function') {
                    fn = Ext.Function.clone(toBorrow);


                    fn.$owner = this;
                    fn.$name = name;

                    prototype[name] = fn;
                }
                else {
                    prototype[name] = toBorrow;
                }
            }

            return this;
        },

        
        override: function(members) {
            var me = this,
                enumerables = Ext.enumerables,
                target = me.prototype,
                cloneFunction = Ext.Function.clone,
                name, index, member, statics, names, previous;

            if (arguments.length === 2) {
                name = members;
                members = {};
                members[name] = arguments[1];
                enumerables = null;
            }

            do {
                names = []; 
                statics = null; 

                for (name in members) { 
                    if (name == 'statics') {
                        statics = members[name];
                    } else if (name == 'inheritableStatics'){
                        me.addInheritableStatics(members[name]);
                    } else if (name == 'config') {
                        me.addConfig(members[name], true);
                    } else {
                        names.push(name);
                    }
                }

                if (enumerables) {
                    names.push.apply(names, enumerables);
                }

                for (index = names.length; index--; ) {
                    name = names[index];

                    if (members.hasOwnProperty(name)) {
                        member = members[name];

                        if (typeof member == 'function' && !member.$className && member !== Ext.emptyFn && member !== Ext.identityFn) {
                            if (typeof member.$owner != 'undefined') {
                                member = cloneFunction(member);
                            }


                            member.$owner = me;
                            member.$name = name;

                            previous = target.hasOwnProperty(name) && target[name];
                            if (previous) {
                                member.$previous = previous;
                            }
                        }

                        target[name] = member;
                    }
                }

                target = me; 
                members = statics; 
            } while (members);

            return this;
        },

        
        callParent: function(args) {
            var method;

            
            return (method = this.callParent.caller) && (method.$previous ||
                  ((method = method.$owner ? method : method.caller) &&
                        method.$owner.superclass.self[method.$name])).apply(this, args || noArgs);
        },

        
        callSuper: function(args) {
            var method;

            
            return (method = this.callSuper.caller) &&
                    ((method = method.$owner ? method : method.caller) &&
                      method.$owner.superclass.self[method.$name]).apply(this, args || noArgs);
        },

        
        mixin: function(name, mixinClass) {
            var me = this,
                mixin = mixinClass.prototype,
                prototype = me.prototype,
                key, statics, i, ln, staticName,
                mixinValue, hookKey, hookFunction;

            if (typeof mixin.onClassMixedIn != 'undefined') {
                mixin.onClassMixedIn.call(mixinClass, me);
            }

            if (!prototype.hasOwnProperty('mixins')) {
                if ('mixins' in prototype) {
                    prototype.mixins = Ext.Object.chain(prototype.mixins);
                }
                else {
                    prototype.mixins = {};
                }
            }

            for (key in mixin) {
                mixinValue = mixin[key];
                if (key === 'mixins') {
                    Ext.merge(prototype.mixins, mixinValue);
                }
                else if (key === 'xhooks') {
                    for (hookKey in mixinValue) {
                        hookFunction = mixinValue[hookKey];

                        
                        hookFunction.$previous = Ext.emptyFn;

                        if (prototype.hasOwnProperty(hookKey)) {

                            
                            
                            
                            hookFunctionFactory(hookFunction, prototype[hookKey], hookKey, me);
                        } else {
                            
                            
                            prototype[hookKey] = hookFunctionFactory(hookFunction, null, hookKey, me);
                        }
                    }
                }
                else if (!(key === 'mixinId' || key === 'config') && (prototype[key] === undefined)) {
                    prototype[key] = mixinValue;
                }
            }

            
            statics = mixin.$inheritableStatics;

            if (statics) {
                for (i = 0, ln = statics.length; i < ln; i++) {
                    staticName = statics[i];

                    if (!me.hasOwnProperty(staticName)) {
                        me[staticName] = mixinClass[staticName];
                    }
                }
            }

            if ('config' in mixin) {
                me.addConfig(mixin.config, false);
            }

            prototype.mixins[name] = mixin;
            return me;
        },

        
        getName: function() {
            return Ext.getClassName(this);
        },

        
        createAlias: flexSetter(function(alias, origin) {
            this.override(alias, function() {
                return this[origin].apply(this, arguments);
            });
        }),

        
        addXtype: function(xtype) {
            var prototype = this.prototype,
                xtypesMap = prototype.xtypesMap,
                xtypes = prototype.xtypes,
                xtypesChain = prototype.xtypesChain;

            if (!prototype.hasOwnProperty('xtypesMap')) {
                xtypesMap = prototype.xtypesMap = Ext.merge({}, prototype.xtypesMap || {});
                xtypes = prototype.xtypes = prototype.xtypes ? [].concat(prototype.xtypes) : [];
                xtypesChain = prototype.xtypesChain = prototype.xtypesChain ? [].concat(prototype.xtypesChain) : [];
                prototype.xtype = xtype;
            }

            if (!xtypesMap[xtype]) {
                xtypesMap[xtype] = true;
                xtypes.push(xtype);
                xtypesChain.push(xtype);
                Ext.ClassManager.setAlias(this, 'widget.' + xtype);
            }

            return this;
        }
    });

    Base.implement({
        
        isInstance: true,

        
        $className: 'Ext.Base',

        
        configClass: Ext.emptyFn,

        
        initConfigList: [],

        
        configMap: {},

        
        initConfigMap: {},

        
        statics: function() {
            var method = this.statics.caller,
                self = this.self;

            if (!method) {
                return self;
            }

            return method.$owner;
        },

        
        callParent: function(args) {
            
            
            
            
            var method,
                superMethod = (method = this.callParent.caller) && (method.$previous ||
                        ((method = method.$owner ? method : method.caller) &&
                                method.$owner.superclass[method.$name]));


            return superMethod.apply(this, args || noArgs);
        },

        
        callSuper: function(args) {
            
            
            
            
            var method,
                superMethod = (method = this.callSuper.caller) &&
                        ((method = method.$owner ? method : method.caller) &&
                          method.$owner.superclass[method.$name]);


            return superMethod.apply(this, args || noArgs);
        },

        
        self: Base,

        
        constructor: function() {
            return this;
        },

        
        initConfig: function(config) {
            var instanceConfig = config,
                configNameCache = Ext.Class.configNameCache,
                defaultConfig = new this.configClass(),
                defaultConfigList = this.initConfigList,
                hasConfig = this.configMap,
                nameMap, i, ln, name, initializedName;

            this.initConfig = Ext.emptyFn;

            this.initialConfig = instanceConfig || {};

            this.config = config = (instanceConfig) ? Ext.merge(defaultConfig, config) : defaultConfig;

            if (instanceConfig) {
                defaultConfigList = defaultConfigList.slice();

                for (name in instanceConfig) {
                    if (hasConfig[name]) {
                        if (instanceConfig[name] !== null) {
                            defaultConfigList.push(name);
                            this[configNameCache[name].initialized] = false;
                        }
                    }
                }
            }

            for (i = 0,ln = defaultConfigList.length; i < ln; i++) {
                name = defaultConfigList[i];
                nameMap = configNameCache[name];
                initializedName = nameMap.initialized;

                if (!this[initializedName]) {
                    this[initializedName] = true;
                    this[nameMap.set].call(this, config[name]);
                }
            }

            return this;
        },

        
        hasConfig: function(name) {
            return Boolean(this.configMap[name]);
        },

        
        setConfig: function(config, applyIfNotSet) {
            if (!config) {
                return this;
            }

            var configNameCache = Ext.Class.configNameCache,
                currentConfig = this.config,
                hasConfig = this.configMap,
                initialConfig = this.initialConfig,
                name, value;

            applyIfNotSet = Boolean(applyIfNotSet);

            for (name in config) {
                if (applyIfNotSet && initialConfig.hasOwnProperty(name)) {
                    continue;
                }

                value = config[name];
                currentConfig[name] = value;

                if (hasConfig[name]) {
                    this[configNameCache[name].set](value);
                }
            }

            return this;
        },

        
        getConfig: function(name) {
            var configNameCache = Ext.Class.configNameCache;

            return this[configNameCache[name].get]();
        },

        
        getInitialConfig: function(name) {
            var config = this.config;

            if (!name) {
                return config;
            }
            else {
                return config[name];
            }
        },

        
        onConfigUpdate: function(names, callback, scope) {
            var self = this.self,
                i, ln, name,
                updaterName, updater, newUpdater;

            names = Ext.Array.from(names);

            scope = scope || this;

            for (i = 0,ln = names.length; i < ln; i++) {
                name = names[i];
                updaterName = 'update' + Ext.String.capitalize(name);
                updater = this[updaterName] || Ext.emptyFn;
                newUpdater = function() {
                    updater.apply(this, arguments);
                    scope[callback].apply(scope, arguments);
                };
                newUpdater.$name = updaterName;
                newUpdater.$owner = self;

                this[updaterName] = newUpdater;
            }
        },

        
        destroy: function() {
            this.destroy = Ext.emptyFn;
        }
    });

    
    Base.prototype.callOverridden = Base.prototype.callParent;

    Ext.Base = Base;

}(Ext.Function.flexSetter));






(function() {
    var ExtClass,
        Base = Ext.Base,
        baseStaticMembers = [],
        baseStaticMember, baseStaticMemberLength;

    for (baseStaticMember in Base) {
        if (Base.hasOwnProperty(baseStaticMember)) {
            baseStaticMembers.push(baseStaticMember);
        }
    }

    baseStaticMemberLength = baseStaticMembers.length;

    
    function makeCtor (className) {
        function constructor () {
            
            
            return this.constructor.apply(this, arguments) || null;
        }
        return constructor;
    }

    
    Ext.Class = ExtClass = function(Class, data, onCreated) {
        if (typeof Class != 'function') {
            onCreated = data;
            data = Class;
            Class = null;
        }

        if (!data) {
            data = {};
        }

        Class = ExtClass.create(Class, data);

        ExtClass.process(Class, data, onCreated);

        return Class;
    };

    Ext.apply(ExtClass, {
        
        onBeforeCreated: function(Class, data, hooks) {
        
            Class.addMembers(data);

            hooks.onCreated.call(Class, Class);
            
        },

        
        create: function(Class, data) {
            var name, i;

            if (!Class) {
                Class = makeCtor(
                );
            }

            for (i = 0; i < baseStaticMemberLength; i++) {
                name = baseStaticMembers[i];
                Class[name] = Base[name];
            }

            return Class;
        },

        
        process: function(Class, data, onCreated) {
            var preprocessorStack = data.preprocessors || ExtClass.defaultPreprocessors,
                registeredPreprocessors = this.preprocessors,
                hooks = {
                    onBeforeCreated: this.onBeforeCreated
                },
                preprocessors = [],
                preprocessor, preprocessorsProperties,
                i, ln, j, subLn, preprocessorProperty;

            delete data.preprocessors;

            for (i = 0,ln = preprocessorStack.length; i < ln; i++) {
                preprocessor = preprocessorStack[i];

                if (typeof preprocessor == 'string') {
                    preprocessor = registeredPreprocessors[preprocessor];
                    preprocessorsProperties = preprocessor.properties;

                    if (preprocessorsProperties === true) {
                        preprocessors.push(preprocessor.fn);
                    }
                    else if (preprocessorsProperties) {
                        for (j = 0,subLn = preprocessorsProperties.length; j < subLn; j++) {
                            preprocessorProperty = preprocessorsProperties[j];

                            if (data.hasOwnProperty(preprocessorProperty)) {
                                preprocessors.push(preprocessor.fn);
                                break;
                            }
                        }
                    }
                }
                else {
                    preprocessors.push(preprocessor);
                }
            }

            hooks.onCreated = onCreated ? onCreated : Ext.emptyFn;
            hooks.preprocessors = preprocessors;

            this.doProcess(Class, data, hooks);
        },
        
        doProcess: function(Class, data, hooks) {
            var me = this,
                preprocessors = hooks.preprocessors,
                preprocessor = preprocessors.shift(),
                doProcess = me.doProcess;

            for ( ; preprocessor ; preprocessor = preprocessors.shift()) {
                
                if (preprocessor.call(me, Class, data, hooks, doProcess) === false) {
                    return;
                }
            }
            hooks.onBeforeCreated.apply(me, arguments);
        },

        
        preprocessors: {},

        
        registerPreprocessor: function(name, fn, properties, position, relativeTo) {
            if (!position) {
                position = 'last';
            }

            if (!properties) {
                properties = [name];
            }

            this.preprocessors[name] = {
                name: name,
                properties: properties || false,
                fn: fn
            };

            this.setDefaultPreprocessorPosition(name, position, relativeTo);

            return this;
        },

        
        getPreprocessor: function(name) {
            return this.preprocessors[name];
        },

        
        getPreprocessors: function() {
            return this.preprocessors;
        },

        
        defaultPreprocessors: [],

        
        getDefaultPreprocessors: function() {
            return this.defaultPreprocessors;
        },

        
        setDefaultPreprocessors: function(preprocessors) {
            this.defaultPreprocessors = Ext.Array.from(preprocessors);

            return this;
        },

        
        setDefaultPreprocessorPosition: function(name, offset, relativeName) {
            var defaultPreprocessors = this.defaultPreprocessors,
                index;

            if (typeof offset == 'string') {
                if (offset === 'first') {
                    defaultPreprocessors.unshift(name);

                    return this;
                }
                else if (offset === 'last') {
                    defaultPreprocessors.push(name);

                    return this;
                }

                offset = (offset === 'after') ? 1 : -1;
            }

            index = Ext.Array.indexOf(defaultPreprocessors, relativeName);

            if (index !== -1) {
                Ext.Array.splice(defaultPreprocessors, Math.max(0, index + offset), 0, name);
            }

            return this;
        },

        configNameCache: {},

        getConfigNameMap: function(name) {
            var cache = this.configNameCache,
                map = cache[name],
                capitalizedName;

            if (!map) {
                capitalizedName = name.charAt(0).toUpperCase() + name.substr(1);

                map = cache[name] = {
                    internal: name,
                    initialized: '_is' + capitalizedName + 'Initialized',
                    apply: 'apply' + capitalizedName,
                    update: 'update' + capitalizedName,
                    'set': 'set' + capitalizedName,
                    'get': 'get' + capitalizedName,
                    doSet : 'doSet' + capitalizedName,
                    changeEvent: name.toLowerCase() + 'change'
                };
            }

            return map;
        }
    });

    
    ExtClass.registerPreprocessor('extend', function(Class, data, hooks) {
        
        var Base = Ext.Base,
            basePrototype = Base.prototype,
            extend = data.extend,
            Parent, parentPrototype, i;

        delete data.extend;

        if (extend && extend !== Object) {
            Parent = extend;
        }
        else {
            Parent = Base;
        }

        parentPrototype = Parent.prototype;

        if (!Parent.$isClass) {
            for (i in basePrototype) {
                if (!parentPrototype[i]) {
                    parentPrototype[i] = basePrototype[i];
                }
            }
        }

        Class.extend(Parent);

        Class.triggerExtended.apply(Class, arguments);

        if (data.onClassExtended) {
            Class.onExtended(data.onClassExtended, Class);
            delete data.onClassExtended;
        }

    }, true);

    
    ExtClass.registerPreprocessor('statics', function(Class, data) {
        
        Class.addStatics(data.statics);

        delete data.statics;
    });

    
    ExtClass.registerPreprocessor('inheritableStatics', function(Class, data) {
        
        Class.addInheritableStatics(data.inheritableStatics);

        delete data.inheritableStatics;
    });

    
    ExtClass.registerPreprocessor('config', function(Class, data) {
        
        var config = data.config,
            prototype = Class.prototype;

        delete data.config;

        Ext.Object.each(config, function(name, value) {
            var nameMap = ExtClass.getConfigNameMap(name),
                internalName = nameMap.internal,
                initializedName = nameMap.initialized,
                applyName = nameMap.apply,
                updateName = nameMap.update,
                setName = nameMap.set,
                getName = nameMap.get,
                hasOwnSetter = (setName in prototype) || data.hasOwnProperty(setName),
                hasOwnApplier = (applyName in prototype) || data.hasOwnProperty(applyName),
                hasOwnUpdater = (updateName in prototype) || data.hasOwnProperty(updateName),
                optimizedGetter, customGetter;

            if (value === null || (!hasOwnSetter && !hasOwnApplier && !hasOwnUpdater)) {
                prototype[internalName] = value;
                prototype[initializedName] = true;
            }
            else {
                prototype[initializedName] = false;
            }

            if (!hasOwnSetter) {
                data[setName] = function(value) {
                    var oldValue = this[internalName],
                        applier = this[applyName],
                        updater = this[updateName];

                    if (!this[initializedName]) {
                        this[initializedName] = true;
                    }

                    if (applier) {
                        value = applier.call(this, value, oldValue);
                    }

                    if (typeof value != 'undefined') {
                        this[internalName] = value;

                        if (updater && value !== oldValue) {
                            updater.call(this, value, oldValue);
                        }
                    }

                    return this;
                };
            }

            if (!(getName in prototype) || data.hasOwnProperty(getName)) {
                customGetter = data[getName] || false;

                if (customGetter) {
                    optimizedGetter = function() {
                        return customGetter.apply(this, arguments);
                    };
                }
                else {
                    optimizedGetter = function() {
                        return this[internalName];
                    };
                }

                data[getName] = function() {
                    var currentGetter;

                    if (!this[initializedName]) {
                        this[initializedName] = true;
                        this[setName](this.config[name]);
                    }

                    currentGetter = this[getName];

                    if ('$previous' in currentGetter) {
                        currentGetter.$previous = optimizedGetter;
                    }
                    else {
                        this[getName] = optimizedGetter;
                    }

                    return optimizedGetter.apply(this, arguments);
                };
            }
        });

        Class.addConfig(config, true);
    });

    
    ExtClass.registerPreprocessor('mixins', function(Class, data, hooks) {
        
        var mixins = data.mixins,
            name, mixin, i, ln;

        delete data.mixins;

        Ext.Function.interceptBefore(hooks, 'onCreated', function() {
        
            if (mixins instanceof Array) {
                for (i = 0,ln = mixins.length; i < ln; i++) {
                    mixin = mixins[i];
                    name = mixin.prototype.mixinId || mixin.$className;

                    Class.mixin(name, mixin);
                }
            }
            else {
                for (var mixinName in mixins) {
                    if (mixins.hasOwnProperty(mixinName)) {
                        Class.mixin(mixinName, mixins[mixinName]);
                    }
                }
            }
        });
    });

    
    Ext.extend = function(Class, Parent, members) {
            
        if (arguments.length === 2 && Ext.isObject(Parent)) {
            members = Parent;
            Parent = Class;
            Class = null;
        }

        var cls;

        if (!Parent) {
            throw new Error("[Ext.extend] Attempting to extend from a class which has not been loaded on the page.");
        }

        members.extend = Parent;
        members.preprocessors = [
            'extend'
            ,'statics'
            ,'inheritableStatics'
            ,'mixins'
            ,'config'
        ];

        if (Class) {
            cls = new ExtClass(Class, members);
            
            cls.prototype.constructor = Class;
        } else {
            cls = new ExtClass(members);
        }

        cls.prototype.override = function(o) {
            for (var m in o) {
                if (o.hasOwnProperty(m)) {
                    this[m] = o[m];
                }
            }
        };

        return cls;
    };
}());






(function(Class, alias, arraySlice, arrayFrom, global) {

    
    function makeCtor () {
        function constructor () {
            
            
            return this.constructor.apply(this, arguments) || null;
        }
        return constructor;
    }

    var Manager = Ext.ClassManager = {

        
        classes: {},

        
        existCache: {},

        
        namespaceRewrites: [{
            from: 'Ext.',
            to: Ext
        }],

        
        maps: {
            alternateToName: {},
            aliasToName: {},
            nameToAliases: {},
            nameToAlternates: {}
        },

        
        enableNamespaceParseCache: true,

        
        namespaceParseCache: {},

        
        instantiators: [],

        
        isCreated: function(className) {
            var existCache = this.existCache,
                i, ln, part, root, parts;


            if (this.classes[className] || existCache[className]) {
                return true;
            }

            root = global;
            parts = this.parseNamespace(className);

            for (i = 0, ln = parts.length; i < ln; i++) {
                part = parts[i];

                if (typeof part != 'string') {
                    root = part;
                } else {
                    if (!root || !root[part]) {
                        return false;
                    }

                    root = root[part];
                }
            }

            existCache[className] = true;

            this.triggerCreated(className);

            return true;
        },

        
        createdListeners: [],

        
        nameCreatedListeners: {},

        
        triggerCreated: function(className) {
            var listeners = this.createdListeners,
                nameListeners = this.nameCreatedListeners,
                alternateNames = this.maps.nameToAlternates[className],
                names = [className],
                i, ln, j, subLn, listener, name;

            for (i = 0,ln = listeners.length; i < ln; i++) {
                listener = listeners[i];
                listener.fn.call(listener.scope, className);
            }

            if (alternateNames) {
                names.push.apply(names, alternateNames);
            }

            for (i = 0,ln = names.length; i < ln; i++) {
                name = names[i];
                listeners = nameListeners[name];

                if (listeners) {
                    for (j = 0,subLn = listeners.length; j < subLn; j++) {
                        listener = listeners[j];
                        listener.fn.call(listener.scope, name);
                    }
                    delete nameListeners[name];
                }
            }
        },

        
        onCreated: function(fn, scope, className) {
            
            var listeners = this.createdListeners,
                nameListeners = this.nameCreatedListeners,
                listener = {
                    fn: fn,
                    scope: scope
                };

            if (className) {
                if (this.isCreated(className)) {
                    fn.call(scope, className);
                    return;
                }

                if (!nameListeners[className]) {
                    nameListeners[className] = [];
                }

                nameListeners[className].push(listener);
            }
            else {
                listeners.push(listener);
            }
        },

        
        parseNamespace: function(namespace) {

            var cache = this.namespaceParseCache,
                parts,
                rewrites,
                root,
                name,
                rewrite, from, to, i, ln;

            if (this.enableNamespaceParseCache) {
                if (cache.hasOwnProperty(namespace)) {
                    return cache[namespace];
                }
            }

            parts = [];
            rewrites = this.namespaceRewrites;
            root = global;
            name = namespace;

            for (i = 0, ln = rewrites.length; i < ln; i++) {
                rewrite = rewrites[i];
                from = rewrite.from;
                to = rewrite.to;

                if (name === from || name.substring(0, from.length) === from) {
                    name = name.substring(from.length);

                    if (typeof to != 'string') {
                        root = to;
                    } else {
                        parts = parts.concat(to.split('.'));
                    }

                    break;
                }
            }

            parts.push(root);

            parts = parts.concat(name.split('.'));

            if (this.enableNamespaceParseCache) {
                cache[namespace] = parts;
            }

            return parts;
        },

        
        setNamespace: function(name, value) {
            var root = global,
                parts = this.parseNamespace(name),
                ln = parts.length - 1,
                leaf = parts[ln],
                i, part;

            for (i = 0; i < ln; i++) {
                part = parts[i];

                if (typeof part != 'string') {
                    root = part;
                } else {
                    if (!root[part]) {
                        root[part] = {};
                    }

                    root = root[part];
                }
            }

            root[leaf] = value;

            return root[leaf];
        },

        
        createNamespaces: function() {
            var root = global,
                parts, part, i, j, ln, subLn;

            for (i = 0, ln = arguments.length; i < ln; i++) {
                parts = this.parseNamespace(arguments[i]);

                for (j = 0, subLn = parts.length; j < subLn; j++) {
                    part = parts[j];

                    if (typeof part != 'string') {
                        root = part;
                    } else {
                        if (!root[part]) {
                            root[part] = {};
                        }

                        root = root[part];
                    }
                }
            }

            return root;
        },

        
        set: function(name, value) {
            var me = this,
                maps = me.maps,
                nameToAlternates = maps.nameToAlternates,
                targetName = me.getName(value),
                alternates;

            me.classes[name] = me.setNamespace(name, value);

            if (targetName && targetName !== name) {
                maps.alternateToName[name] = targetName;
                alternates = nameToAlternates[targetName] || (nameToAlternates[targetName] = []);
                alternates.push(name);
            }

            return this;
        },

        
        get: function(name) {
            var classes = this.classes,
                root,
                parts,
                part, i, ln;

            if (classes[name]) {
                return classes[name];
            }

            root = global;
            parts = this.parseNamespace(name);

            for (i = 0, ln = parts.length; i < ln; i++) {
                part = parts[i];

                if (typeof part != 'string') {
                    root = part;
                } else {
                    if (!root || !root[part]) {
                        return null;
                    }

                    root = root[part];
                }
            }

            return root;
        },

        
        setAlias: function(cls, alias) {
            var aliasToNameMap = this.maps.aliasToName,
                nameToAliasesMap = this.maps.nameToAliases,
                className;

            if (typeof cls == 'string') {
                className = cls;
            } else {
                className = this.getName(cls);
            }

            if (alias && aliasToNameMap[alias] !== className) {

                aliasToNameMap[alias] = className;
            }

            if (!nameToAliasesMap[className]) {
                nameToAliasesMap[className] = [];
            }

            if (alias) {
                Ext.Array.include(nameToAliasesMap[className], alias);
            }

            return this;
        },

        
        addNameAliasMappings: function(aliases){
            var aliasToNameMap = this.maps.aliasToName,
                nameToAliasesMap = this.maps.nameToAliases,
                className, aliasList, alias, i;

            for (className in aliases) {
                aliasList = nameToAliasesMap[className] ||
                    (nameToAliasesMap[className] = []);

                for (i = 0; i < aliases[className].length; i++) {
                    alias = aliases[className][i];
                    if (!aliasToNameMap[alias]) {
                        aliasToNameMap[alias] = className;
                        aliasList.push(alias);
                    }
                }

            }
            return this;
        },

        
        addNameAlternateMappings: function(alternates) {
            var alternateToName = this.maps.alternateToName,
                nameToAlternates = this.maps.nameToAlternates,
                className, aliasList, alternate, i;

            for (className in alternates) {
                aliasList = nameToAlternates[className] ||
                    (nameToAlternates[className] = []);

                for (i  = 0; i < alternates[className].length; i++) {
                    alternate = alternates[className][i];
                    if (!alternateToName[alternate]) {
                        alternateToName[alternate] = className;
                        aliasList.push(alternate);
                    }
                }

            }
            return this;
        },

        
        getByAlias: function(alias) {
            return this.get(this.getNameByAlias(alias));
        },

        
        getNameByAlias: function(alias) {
            return this.maps.aliasToName[alias] || '';
        },

        
        getNameByAlternate: function(alternate) {
            return this.maps.alternateToName[alternate] || '';
        },

        
        getAliasesByName: function(name) {
            return this.maps.nameToAliases[name] || [];
        },

        
        getName: function(object) {
            return object && object.$className || '';
        },

        
        getClass: function(object) {
            return object && object.self || null;
        },

        
        create: function(className, data, createdFn) {

            var ctor = makeCtor();
            if (typeof data == 'function') {
                data = data(ctor);
            }


            data.$className = className;

            return new Class(ctor, data, function() {
                var postprocessorStack = data.postprocessors || Manager.defaultPostprocessors,
                    registeredPostprocessors = Manager.postprocessors,
                    postprocessors = [],
                    postprocessor, i, ln, j, subLn, postprocessorProperties, postprocessorProperty;

                delete data.postprocessors;

                for (i = 0,ln = postprocessorStack.length; i < ln; i++) {
                    postprocessor = postprocessorStack[i];

                    if (typeof postprocessor == 'string') {
                        postprocessor = registeredPostprocessors[postprocessor];
                        postprocessorProperties = postprocessor.properties;

                        if (postprocessorProperties === true) {
                            postprocessors.push(postprocessor.fn);
                        }
                        else if (postprocessorProperties) {
                            for (j = 0,subLn = postprocessorProperties.length; j < subLn; j++) {
                                postprocessorProperty = postprocessorProperties[j];

                                if (data.hasOwnProperty(postprocessorProperty)) {
                                    postprocessors.push(postprocessor.fn);
                                    break;
                                }
                            }
                        }
                    }
                    else {
                        postprocessors.push(postprocessor);
                    }
                }

                data.postprocessors = postprocessors;
                data.createdFn = createdFn;
                Manager.processCreate(className, this, data);
            });
        },

        processCreate: function(className, cls, clsData){
            var me = this,
                postprocessor = clsData.postprocessors.shift(),
                createdFn = clsData.createdFn;

            if (!postprocessor) {
                
                if (className) {
                    me.set(className, cls);
                }

                if (createdFn) {
                    createdFn.call(cls, cls);
                }

                if (className) {
                    me.triggerCreated(className);
                }
                return;
            }

            if (postprocessor.call(me, className, cls, clsData, me.processCreate) !== false) {
                me.processCreate(className, cls, clsData);
            }
        },

        createOverride: function (className, data, createdFn) {
            var me = this,
                overriddenClassName = data.override,
                requires = data.requires,
                uses = data.uses,
                compat = data.compatibility,
                classReady = function () {
                    var cls, temp;

                    if (requires) {
                        temp = requires;
                        requires = null; 

                        
                        
                        
                        Ext.Loader.require(temp, classReady);
                    } else {
                        
                        
                        cls = me.get(overriddenClassName);

                        
                        delete data.override;
                        delete data.compatibility;
                        delete data.requires;
                        delete data.uses;

                        Ext.override(cls, data);

                        
                        
                        
                        me.triggerCreated(className);

                        if (uses) {
                            Ext.Loader.addUsedClasses(uses); 
                        }

                        if (createdFn) {
                            createdFn.call(cls); 
                        }
                    }
                };

            me.existCache[className] = true;

            if (!compat || Ext.checkVersion(compat)) {
                
                me.onCreated(classReady, me, overriddenClassName);
            }

            return me;
        },

        
        instantiateByAlias: function() {
            var alias = arguments[0],
                args = arraySlice.call(arguments),
                className = this.getNameByAlias(alias);

            if (!className) {
                className = this.maps.aliasToName[alias];



                Ext.syncRequire(className);
            }

            args[0] = className;

            return this.instantiate.apply(this, args);
        },

        
        instantiate: function() {
            var name = arguments[0],
                nameType = typeof name,
                args = arraySlice.call(arguments, 1),
                alias = name,
                possibleName, cls;

            if (nameType != 'function') {
                if (nameType != 'string' && args.length === 0) {
                    args = [name];
                    name = name.xclass;
                }


                cls = this.get(name);
            }
            else {
                cls = name;
            }

            
            if (!cls) {
                possibleName = this.getNameByAlias(name);

                if (possibleName) {
                    name = possibleName;

                    cls = this.get(name);
                }
            }

            
            if (!cls) {
                possibleName = this.getNameByAlternate(name);

                if (possibleName) {
                    name = possibleName;

                    cls = this.get(name);
                }
            }

            
            if (!cls) {

                Ext.syncRequire(name);

                cls = this.get(name);
            }


            return this.getInstantiator(args.length)(cls, args);
        },

        
        dynInstantiate: function(name, args) {
            args = arrayFrom(args, true);
            args.unshift(name);

            return this.instantiate.apply(this, args);
        },

        
        getInstantiator: function(length) {
            var instantiators = this.instantiators,
                instantiator,
                i,
                args;

            instantiator = instantiators[length];

            if (!instantiator) {
                i = length;
                args = [];

                for (i = 0; i < length; i++) {
                    args.push('a[' + i + ']');
                }

                instantiator = instantiators[length] = new Function('c', 'a', 'return new c(' + args.join(',') + ')');
            }

            return instantiator;
        },

        
        postprocessors: {},

        
        defaultPostprocessors: [],

        
        registerPostprocessor: function(name, fn, properties, position, relativeTo) {
            if (!position) {
                position = 'last';
            }

            if (!properties) {
                properties = [name];
            }

            this.postprocessors[name] = {
                name: name,
                properties: properties || false,
                fn: fn
            };

            this.setDefaultPostprocessorPosition(name, position, relativeTo);

            return this;
        },

        
        setDefaultPostprocessors: function(postprocessors) {
            this.defaultPostprocessors = arrayFrom(postprocessors);

            return this;
        },

        
        setDefaultPostprocessorPosition: function(name, offset, relativeName) {
            var defaultPostprocessors = this.defaultPostprocessors,
                index;

            if (typeof offset == 'string') {
                if (offset === 'first') {
                    defaultPostprocessors.unshift(name);

                    return this;
                }
                else if (offset === 'last') {
                    defaultPostprocessors.push(name);

                    return this;
                }

                offset = (offset === 'after') ? 1 : -1;
            }

            index = Ext.Array.indexOf(defaultPostprocessors, relativeName);

            if (index !== -1) {
                Ext.Array.splice(defaultPostprocessors, Math.max(0, index + offset), 0, name);
            }

            return this;
        },

        
        getNamesByExpression: function(expression) {
            var nameToAliasesMap = this.maps.nameToAliases,
                names = [],
                name, alias, aliases, possibleName, regex, i, ln;


            if (expression.indexOf('*') !== -1) {
                expression = expression.replace(/\*/g, '(.*?)');
                regex = new RegExp('^' + expression + '$');

                for (name in nameToAliasesMap) {
                    if (nameToAliasesMap.hasOwnProperty(name)) {
                        aliases = nameToAliasesMap[name];

                        if (name.search(regex) !== -1) {
                            names.push(name);
                        }
                        else {
                            for (i = 0, ln = aliases.length; i < ln; i++) {
                                alias = aliases[i];

                                if (alias.search(regex) !== -1) {
                                    names.push(name);
                                    break;
                                }
                            }
                        }
                    }
                }

            } else {
                possibleName = this.getNameByAlias(expression);

                if (possibleName) {
                    names.push(possibleName);
                } else {
                    possibleName = this.getNameByAlternate(expression);

                    if (possibleName) {
                        names.push(possibleName);
                    } else {
                        names.push(expression);
                    }
                }
            }

            return names;
        }
    };

    
    Manager.registerPostprocessor('alias', function(name, cls, data) {
        
        var aliases = data.alias,
            i, ln;

        for (i = 0,ln = aliases.length; i < ln; i++) {
            alias = aliases[i];

            this.setAlias(cls, alias);
        }

    }, ['xtype', 'alias']);

    
    Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {
        
        if (data.singleton) {
            fn.call(this, name, new cls(), data);
        }
        else {
            return true;
        }
        return false;
    });

    
    Manager.registerPostprocessor('alternateClassName', function(name, cls, data) {
        
        var alternates = data.alternateClassName,
            i, ln, alternate;

        if (!(alternates instanceof Array)) {
            alternates = [alternates];
        }

        for (i = 0, ln = alternates.length; i < ln; i++) {
            alternate = alternates[i];


            this.set(alternate, cls);
        }
    });

    Ext.apply(Ext, {
        
        create: alias(Manager, 'instantiate'),

        
        widget: function(name, config) {
            
            
            
            
            
            
            
            var xtype = name,
                alias, className, T, load;

            if (typeof xtype != 'string') { 
                
                config = name; 
                xtype = config.xtype;
            } else {
                config = config || {};
            }

            if (config.isComponent) {
                return config;
            }

            alias = 'widget.' + xtype;
            className = Manager.getNameByAlias(alias);

            
            if (!className) {
                load = true;
            }

            T = Manager.get(className);
            if (load || !T) {
                return Manager.instantiateByAlias(alias, config);
            }
            return new T(config);
        },

        
        createByAlias: alias(Manager, 'instantiateByAlias'),

        
        define: function (className, data, createdFn) {
            
            if (data.override) {
                return Manager.createOverride.apply(Manager, arguments);
            }

            return Manager.create.apply(Manager, arguments);
        },

        
        undefine: function(className) {
        
            var classes = Manager.classes,
                maps = Manager.maps,
                aliasToName = maps.aliasToName,
                nameToAliases = maps.nameToAliases,
                alternateToName = maps.alternateToName,
                nameToAlternates = maps.nameToAlternates,
                aliases = nameToAliases[className],
                alternates = nameToAlternates[className],
                parts, partCount, namespace, i;

            delete Manager.namespaceParseCache[className];
            delete nameToAliases[className];
            delete nameToAlternates[className];
            delete classes[className];

            if (aliases) {
                for (i = aliases.length; i--;) {
                    delete aliasToName[aliases[i]];
                }
            }

            if (alternates) {
                for (i = alternates.length; i--; ) {
                    delete alternateToName[alternates[i]];
                }
            }

            parts  = Manager.parseNamespace(className);
            partCount = parts.length - 1;
            namespace = parts[0];

            for (i = 1; i < partCount; i++) {
                namespace = namespace[parts[i]];
                if (!namespace) {
                    return;
                }
            }

            
            try {
                delete namespace[parts[partCount]];
            }
            catch (e) {
                namespace[parts[partCount]] = undefined;
            }
        },

        
        getClassName: alias(Manager, 'getName'),

        
        getDisplayName: function(object) {
            if (object) {
                if (object.displayName) {
                    return object.displayName;
                }

                if (object.$name && object.$class) {
                    return Ext.getClassName(object.$class) + '#' + object.$name;
                }

                if (object.$className) {
                    return object.$className;
                }
            }

            return 'Anonymous';
        },

        
        getClass: alias(Manager, 'getClass'),

        
        namespace: alias(Manager, 'createNamespaces')
    });

    
    Ext.createWidget = Ext.widget;

    
    Ext.ns = Ext.namespace;

    Class.registerPreprocessor('className', function(cls, data) {
        if (data.$className) {
            cls.$className = data.$className;
        }
        
    }, true, 'first');

    Class.registerPreprocessor('alias', function(cls, data) {
        
        var prototype = cls.prototype,
            xtypes = arrayFrom(data.xtype),
            aliases = arrayFrom(data.alias),
            widgetPrefix = 'widget.',
            widgetPrefixLength = widgetPrefix.length,
            xtypesChain = Array.prototype.slice.call(prototype.xtypesChain || []),
            xtypesMap = Ext.merge({}, prototype.xtypesMap || {}),
            i, ln, alias, xtype;

        for (i = 0,ln = aliases.length; i < ln; i++) {
            alias = aliases[i];


            if (alias.substring(0, widgetPrefixLength) === widgetPrefix) {
                xtype = alias.substring(widgetPrefixLength);
                Ext.Array.include(xtypes, xtype);
            }
        }

        cls.xtype = data.xtype = xtypes[0];
        data.xtypes = xtypes;

        for (i = 0,ln = xtypes.length; i < ln; i++) {
            xtype = xtypes[i];

            if (!xtypesMap[xtype]) {
                xtypesMap[xtype] = true;
                xtypesChain.push(xtype);
            }
        }

        data.xtypesChain = xtypesChain;
        data.xtypesMap = xtypesMap;

        Ext.Function.interceptAfter(data, 'onClassCreated', function() {
        
            var mixins = prototype.mixins,
                key, mixin;

            for (key in mixins) {
                if (mixins.hasOwnProperty(key)) {
                    mixin = mixins[key];

                    xtypes = mixin.xtypes;

                    if (xtypes) {
                        for (i = 0,ln = xtypes.length; i < ln; i++) {
                            xtype = xtypes[i];

                            if (!xtypesMap[xtype]) {
                                xtypesMap[xtype] = true;
                                xtypesChain.push(xtype);
                            }
                        }
                    }
                }
            }
        });

        for (i = 0,ln = xtypes.length; i < ln; i++) {
            xtype = xtypes[i];


            Ext.Array.include(aliases, widgetPrefix + xtype);
        }

        data.alias = aliases;

    }, ['xtype', 'alias']);

}(Ext.Class, Ext.Function.alias, Array.prototype.slice, Ext.Array.from, Ext.global));



if (Ext._alternatesMetadata) {
   Ext.ClassManager.addNameAlternateMappings(Ext._alternatesMetadata);
   Ext._alternatesMetadata = null;
}

if (Ext._aliasMetadata) {
    Ext.ClassManager.addNameAliasMappings(Ext._aliasMetadata);
    Ext._aliasMetadata = null;
}







Ext.Loader = new function() {
    var Loader = this,
        Manager = Ext.ClassManager,
        Class = Ext.Class,
        flexSetter = Ext.Function.flexSetter,
        alias = Ext.Function.alias,
        pass = Ext.Function.pass,
        defer = Ext.Function.defer,
        arrayErase = Ext.Array.erase,
        dependencyProperties = ['extend', 'mixins', 'requires'],
        isInHistory = {},
        history = [],
        slashDotSlashRe = /\/\.\//g,
        dotRe = /\./g,
        setPathCount = 0;

    Ext.apply(Loader, {

        
        isInHistory: isInHistory,

        
        history: history,

        
        config: {
            
            enabled: false,

            
            scriptChainDelay : false,

            
            disableCaching: true,

            
            disableCachingParam: '_dc',

            
            garbageCollect : false,

            
            paths: {
                'Ext': '.'
            },

            
            preserveScripts : true,

            
            scriptCharset : undefined
        },

        
        setConfig: function(name, value) {
            if (Ext.isObject(name) && arguments.length === 1) {
                Ext.merge(Loader.config, name);

                if ('paths' in name) {
                    Ext.app.collectNamespaces(name.paths);
                }
            }
            else {
                Loader.config[name] = (Ext.isObject(value)) ? Ext.merge(Loader.config[name], value) : value;

                if (name === 'paths') {
                    Ext.app.collectNamespaces(value);
                }
            }

            return Loader;
        },

        
        getConfig: function(name) {
            if (name) {
                return Loader.config[name];
            }

            return Loader.config;
        },

        
        setPath: flexSetter(function(name, path) {
            Loader.config.paths[name] = path;
            Ext.app.namespaces[name] = true;
            setPathCount++;

            return Loader;
        }),

        
        addClassPathMappings: function(paths) {
            var name;

            if(setPathCount == 0){
                Loader.config.paths = paths;
            } else {
                for(name in paths){
                    Loader.config.paths[name] = paths[name];
                }
            }
            setPathCount++;
            return Loader;
        },

        
        getPath: function(className) {
            var path = '',
                paths = Loader.config.paths,
                prefix = Loader.getPrefix(className);

            if (prefix.length > 0) {
                if (prefix === className) {
                    return paths[prefix];
                }

                path = paths[prefix];
                className = className.substring(prefix.length + 1);
            }

            if (path.length > 0) {
                path += '/';
            }

            return path.replace(slashDotSlashRe, '/') + className.replace(dotRe, "/") + '.js';
        },

        
        getPrefix: function(className) {
            var paths = Loader.config.paths,
                prefix, deepestPrefix = '';

            if (paths.hasOwnProperty(className)) {
                return className;
            }

            for (prefix in paths) {
                if (paths.hasOwnProperty(prefix) && prefix + '.' === className.substring(0, prefix.length + 1)) {
                    if (prefix.length > deepestPrefix.length) {
                        deepestPrefix = prefix;
                    }
                }
            }

            return deepestPrefix;
        },

        
        isAClassNameWithAKnownPrefix: function(className) {
            var prefix = Loader.getPrefix(className);

            
            return prefix !== '' && prefix !== className;
        },

        
        require: function(expressions, fn, scope, excludes) {
            if (fn) {
                fn.call(scope);
            }
        },

        
        syncRequire: function() {},

        
        exclude: function(excludes) {
            return {
                require: function(expressions, fn, scope) {
                    return Loader.require(expressions, fn, scope, excludes);
                },

                syncRequire: function(expressions, fn, scope) {
                    return Loader.syncRequire(expressions, fn, scope, excludes);
                }
            };
        },

        
        onReady: function(fn, scope, withDomReady, options) {
            var oldFn;

            if (withDomReady !== false && Ext.onDocumentReady) {
                oldFn = fn;

                fn = function() {
                    Ext.onDocumentReady(oldFn, scope, options);
                };
            }

            fn.call(scope);
        }
    });

    var queue = [],
        isClassFileLoaded = {},
        isFileLoaded = {},
        classNameToFilePathMap = {},
        scriptElements = {},
        readyListeners = [],
        usedClasses = [],
        requiresMap = {},
        comparePriority = function(listenerA, listenerB) {
            return listenerB.priority - listenerA.priority;
        };

    Ext.apply(Loader, {
        
        documentHead: typeof document != 'undefined' && (document.head || document.getElementsByTagName('head')[0]),

        
        isLoading: false,

        
        queue: queue,

        
        isClassFileLoaded: isClassFileLoaded,

        
        isFileLoaded: isFileLoaded,

        
        readyListeners: readyListeners,

        
        optionalRequires: usedClasses,

        
        requiresMap: requiresMap,

        
        numPendingFiles: 0,

        
        numLoadedFiles: 0,

        
        hasFileLoadError: false,

        
        classNameToFilePathMap: classNameToFilePathMap,

        
        scriptsLoading: 0,

        
        syncModeEnabled: false,

        scriptElements: scriptElements,

        
        refreshQueue: function() {
            var ln = queue.length,
                i, item, j, requires;

            

            if (!ln && !Loader.scriptsLoading) {
                return Loader.triggerReady();
            }

            for (i = 0; i < ln; i++) {
                item = queue[i];

                if (item) {
                    requires = item.requires;

                    
                    
                    if (requires.length > Loader.numLoadedFiles) {
                        continue;
                    }

                    
                    for (j = 0; j < requires.length; ) {
                        if (Manager.isCreated(requires[j])) {
                            
                            arrayErase(requires, j, 1);
                        }
                        else {
                            j++;
                        }
                    }

                    
                    if (item.requires.length === 0) {
                        arrayErase(queue, i, 1);
                        item.callback.call(item.scope);
                        Loader.refreshQueue();
                        break;
                    }
                }
            }

            return Loader;
        },

        
        injectScriptElement: function(url, onLoad, onError, scope, charset) {
            var script = document.createElement('script'),
                dispatched = false,
                config = Loader.config,
                onLoadFn = function() {

                    if(!dispatched) {
                        dispatched = true;
                        script.onload = script.onreadystatechange = script.onerror = null;
                        if (typeof config.scriptChainDelay == 'number') {
                            
                            defer(onLoad, config.scriptChainDelay, scope);
                        } else {
                            onLoad.call(scope);
                        }
                        Loader.cleanupScriptElement(script, config.preserveScripts === false, config.garbageCollect);
                    }

                },
                onErrorFn = function(arg) {
                    defer(onError, 1, scope);   
                    Loader.cleanupScriptElement(script, config.preserveScripts === false, config.garbageCollect);
                };

            script.type = 'text/javascript';
            script.onerror = onErrorFn;
            charset = charset || config.scriptCharset;
            if (charset) {
                script.charset = charset;
            }

            
            if ('addEventListener' in script ) {
                script.onload = onLoadFn;
            } else if ('readyState' in script) {   
                script.onreadystatechange = function() {
                    if ( this.readyState == 'loaded' || this.readyState == 'complete' ) {
                        onLoadFn();
                    }
                };
            } else {
                 script.onload = onLoadFn;
            }

            script.src = url;
            (Loader.documentHead || document.getElementsByTagName('head')[0]).appendChild(script);

            return script;
        },

        
        removeScriptElement: function(url) {
            if (scriptElements[url]) {
                Loader.cleanupScriptElement(scriptElements[url], true, !!Loader.getConfig('garbageCollect'));
                delete scriptElements[url];
            }

            return Loader;
        },

        
        cleanupScriptElement: function(script, remove, collect) {
            var prop;
            script.onload = script.onreadystatechange = script.onerror = null;
            if (remove) {
                Ext.removeNode(script);       
                if (collect) {
                    for (prop in script) {
                        try {
                            if (prop != 'src') {
                                
                                
                                script[prop] = null;
                            }
                            delete script[prop];      
                        } catch (cleanEx) {
                            
                        }
                    }
                }
            }

            return Loader;
        },

        
        loadScript: function (options) {
            var config = Loader.getConfig(),
                isString = typeof options == 'string',
                url = isString ? options : options.url,
                onError = !isString && options.onError,
                onLoad = !isString && options.onLoad,
                scope = !isString && options.scope,
                onScriptError = function() {
                    Loader.numPendingFiles--;
                    Loader.scriptsLoading--;

                    if (onError) {
                        onError.call(scope, "Failed loading '" + url + "', please verify that the file exists");
                    }

                    if (Loader.numPendingFiles + Loader.scriptsLoading === 0) {
                        Loader.refreshQueue();
                    }
                },
                onScriptLoad = function () {
                    Loader.numPendingFiles--;
                    Loader.scriptsLoading--;

                    if (onLoad) {
                        onLoad.call(scope);
                    }

                    if (Loader.numPendingFiles + Loader.scriptsLoading === 0) {
                        Loader.refreshQueue();
                    }
                },
                src;

            Loader.isLoading = true;
            Loader.numPendingFiles++;
            Loader.scriptsLoading++;

            src = config.disableCaching ?
                (url + '?' + config.disableCachingParam + '=' + Ext.Date.now()) : url;

            scriptElements[url] = Loader.injectScriptElement(src, onScriptLoad, onScriptError);
        },

        
        loadScriptFile: function(url, onLoad, onError, scope, synchronous) {
            if (isFileLoaded[url]) {
                return Loader;
            }

            var config = Loader.getConfig(),
                noCacheUrl = url + (config.disableCaching ? ('?' + config.disableCachingParam + '=' + Ext.Date.now()) : ''),
                isCrossOriginRestricted = false,
                xhr, status, onScriptError,
                debugSourceURL = "";

            scope = scope || Loader;

            Loader.isLoading = true;

            if (!synchronous) {
                onScriptError = function() {
                };

                scriptElements[url] = Loader.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
            } else {
                if (typeof XMLHttpRequest != 'undefined') {
                    xhr = new XMLHttpRequest();
                } else {
                    xhr = new ActiveXObject('Microsoft.XMLHTTP');
                }

                try {
                    xhr.open('GET', noCacheUrl, false);
                    xhr.send(null);
                } catch (e) {
                    isCrossOriginRestricted = true;
                }

                status = (xhr.status === 1223) ? 204 :
                    (xhr.status === 0 && ((self.location || {}).protocol == 'file:' || (self.location || {}).protocol == 'ionp:')) ? 200 : xhr.status;

                isCrossOriginRestricted = isCrossOriginRestricted || (status === 0);

                if (isCrossOriginRestricted
                ) {
                }
                else if ((status >= 200 && status < 300) || (status === 304)
                ) {
                    
                    
                    if (!Ext.isIE) {
                        debugSourceURL = "\n//@ sourceURL=" + url;
                    }

                    Ext.globalEval(xhr.responseText + debugSourceURL);

                    onLoad.call(scope);
                }
                else {
                }

                
                xhr = null;
            }
        },

        
        syncRequire: function() {
            var syncModeEnabled = Loader.syncModeEnabled;

            if (!syncModeEnabled) {
                Loader.syncModeEnabled = true;
            }

            Loader.require.apply(Loader, arguments);

            if (!syncModeEnabled) {
                Loader.syncModeEnabled = false;
            }

            Loader.refreshQueue();
        },

        
        require: function(expressions, fn, scope, excludes) {
            var excluded = {},
                included = {},
                excludedClassNames = [],
                possibleClassNames = [],
                classNames = [],
                references = [],
                callback,
                syncModeEnabled,
                filePath, expression, exclude, className,
                possibleClassName, i, j, ln, subLn;

            if (excludes) {
                
                excludes = (typeof excludes === 'string') ? [ excludes ] : excludes;

                for (i = 0,ln = excludes.length; i < ln; i++) {
                    exclude = excludes[i];

                    if (typeof exclude == 'string' && exclude.length > 0) {
                        excludedClassNames = Manager.getNamesByExpression(exclude);

                        for (j = 0,subLn = excludedClassNames.length; j < subLn; j++) {
                            excluded[excludedClassNames[j]] = true;
                        }
                    }
                }
            }

            
            expressions = (typeof expressions === 'string') ? [ expressions ] : (expressions ? expressions : []);

            if (fn) {
                if (fn.length > 0) {
                    callback = function() {
                        var classes = [],
                            i, ln;

                        for (i = 0,ln = references.length; i < ln; i++) {
                            classes.push(Manager.get(references[i]));
                        }

                        return fn.apply(this, classes);
                    };
                }
                else {
                    callback = fn;
                }
            }
            else {
                callback = Ext.emptyFn;
            }

            scope = scope || Ext.global;

            for (i = 0,ln = expressions.length; i < ln; i++) {
                expression = expressions[i];

                if (typeof expression == 'string' && expression.length > 0) {
                    possibleClassNames = Manager.getNamesByExpression(expression);
                    subLn = possibleClassNames.length;

                    for (j = 0; j < subLn; j++) {
                        possibleClassName = possibleClassNames[j];

                        if (excluded[possibleClassName] !== true) {
                            references.push(possibleClassName);

                            if (!Manager.isCreated(possibleClassName) && !included[possibleClassName]) {
                                included[possibleClassName] = true;
                                classNames.push(possibleClassName);
                            }
                        }
                    }
                }
            }

            
            
            if (classNames.length > 0) {
                if (!Loader.config.enabled) {
                    throw new Error("Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " +
                             "Missing required class" + ((classNames.length > 1) ? "es" : "") + ": " + classNames.join(', '));
                }
            }
            else {
                callback.call(scope);
                return Loader;
            }

            syncModeEnabled = Loader.syncModeEnabled;

            if (!syncModeEnabled) {
                queue.push({
                    requires: classNames.slice(), 
                                                  
                    callback: callback,
                    scope: scope
                });
            }

            ln = classNames.length;

            for (i = 0; i < ln; i++) {
                className = classNames[i];

                filePath = Loader.getPath(className);

                
                
                
                if (syncModeEnabled && isClassFileLoaded.hasOwnProperty(className)) {
                    if (!isClassFileLoaded[className]) {
                        Loader.numPendingFiles--;
                        Loader.removeScriptElement(filePath);
                        delete isClassFileLoaded[className];
                    }
                }

                if (!isClassFileLoaded.hasOwnProperty(className)) {
                    isClassFileLoaded[className] = false;
                    classNameToFilePathMap[className] = filePath;

                    Loader.numPendingFiles++;
                    Loader.loadScriptFile(
                        filePath,
                        pass(Loader.onFileLoaded, [className, filePath], Loader),
                        pass(Loader.onFileLoadError, [className, filePath], Loader),
                        Loader,
                        syncModeEnabled
                    );
                }
            }

            if (syncModeEnabled) {
                callback.call(scope);

                if (ln === 1) {
                    return Manager.get(className);
                }
            }

            return Loader;
        },

        
        onFileLoaded: function(className, filePath) {
            var loaded = isClassFileLoaded[className];
            Loader.numLoadedFiles++;

            isClassFileLoaded[className] = true;
            isFileLoaded[filePath] = true;

            
            
            if (!loaded) {
                Loader.numPendingFiles--;
            }

            if (Loader.numPendingFiles === 0) {
                Loader.refreshQueue();
            }

        },

        
        onFileLoadError: function(className, filePath, errorMessage, isSynchronous) {
            Loader.numPendingFiles--;
            Loader.hasFileLoadError = true;

        },

        
        addUsedClasses: function (classes) {
            var cls, i, ln;

            if (classes) {
                classes = (typeof classes == 'string') ? [classes] : classes;
                for (i = 0, ln = classes.length; i < ln; i++) {
                    cls = classes[i];
                    if (typeof cls == 'string' && !Ext.Array.contains(usedClasses, cls)) {
                        usedClasses.push(cls);
                    }
                }
            }

            return Loader;
        },

        
        triggerReady: function() {
            var listener,
                refClasses = usedClasses;

            if (Loader.isLoading) {
                Loader.isLoading = false;

                if (refClasses.length !== 0) {
                    
                    refClasses = refClasses.slice();
                    usedClasses.length = 0;
                    
                    
                    Loader.require(refClasses, Loader.triggerReady, Loader);
                    return Loader;
                }
            }

            Ext.Array.sort(readyListeners, comparePriority);

            
            
            
            while (readyListeners.length && !Loader.isLoading) {
                
                
                listener = readyListeners.shift();
                listener.fn.call(listener.scope);
            }

            return Loader;
        },

        
        onReady: function(fn, scope, withDomReady, options) {
            var oldFn;

            if (withDomReady !== false && Ext.onDocumentReady) {
                oldFn = fn;

                fn = function() {
                    Ext.onDocumentReady(oldFn, scope, options);
                };
            }

            if (!Loader.isLoading) {
                fn.call(scope);
            }
            else {
                readyListeners.push({
                    fn: fn,
                    scope: scope,
                    priority: (options && options.priority) || 0
                });
            }
        },

        
        historyPush: function(className) {
            if (className && isClassFileLoaded.hasOwnProperty(className) && !isInHistory[className]) {
                isInHistory[className] = true;
                history.push(className);
            }
            return Loader;
        }
    });

    
    Ext.disableCacheBuster = function (disable, path) {
        var date = new Date();
        date.setTime(date.getTime() + (disable ? 10*365 : -1) * 24*60*60*1000);
        date = date.toGMTString();
        document.cookie = 'ext-cache=1; expires=' + date + '; path='+(path || '/');
    };


    
    Ext.require = alias(Loader, 'require');

    
    Ext.syncRequire = alias(Loader, 'syncRequire');

    
    Ext.exclude = alias(Loader, 'exclude');

    
    Ext.onReady = function(fn, scope, options) {
        Loader.onReady(fn, scope, true, options);
    };

    
    Class.registerPreprocessor('loader', function(cls, data, hooks, continueFn) {
        
        var me = this,
            dependencies = [],
            dependency,
            className = Manager.getName(cls),
            i, j, ln, subLn, value, propertyName, propertyValue,
            requiredMap, requiredDep;

        

        for (i = 0,ln = dependencyProperties.length; i < ln; i++) {
            propertyName = dependencyProperties[i];

            if (data.hasOwnProperty(propertyName)) {
                propertyValue = data[propertyName];

                if (typeof propertyValue == 'string') {
                    dependencies.push(propertyValue);
                }
                else if (propertyValue instanceof Array) {
                    for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
                        value = propertyValue[j];

                        if (typeof value == 'string') {
                            dependencies.push(value);
                        }
                    }
                }
                else if (typeof propertyValue != 'function') {
                    for (j in propertyValue) {
                        if (propertyValue.hasOwnProperty(j)) {
                            value = propertyValue[j];

                            if (typeof value == 'string') {
                                dependencies.push(value);
                            }
                        }
                    }
                }
            }
        }

        if (dependencies.length === 0) {
            return;
        }


        Loader.require(dependencies, function() {
            for (i = 0,ln = dependencyProperties.length; i < ln; i++) {
                propertyName = dependencyProperties[i];

                if (data.hasOwnProperty(propertyName)) {
                    propertyValue = data[propertyName];

                    if (typeof propertyValue == 'string') {
                        data[propertyName] = Manager.get(propertyValue);
                    }
                    else if (propertyValue instanceof Array) {
                        for (j = 0, subLn = propertyValue.length; j < subLn; j++) {
                            value = propertyValue[j];

                            if (typeof value == 'string') {
                                data[propertyName][j] = Manager.get(value);
                            }
                        }
                    }
                    else if (typeof propertyValue != 'function') {
                        for (var k in propertyValue) {
                            if (propertyValue.hasOwnProperty(k)) {
                                value = propertyValue[k];

                                if (typeof value == 'string') {
                                    data[propertyName][k] = Manager.get(value);
                                }
                            }
                        }
                    }
                }
            }

            continueFn.call(me, cls, data, hooks);
        });

        return false;
    }, true, 'after', 'className');

    
    Manager.registerPostprocessor('uses', function(name, cls, data) {
        
        var uses = data.uses;
        if (uses) {
            Loader.addUsedClasses(uses);
        }
    });

    Manager.onCreated(Loader.historyPush);
};



if (Ext._classPathMetadata) {
    Ext.Loader.addClassPathMappings(Ext._classPathMetadata);
    Ext._classPathMetadata = null;
}


(function() {
    var scripts = document.getElementsByTagName('script'),
        currentScript = scripts[scripts.length - 1],
        src = currentScript.src,
        path = src.substring(0, src.lastIndexOf('/') + 1),
        Loader = Ext.Loader;


    Loader.setConfig({
        enabled: true,
        disableCaching:
            true,
        paths: {
            'Ext': path + 'src'
        }
    });
})();



Ext._endTime = new Date().getTime();
if (Ext._beforereadyhandler){
    Ext._beforereadyhandler();
}






Ext.Error = Ext.extend(Error, {
    statics: {
        
        ignore: false,

        
        

        
        raise: function(err){
            err = err || {};
            if (Ext.isString(err)) {
                err = { msg: err };
            }

            var method = this.raise.caller,
                msg;

            if (method) {
                if (method.$name) {
                    err.sourceMethod = method.$name;
                }
                if (method.$owner) {
                    err.sourceClass = method.$owner.$className;
                }
            }

            if (Ext.Error.handle(err) !== true) {
                msg = Ext.Error.prototype.toString.call(err);

                Ext.log({
                    msg: msg,
                    level: 'error',
                    dump: err,
                    stack: true
                });

                throw new Ext.Error(err);
            }
        },

        
        handle: function(){
            return Ext.Error.ignore;
        }
    },

    
    name: 'Ext.Error',

    
    constructor: function(config){
        if (Ext.isString(config)) {
            config = { msg: config };
        }

        var me = this;

        Ext.apply(me, config);

        me.message = me.message || me.msg; 
        
    },

    
    toString: function(){
        var me = this,
            className = me.sourceClass ? me.sourceClass : '',
            methodName = me.sourceMethod ? '.' + me.sourceMethod + '(): ' : '',
            msg = me.msg || '(No description provided)';

        return className + methodName + msg;
    }
});


Ext.deprecated = function (suggestion) {
    return Ext.emptyFn;
};








Ext.JSON = (new(function() {
    var me = this,
    encodingFunction,
    decodingFunction,
    useNative = null,
    useHasOwn = !! {}.hasOwnProperty,
    isNative = function() {
        if (useNative === null) {
            useNative = Ext.USE_NATIVE_JSON && window.JSON && JSON.toString() == '[object JSON]';
        }
        return useNative;
    },
    pad = function(n) {
        return n < 10 ? "0" + n : n;
    },
    doDecode = function(json) {
        return eval("(" + json + ')');
    },
    doEncode = function(o, newline) {
        
        if (o === null || o === undefined) {
            return "null";
        } else if (Ext.isDate(o)) {
            return Ext.JSON.encodeDate(o);
        } else if (Ext.isString(o)) {
            return Ext.JSON.encodeString(o);
        } else if (typeof o == "number") {
            
            return isFinite(o) ? String(o) : "null";
        } else if (Ext.isBoolean(o)) {
            return String(o);
        }
        
        
        else if (o.toJSON) {
            return o.toJSON();
        } else if (Ext.isArray(o)) {
            return encodeArray(o, newline);
        } else if (Ext.isObject(o)) {
            return encodeObject(o, newline);
        } else if (typeof o === "function") {
            return "null";
        }
        return 'undefined';
    },
    m = {
        "\b": '\\b',
        "\t": '\\t',
        "\n": '\\n',
        "\f": '\\f',
        "\r": '\\r',
        '"': '\\"',
        "\\": '\\\\',
        '\x0b': '\\u000b' 
    },
    charToReplace = /[\\\"\x00-\x1f\x7f-\uffff]/g,
    encodeString = function(s) {
        return '"' + s.replace(charToReplace, function(a) {
            var c = m[a];
            return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        }) + '"';
    },


    encodeArray = function(o, newline) {

        var a = ["[", ""], 
            len = o.length,
            i;
        for (i = 0; i < len; i += 1) {
            a.push(Ext.JSON.encodeValue(o[i]), ',');
        }
        
        a[a.length - 1] = ']';
        return a.join("");
    },

    encodeObject = function(o, newline) {

        var a = ["{", ""], 
            i, val;
        for (i in o) {
            val = o[i];
            if (!useHasOwn || o.hasOwnProperty(i)) {
                
                if (typeof val === 'function' || val === undefined) {
                    continue;
                }
                a.push(Ext.JSON.encodeValue(i), ":", Ext.JSON.encodeValue(val), ',');
                
            }
        }
        
        a[a.length - 1] = '}';
        return a.join("");
    };
    
    
    me.encodeString = encodeString;

    
    me.encodeValue = doEncode;

    
    me.encodeDate = function(o) {
        return '"' + o.getFullYear() + "-"
        + pad(o.getMonth() + 1) + "-"
        + pad(o.getDate()) + "T"
        + pad(o.getHours()) + ":"
        + pad(o.getMinutes()) + ":"
        + pad(o.getSeconds()) + '"';
    };

    
    me.encode = function(o) {
        if (!encodingFunction) {
            
            encodingFunction = isNative() ? JSON.stringify : me.encodeValue;
        }
        return encodingFunction(o);
    };

    
    me.decode = function(json, safe) {
        if (!decodingFunction) {
            
            decodingFunction = isNative() ? JSON.parse : doDecode;
        }
        try {
            return decodingFunction(json);
        } catch (e) {
            if (safe === true) {
                return null;
            }
            Ext.Error.raise({
                sourceClass: "Ext.JSON",
                sourceMethod: "decode",
                msg: "You're trying to decode an invalid JSON String: " + json
            });
        }
    };
})());

Ext.encode = Ext.JSON.encode;

Ext.decode = Ext.JSON.decode;






Ext.apply(Ext, {
    userAgent: navigator.userAgent.toLowerCase(),
    cache: {},
    idSeed: 1000,
    windowId: 'ext-window',
    documentId: 'ext-document',

    
    isReady: false,

    
    enableGarbageCollector: true,

    
    enableListenerCollection: true,

    
    rootHierarchyState: {},

    addCacheEntry: function(id, el, dom) {
        dom = dom || el.dom;


        var cache = Ext.cache,
            key = id || (el && el.id) || dom.id,
            entry = cache[key] || (cache[key] = {
                data: {},
                events: {},

                dom: dom,

                
                skipGarbageCollection: !!(dom.getElementById || dom.navigator)
            });

        if (el) {
            el.$cache = entry;
            
            
            entry.el = el;
        }

        return entry;
    },

    updateCacheEntry: function(cacheItem, dom){
        cacheItem.dom = dom;
        if (cacheItem.el) {
            cacheItem.el.dom = dom;
        }
        return cacheItem;
    },

    
    id: function(el, prefix) {
        var me = this,
            sandboxPrefix = '';
        el = Ext.getDom(el, true) || {};
        if (el === document) {
            el.id = me.documentId;
        }
        else if (el === window) {
            el.id = me.windowId;
        }
        if (!el.id) {
            if (me.isSandboxed) {
                sandboxPrefix = Ext.sandboxName.toLowerCase() + '-';
            }
            el.id = sandboxPrefix + (prefix || "ext-gen") + (++Ext.idSeed);
        }
        return el.id;
    },

    escapeId: (function(){
        var validIdRe = /^[a-zA-Z_][a-zA-Z0-9_\-]*$/i,
            escapeRx = /([\W]{1})/g,
            leadingNumRx = /^(\d)/g,
            escapeFn = function(match, capture){
                return "\\" + capture;
            },
            numEscapeFn = function(match, capture){
                return '\\00' + capture.charCodeAt(0).toString(16) + ' ';
            };

        return function(id) {
            return validIdRe.test(id)
                ? id
                
                
                : id.replace(escapeRx, escapeFn)
                    .replace(leadingNumRx, numEscapeFn);
        };
    }()),

    
    getBody: (function() {
        var body;
        return function() {
            return body || (body = Ext.get(document.body));
        };
    }()),

    
    getHead: (function() {
        var head;
        return function() {
            return head || (head = Ext.get(document.getElementsByTagName("head")[0]));
        };
    }()),

    
    getDoc: (function() {
        var doc;
        return function() {
            return doc || (doc = Ext.get(document));
        };
    }()),

    
    getOrientation: function() {
        return window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
    },

    
    destroy: function() {
        var ln = arguments.length,
        i, arg;

        for (i = 0; i < ln; i++) {
            arg = arguments[i];
            if (arg) {
                if (Ext.isArray(arg)) {
                    this.destroy.apply(this, arg);
                } else if (arg.isStore) {
                    arg.destroyStore();
                } else if (Ext.isFunction(arg.destroy)) {
                    arg.destroy();
                } else if (arg.dom) {
                    arg.remove();
                }
            }
        }
    },

    
    callback: function (callback, scope, args, delay) {
        var fn, ret;

        if (Ext.isFunction(callback)){
            fn = callback;
        } else if (scope && Ext.isString(callback)) {
            fn = scope[callback];
        }

        if (fn) {
            args = args || [];
            scope = scope || window;
            if (delay) {
                Ext.defer(fn, delay, scope, args);
            } else {
                ret = fn.apply(scope, args);
            }
        }

        return ret;
    },

    
    resolveMethod: function(fn, scope) {
        if (Ext.isFunction(fn)) {
            return fn;
        }


        return scope[fn];
    },

    
    htmlEncode : function(value) {
        return Ext.String.htmlEncode(value);
    },

    
    htmlDecode : function(value) {
         return Ext.String.htmlDecode(value);
    },

    
    urlAppend : function(url, s) {
        return Ext.String.urlAppend(url, s);
    }
});


Ext.ns = Ext.namespace;


window.undefined = window.undefined;


(function(){

    var check = function(regex){
            return regex.test(Ext.userAgent);
        },
        isStrict = document.compatMode == "CSS1Compat",
        version = function (is, regex) {
            var m;
            return (is && (m = regex.exec(Ext.userAgent))) ? parseFloat(m[1]) : 0;
        },
        docMode = document.documentMode,
        isOpera = check(/opera/),
        isOpera10_5 = isOpera && check(/version\/10\.5/),
        isChrome = check(/\bchrome\b/),
        isWebKit = check(/webkit/),
        isSafari = !isChrome && check(/safari/),
        isSafari2 = isSafari && check(/applewebkit\/4/), 
        isSafari3 = isSafari && check(/version\/3/),
        isSafari4 = isSafari && check(/version\/4/),
        isSafari5_0 = isSafari && check(/version\/5\.0/),
        isSafari5 = isSafari && check(/version\/5/),
        isIE = !isOpera && (check(/msie/) || check(/trident/)),
        isIE7 = isIE && ((check(/msie 7/) && docMode != 8 && docMode != 9 && docMode != 10) || docMode == 7),
        isIE8 = isIE && ((check(/msie 8/) && docMode != 7 && docMode != 9 && docMode != 10) || docMode == 8),
        isIE9 = isIE && ((check(/msie 9/) && docMode != 7 && docMode != 8 && docMode != 10) || docMode == 9),
        isIE10 = isIE && ((check(/msie 10/) && docMode != 7 && docMode != 8 && docMode != 9) || docMode == 10),
        isIE11 = isIE && ((check(/trident\/7\.0/) && docMode != 7 && docMode != 8 && docMode != 9 && docMode != 10) || docMode == 11),
        isIE6 = isIE && check(/msie 6/),
        isGecko = !isWebKit && !isIE && check(/gecko/), 
        isGecko3 = isGecko && check(/rv:1\.9/),
        isGecko4 = isGecko && check(/rv:2\.0/),
        isGecko5 = isGecko && check(/rv:5\./),
        isGecko10 = isGecko && check(/rv:10\./),
        isFF3_0 = isGecko3 && check(/rv:1\.9\.0/),
        isFF3_5 = isGecko3 && check(/rv:1\.9\.1/),
        isFF3_6 = isGecko3 && check(/rv:1\.9\.2/),
        isWindows = check(/windows|win32/),
        isMac = check(/macintosh|mac os x/),
        isLinux = check(/linux/),
        scrollbarSize = null,
        chromeVersion = version(true, /\bchrome\/(\d+\.\d+)/),
        firefoxVersion = version(true, /\bfirefox\/(\d+\.\d+)/),
        ieVersion = version(isIE, /msie (\d+\.\d+)/),
        operaVersion = version(isOpera, /version\/(\d+\.\d+)/),
        safariVersion = version(isSafari, /version\/(\d+\.\d+)/),
        webKitVersion = version(isWebKit, /webkit\/(\d+\.\d+)/),
        isSecure = /^https/i.test(window.location.protocol),
        nullLog;
        
    
    try {
        document.execCommand("BackgroundImageCache", false, true);
    } catch(e) {}



    nullLog = function () {};
    nullLog.info = nullLog.warn = nullLog.error = Ext.emptyFn;

    
    Ext.setVersion('ext', '4.2.2.1144');
    Ext.setVersion('extjs', '4.2.2.1144');
    Ext.apply(Ext, {
        
        SSL_SECURE_URL : isSecure && isIE ? 'javascript:\'\'' : 'about:blank',

        

        plainTableCls: Ext.buildSettings.baseCSSPrefix + 'table-plain',

        plainListCls: Ext.buildSettings.baseCSSPrefix + 'list-plain',

        
        enableNestedListenerRemoval : false,

        
        USE_NATIVE_JSON : false,

        
        getDom : function(el, strict) {
            if (!el || !document) {
                return null;
            }
            if (el.dom) {
                return el.dom;
            } else {
                if (typeof el == 'string') {
                    var e = Ext.getElementById(el);
                    
                    
                    if (e && isIE && strict) {
                        if (el == e.getAttribute('id')) {
                            return e;
                        } else {
                            return null;
                        }
                    }
                    return e;
                } else {
                    return el;
                }
            }
        },

        
        removeNode : isIE6 || isIE7 || isIE8
            ? (function() {
                var d;
                return function(n){
                    if(n && n.tagName.toUpperCase() != 'BODY'){
                        (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);

                        var cache = Ext.cache,
                            id = n.id;

                        if (cache[id]) {
                            delete cache[id].dom;
                            delete cache[id];
                        }

                        if (isIE8 && n.parentNode) {
                            n.parentNode.removeChild(n);
                        }
                        d = d || document.createElement('div');
                        d.appendChild(n);
                        d.innerHTML = '';
                    }
                };
            }())
            : function(n) {
                if (n && n.parentNode && n.tagName.toUpperCase() != 'BODY') {
                    (Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);

                    var cache = Ext.cache,
                        id = n.id;

                    if (cache[id]) {
                        delete cache[id].dom;
                        delete cache[id];
                    }

                    n.parentNode.removeChild(n);
                }
            },

        isStrict: isStrict,

        
        isIEQuirks: isIE && (!isStrict && (isIE6 || isIE7 || isIE8 || isIE9)),

        
        isOpera : isOpera,

        
        isOpera10_5 : isOpera10_5,

        
        isWebKit : isWebKit,

        
        isChrome : isChrome,

        
        isSafari : isSafari,

        
        isSafari3 : isSafari3,

        
        isSafari4 : isSafari4,

        
        isSafari5 : isSafari5,

        
        isSafari5_0 : isSafari5_0,


        
        isSafari2 : isSafari2,

        
        isIE : isIE,

        
        isIE6 : isIE6,

        
        isIE7 : isIE7,

        
        isIE7m : isIE6 || isIE7,

        
        isIE7p : isIE && !isIE6,

        
        isIE8 : isIE8,

        
        isIE8m : isIE6 || isIE7 || isIE8,

        
        isIE8p : isIE && !(isIE6 || isIE7),

        
        isIE9 : isIE9,

        
        isIE9m : isIE6 || isIE7 || isIE8 || isIE9,

        
        isIE9p : isIE && !(isIE6 || isIE7 || isIE8),

        
        isIE10 : isIE10,

        
        isIE10m : isIE6 || isIE7 || isIE8 || isIE9 || isIE10,

        
        isIE10p : isIE && !(isIE6 || isIE7 || isIE8 || isIE9),
        
        
        isIE11: isIE11, 
        
        
        isIE11m : isIE6 || isIE7 || isIE8 || isIE9 || isIE10 || isIE11,
 
        
        isIE11p : isIE && !(isIE6 || isIE7 || isIE8 || isIE9 || isIE10),

        
        isGecko : isGecko,

        
        isGecko3 : isGecko3,

        
        isGecko4 : isGecko4,

        
        isGecko5 : isGecko5,

        
        isGecko10 : isGecko10,

        
        isFF3_0 : isFF3_0,

        
        isFF3_5 : isFF3_5,

        
        isFF3_6 : isFF3_6,

        
        isFF4 : 4 <= firefoxVersion && firefoxVersion < 5,

        
        isFF5 : 5 <= firefoxVersion && firefoxVersion < 6,

        
        isFF10 : 10 <= firefoxVersion && firefoxVersion < 11,

        
        isLinux : isLinux,

        
        isWindows : isWindows,

        
        isMac : isMac,

        
        chromeVersion: chromeVersion,

        
        firefoxVersion: firefoxVersion,

        
        ieVersion: ieVersion,

        
        operaVersion: operaVersion,

        
        safariVersion: safariVersion,

        
        webKitVersion: webKitVersion,

        
        isSecure: isSecure,

        
        BLANK_IMAGE_URL : (isIE6 || isIE7) ? '/' + '/www.sencha.com/s.gif' : 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',

        
        value : function(v, defaultValue, allowBlank){
            return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
        },

        
        escapeRe : function(s) {
            return s.replace(/([-.*+?\^${}()|\[\]\/\\])/g, "\\$1");
        },

        
        addBehaviors : function(o){
            if(!Ext.isReady){
                Ext.onReady(function(){
                    Ext.addBehaviors(o);
                });
            } else {
                var cache = {}, 
                    parts,
                    b,
                    s;
                for (b in o) {
                    if ((parts = b.split('@'))[1]) { 
                        s = parts[0];
                        if(!cache[s]){
                            cache[s] = Ext.select(s);
                        }
                        cache[s].on(parts[1], o[b]);
                    }
                }
                cache = null;
            }
        },

        
        getScrollbarSize: function (force) {
            if (!Ext.isReady) {
                return {};
            }

            if (force || !scrollbarSize) {
                var db = document.body,
                    div = document.createElement('div');

                div.style.width = div.style.height = '100px';
                div.style.overflow = 'scroll';
                div.style.position = 'absolute';

                db.appendChild(div); 

                
                scrollbarSize = {
                    width: div.offsetWidth - div.clientWidth,
                    height: div.offsetHeight - div.clientHeight
                };

                db.removeChild(div);
            }

            return scrollbarSize;
        },

        
        getScrollBarWidth: function(force){
            var size = Ext.getScrollbarSize(force);
            return size.width + 2; 
        },

        
        copyTo : function(dest, source, names, usePrototypeKeys){
            if(typeof names == 'string'){
                names = names.split(/[,;\s]/);
            }

            var n,
                nLen = names? names.length : 0,
                name;

            for(n = 0; n < nLen; n++) {
                name = names[n];

                if(usePrototypeKeys || source.hasOwnProperty(name)){
                    dest[name] = source[name];
                }
            }

            return dest;
        },

        
        destroyMembers : function(o){
            for (var i = 1, a = arguments, len = a.length; i < len; i++) {
                Ext.destroy(o[a[i]]);
                delete o[a[i]];
            }
        },

        
        log :
            nullLog,

        
        partition : function(arr, truth){
            var ret = [[],[]],
                a, v,
                aLen = arr.length;

            for (a = 0; a < aLen; a++) {
                v = arr[a];
                ret[ (truth && truth(v, a, arr)) || (!truth && v) ? 0 : 1].push(v);
            }

            return ret;
        },

        
        invoke : function(arr, methodName){
            var ret  = [],
                args = Array.prototype.slice.call(arguments, 2),
                a, v,
                aLen = arr.length;

            for (a = 0; a < aLen; a++) {
                v = arr[a];

                if (v && typeof v[methodName] == 'function') {
                    ret.push(v[methodName].apply(v, args));
                } else {
                    ret.push(undefined);
                }
            }

            return ret;
        },

        
        zip : function(){
            var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
                arrs = parts[0],
                fn = parts[1][0],
                len = Ext.max(Ext.pluck(arrs, "length")),
                ret = [],
                i,
                j,
                aLen;

            for (i = 0; i < len; i++) {
                ret[i] = [];
                if(fn){
                    ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
                }else{
                    for (j = 0, aLen = arrs.length; j < aLen; j++){
                        ret[i].push( arrs[j][i] );
                    }
                }
            }
            return ret;
        },

        
        toSentence: function(items, connector) {
            var length = items.length,
                head,
                tail;

            if (length <= 1) {
                return items[0];
            } else {
                head = items.slice(0, length - 1);
                tail = items[length - 1];

                return Ext.util.Format.format("{0} {1} {2}", head.join(", "), connector || 'and', tail);
            }
        },

        
        setGlyphFontFamily: function(fontFamily) {
            Ext._glyphFontFamily = fontFamily;
        },

        
        useShims: isIE6
    });
}());


Ext.application = function(config) {
    var App, paths, ns,
        
        createApp = function() {
            Ext.onReady(function() {
                Ext.app.Application.instance = new App();
            });
        };

    if (typeof config === "string") {
        Ext.require(config, function() {
            App = Ext.ClassManager.get(config);
            createApp();
        });
    }
    else {
        
        
        Ext.Loader.setPath(config.name, config.appFolder || 'app');

        if (paths = config.paths) {
            for (ns in paths) {
                if (paths.hasOwnProperty(ns)) {
                    Ext.Loader.setPath(ns, paths[ns]);
                }
            }
        }

        config['paths processed'] = true;

        
        Ext.define(config.name + ".$application", Ext.apply({
            extend: 'Ext.app.Application' 
        }, config),
        
        function () {
            App = this;
            createApp();
        });
    }
};






(function() {
    Ext.ns('Ext.util');

    var UtilFormat     = Ext.util.Format = {},
        stripTagsRE    = /<\/?[^>]+>/gi,
        stripScriptsRe = /(?:)((\n|\r|.)*?)(?:<\/script>)/ig,
        nl2brRe        = /\r?\n/g,
        allHashes      = /^#+$/,

        
        formatPattern = /[\d,\.#]+/,

        
        formatCleanRe  = /[^\d\.#]/g,

        
        
        I18NFormatCleanRe,

        
        formatFns = {};

    Ext.apply(UtilFormat, {
        
        
        thousandSeparator: ',',
        

        
        
        decimalSeparator: '.',
        

        
        
        currencyPrecision: 2,
        

         
        
        currencySign: '$',
        

        
        
        currencyAtEnd: false,
        

        
        undef : function(value) {
            return value !== undefined ? value : "";
        },

        
        defaultValue : function(value, defaultValue) {
            return value !== undefined && value !== '' ? value : defaultValue;
        },

        
        substr : 'ab'.substr(-1) != 'b'
        ? function (value, start, length) {
            var str = String(value);
            return (start < 0)
                ? str.substr(Math.max(str.length + start, 0), length)
                : str.substr(start, length);
        }
        : function(value, start, length) {
            return String(value).substr(start, length);
        },

        
        lowercase : function(value) {
            return String(value).toLowerCase();
        },

        
        uppercase : function(value) {
            return String(value).toUpperCase();
        },

        
        usMoney : function(v) {
            return UtilFormat.currency(v, '$', 2);
        },

        
        currency: function(v, currencySign, decimals, end) {
            var negativeSign = '',
                format = ",0",
                i = 0;
            v = v - 0;
            if (v < 0) {
                v = -v;
                negativeSign = '-';
            }
            decimals = Ext.isDefined(decimals) ? decimals : UtilFormat.currencyPrecision;
            format += (decimals > 0 ? '.' : '');
            for (; i < decimals; i++) {
                format += '0';
            }
            v = UtilFormat.number(v, format);
            if ((end || UtilFormat.currencyAtEnd) === true) {
                return Ext.String.format("{0}{1}{2}", negativeSign, v, currencySign || UtilFormat.currencySign);
            } else {
                return Ext.String.format("{0}{1}{2}", negativeSign, currencySign || UtilFormat.currencySign, v);
            }
        },

        
        date: function(v, format) {
            if (!v) {
                return "";
            }
            if (!Ext.isDate(v)) {
                v = new Date(Date.parse(v));
            }
            return Ext.Date.dateFormat(v, format || Ext.Date.defaultFormat);
        },

        
        dateRenderer : function(format) {
            return function(v) {
                return UtilFormat.date(v, format);
            };
        },

        
        stripTags : function(v) {
            return !v ? v : String(v).replace(stripTagsRE, "");
        },

        
        stripScripts : function(v) {
            return !v ? v : String(v).replace(stripScriptsRe, "");
        },

        
        fileSize : (function(){
            var byteLimit = 1024,
                kbLimit = 1048576,
                mbLimit = 1073741824;
                
            return function(size) {
                var out;
                if (size < byteLimit) {
                    if (size === 1) {
                        out = '1 byte';    
                    } else {
                        out = size + ' bytes';
                    }
                } else if (size < kbLimit) {
                    out = (Math.round(((size*10) / byteLimit))/10) + ' KB';
                } else if (size < mbLimit) {
                    out = (Math.round(((size*10) / kbLimit))/10) + ' MB';
                } else {
                    out = (Math.round(((size*10) / mbLimit))/10) + ' GB';
                }
                return out;
            };
        })(),

        
        math : (function(){
            var fns = {};

            return function(v, a){
                if (!fns[a]) {
                    fns[a] = Ext.functionFactory('v', 'return v ' + a + ';');
                }
                return fns[a](v);
            };
        }()),

        
        round : function(value, precision) {
            var result = Number(value);
            if (typeof precision == 'number') {
                precision = Math.pow(10, precision);
                result = Math.round(value * precision) / precision;
            }
            return result;
        },

        
        number : function(v, formatString) {
            if (!formatString) {
                return v;
            }
            var formatFn = formatFns[formatString];

            
            
            if (!formatFn) {

                var originalFormatString = formatString,
                    comma = UtilFormat.thousandSeparator,
                    decimalSeparator = UtilFormat.decimalSeparator,
                    precision = 0,
                    trimPart = '',
                    hasComma,
                    splitFormat,
                    extraChars,
                    multiplier,
                    trimTrailingZeroes,
                    code;

                
                
                
                
                if (formatString.substr(formatString.length - 2) == '/i') {
                    if (!I18NFormatCleanRe) {
                        I18NFormatCleanRe = new RegExp('[^\\d\\' + UtilFormat.decimalSeparator + ']','g');
                    }
                    formatString = formatString.substr(0, formatString.length - 2);
                    hasComma = formatString.indexOf(comma) != -1;
                    splitFormat = formatString.replace(I18NFormatCleanRe, '').split(decimalSeparator);
                } else {
                    hasComma = formatString.indexOf(',') != -1;
                    splitFormat = formatString.replace(formatCleanRe, '').split('.');
                }
                extraChars = formatString.replace(formatPattern, '');

                if (splitFormat.length > 2) {
                } else if (splitFormat.length === 2) {
                    precision = splitFormat[1].length;

                    
                    trimTrailingZeroes = allHashes.test(splitFormat[1]);
                    if (trimTrailingZeroes) {
                        
                        trimPart = 'trailingZeroes=new RegExp(Ext.String.escapeRegex(utilFormat.decimalSeparator) + "?0+$")'
                    }
                }
                
                
                code = [
                    'var utilFormat=Ext.util.Format,extNumber=Ext.Number,neg,absVal,fnum,parts' +
                        (hasComma ? ',thousandSeparator,thousands=[],j,n,i' : '') +
                        (extraChars  ? ',formatString="' + formatString + '",formatPattern=/[\\d,\\.#]+/' : '') +
                        ',trailingZeroes;' +
                    'return function(v){' +
                    'if(typeof v!=="number"&&isNaN(v=extNumber.from(v,NaN)))return"";' +
                    'neg=v<0;',
                    'absVal=Math.abs(v);',
                    'fnum=Ext.Number.toFixed(absVal, ' + precision + ');',
                    trimPart, ';'
                ];

                if (hasComma) {
                    
                    
                    
                    if (precision) {
                        code[code.length] = 'parts=fnum.split(".");';
                        code[code.length] = 'fnum=parts[0];';
                    }
                    code[code.length] =
                        'if(absVal>=1000) {';
                            code[code.length] = 'thousandSeparator=utilFormat.thousandSeparator;' +
                            'thousands.length=0;' +
                            'j=fnum.length;' +
                            'n=fnum.length%3||3;' +
                            'for(i=0;i');
        },

        
        capitalize: Ext.String.capitalize,

        
        ellipsis: Ext.String.ellipsis,

        
        format: Ext.String.format,

        
        htmlDecode: Ext.String.htmlDecode,

        
        htmlEncode: Ext.String.htmlEncode,

        
        leftPad: Ext.String.leftPad,

        
        trim : Ext.String.trim,

        
        parseBox : function(box) {
            box = box || 0;

            if (typeof box === 'number') {
                return {
                    top   : box,
                    right : box,
                    bottom: box,
                    left  : box
                };
             }

            var parts  = box.split(' '),
                ln = parts.length;

            if (ln == 1) {
                parts[1] = parts[2] = parts[3] = parts[0];
            }
            else if (ln == 2) {
                parts[2] = parts[0];
                parts[3] = parts[1];
            }
            else if (ln == 3) {
                parts[3] = parts[1];
            }

            return {
                top   :parseInt(parts[0], 10) || 0,
                right :parseInt(parts[1], 10) || 0,
                bottom:parseInt(parts[2], 10) || 0,
                left  :parseInt(parts[3], 10) || 0
            };
        },

        
        escapeRegex : function(s) {
            return s.replace(/([\-.*+?\^${}()|\[\]\/\\])/g, "\\$1");
        }
    });
}());





Ext.define('Ext.util.TaskRunner', {
    

    
    interval: 10,

    
    timerId: null,

    constructor: function (interval) {
        var me = this;

        if (typeof interval == 'number') {
            me.interval = interval;
        } else if (interval) {
            Ext.apply(me, interval);
        }

        me.tasks = [];
        me.timerFn = Ext.Function.bind(me.onTick, me);
    },

    
    newTask: function (config) {
        var task = new Ext.util.TaskRunner.Task(config);
        task.manager = this;
        return task;
    },

    
    start: function(task) {
        var me = this,
            now = Ext.Date.now();

        if (!task.pending) {
            me.tasks.push(task);
            task.pending = true; 
        }

        task.stopped = false; 
        task.taskStartTime = now;
        task.taskRunTime = task.fireOnStart !== false ? 0 : task.taskStartTime;
        task.taskRunCount = 0;

        if (!me.firing) {
            if (task.fireOnStart !== false) {
                me.startTimer(0, now);
            } else {
                me.startTimer(task.interval, now);
            }
        }

        return task;
    },

    
    stop: function(task) {
        
        
        
        if (!task.stopped) {
            task.stopped = true;

            if (task.onStop) {
                task.onStop.call(task.scope || task, task);
            }
        }

        return task;
    },

    
    stopAll: function() {
        
        Ext.each(this.tasks, this.stop, this);
    },

    

    firing: false,

    nextExpires: 1e99,

    
    onTick: function () {
        var me = this,
            tasks = me.tasks,
            now = Ext.Date.now(),
            nextExpires = 1e99,
            len = tasks.length,
            expires, newTasks, i, task, rt, remove;

        me.timerId = null;
        me.firing = true; 

        
        
        
        
        for (i = 0; i < len || i < (len = tasks.length); ++i) {
            task = tasks[i];

            if (!(remove = task.stopped)) {
                expires = task.taskRunTime + task.interval;

                if (expires <= now) {
                    rt = 1; 
                    try {
                        rt = task.run.apply(task.scope || task, task.args || [++task.taskRunCount]);
                    } catch (taskError) {
                        try {
                            if (task.onError) {
                                rt = task.onError.call(task.scope || task, task, taskError);
                            }
                        } catch (ignore) { }
                        }
                    task.taskRunTime = now;
                    if (rt === false || task.taskRunCount === task.repeat) {
                        me.stop(task);
                        remove = true;
                    } else {
                        remove = task.stopped; 
                        expires = now + task.interval;
                    }
                }

                if (!remove && task.duration && task.duration <= (now - task.taskStartTime)) {
                    me.stop(task);
                    remove = true;
                }
            }

            if (remove) {
                task.pending = false; 

                
                
                
                
                
                if (!newTasks) {
                    newTasks = tasks.slice(0, i);
                    
                    
                    
                }
            } else {
                if (newTasks) {
                    newTasks.push(task); 
                }

                if (nextExpires > expires) {
                    nextExpires = expires; 
                }
            }
        }

        if (newTasks) {
            
            
            me.tasks = newTasks;
        }

        me.firing = false; 

        if (me.tasks.length) {
            
            
            
            me.startTimer(nextExpires - now, Ext.Date.now());
        }
        
        
        if (me.fireIdleEvent !== false) {
            Ext.EventManager.idleEvent.fire();
        }
   },

    
    startTimer: function (timeout, now) {
        var me = this,
            expires = now + timeout,
            timerId = me.timerId;

        
        
        if (timerId && me.nextExpires - expires > me.interval) {
            clearTimeout(timerId);
            timerId = null;
        }

        if (!timerId) {
            if (timeout < me.interval) {
                timeout = me.interval;
            }

            me.timerId = setTimeout(me.timerFn, timeout);
            me.nextExpires = expires;
        }
    }
},
function () {
    var me = this,
        proto = me.prototype;

    
    proto.destroy = proto.stopAll;

    
    Ext.util.TaskManager = Ext.TaskManager = new me();

    
    me.Task = new Ext.Class({
        isTask: true,

        
        stopped: true, 

        
        fireOnStart: false,

        constructor: function (config) {
            Ext.apply(this, config);
        },

        
        restart: function (interval) {
            if (interval !== undefined) {
                this.interval = interval;
            }

            this.manager.start(this);
        },

        
        start: function (interval) {
            if (this.stopped) {
                this.restart(interval);
            }
        },

        
        stop: function () {
            this.manager.stop(this);
        }
    });

    proto = me.Task.prototype;

    
    proto.destroy = proto.stop;
});












Ext.define('Ext.util.TaskManager', {
    extend:  Ext.util.TaskRunner ,

    alternateClassName: [
        'Ext.TaskManager'
    ],

    singleton: true
});





Ext.define('Ext.perf.Accumulator', (function () {
    var currentFrame = null,
        khrome = Ext.global['chrome'],
        formatTpl,
        
        
        getTimestamp = function () {

            getTimestamp = function () {
                return new Date().getTime();
            };
            
            var interval, toolbox;

            
            if (Ext.isChrome && khrome && khrome.Interval) {
                interval = new khrome.Interval();
                interval.start();
                getTimestamp = function () {
                    return interval.microseconds() / 1000;
                };
            } else if (window.ActiveXObject) {
                try {
                    
                    toolbox = new ActiveXObject('SenchaToolbox.Toolbox');
                    Ext.senchaToolbox = toolbox; 
                    getTimestamp = function () {
                        return toolbox.milliseconds;
                    };
                } catch (e) {
                    
                }
            } else if (Date.now) {
                getTimestamp = Date.now;
            }

            Ext.perf.getTimestamp = Ext.perf.Accumulator.getTimestamp = getTimestamp;
            return getTimestamp();
        };

    function adjustSet (set, time) {
        set.sum += time;
        set.min = Math.min(set.min, time);
        set.max = Math.max(set.max, time);
    }

    function leaveFrame (time) {
        var totalTime = time ? time : (getTimestamp() - this.time), 
            me = this, 
            accum = me.accum;

        ++accum.count;
        if (! --accum.depth) {
            adjustSet(accum.total, totalTime);
        }
        adjustSet(accum.pure, totalTime - me.childTime);

        currentFrame = me.parent;
        if (currentFrame) {
            ++currentFrame.accum.childCount;
            currentFrame.childTime += totalTime;
        }
    }

    function makeSet () {
        return {
            min: Number.MAX_VALUE,
            max: 0,
            sum: 0
        };
    }

    function makeTap (me, fn) {
        return function () {
            var frame = me.enter(),
                ret = fn.apply(this, arguments);

            frame.leave();
            return ret;
        };
    }

    function round (x) {
        return Math.round(x * 100) / 100;
    }

    function setToJSON (count, childCount, calibration, set) {
        var data = {
            avg: 0,
            min: set.min,
            max: set.max,
            sum: 0
        };

        if (count) {
            calibration = calibration || 0;
            data.sum = set.sum - childCount * calibration;
            data.avg = data.sum / count;
            
            
        }

        return data;
    }

    return {
        constructor: function (name) {
            var me = this;

            me.count = me.childCount = me.depth = me.maxDepth = 0;
            me.pure = makeSet();
            me.total = makeSet();
            me.name = name;
        },

        statics: {
            getTimestamp: getTimestamp
        },

        format: function (calibration) {
            if (!formatTpl) {
                formatTpl = new Ext.XTemplate([
                        '{name} - {count} call(s)',
                        '',
                            '',
                                ' ({childCount} children)',
                            '',
                            '',
                                ' ({depth} deep)',
                            '',
                            '',
                                ', {type}: {[this.time(values.sum)]} msec (',
                                     
                                     'avg={[this.time(values.sum / parent.count)]}',
                                     
                                     ')',
                            '',
                        ''
                    ].join(''), {
                        time: function (t) {
                            return Math.round(t * 100) / 100;
                        }
                    });
            }

            var data = this.getData(calibration);
            data.name = this.name;
            data.pure.type = 'Pure';
            data.total.type = 'Total';
            data.times = [data.pure, data.total];
            return formatTpl.apply(data);
        },

        getData: function (calibration) {
            var me = this;

            return {
                count: me.count,
                childCount: me.childCount,
                depth: me.maxDepth,
                pure: setToJSON(me.count, me.childCount, calibration, me.pure),
                total: setToJSON(me.count, me.childCount, calibration, me.total)
            };
        },

        enter: function () {
            var me = this,
                frame = {
                    accum: me,
                    leave: leaveFrame,
                    childTime: 0,
                    parent: currentFrame
                };

            ++me.depth;
            if (me.maxDepth < me.depth) {
                me.maxDepth = me.depth;
            }

            currentFrame = frame;
            frame.time = getTimestamp(); 
            return frame;
        },

        monitor: function (fn, scope, args) {
            var frame = this.enter();
            if (args) {
                fn.apply(scope, args);
            } else {
                fn.call(scope);
            }
            frame.leave();
        },

        report: function () {
            Ext.log(this.format());
        },

        tap: function (className, methodName) {
            var me = this,
                methods = typeof methodName == 'string' ? [methodName] : methodName,
                klass, statik, i, parts, length, name, src,
                tapFunc;

            tapFunc = function(){
                if (typeof className == 'string') {
                    klass = Ext.global;
                    parts = className.split('.');
                    for (i = 0, length = parts.length; i < length; ++i) {
                        klass = klass[parts[i]];
                    }
                } else {
                    klass = className;
                }

                for (i = 0, length = methods.length; i < length; ++i) {
                    name = methods[i];
                    statik = name.charAt(0) == '!';

                    if (statik) {
                        name = name.substring(1);
                    } else {
                        statik = !(name in klass.prototype);
                    }

                    src = statik ? klass : klass.prototype;
                    src[name] = makeTap(me, src[name]);
                }
            };

            Ext.ClassManager.onCreated(tapFunc, me, className);

            return me;
        }
    };
}()),

function () {
    Ext.perf.getTimestamp = this.getTimestamp;
});





Ext.define('Ext.perf.Monitor', {
    singleton: true,
    alternateClassName: 'Ext.Perf',

               
                              
      

    constructor: function () {
        this.accumulators = [];
        this.accumulatorsByName = {};
    },

    calibrate: function () {
        var accum = new Ext.perf.Accumulator('$'),
            total = accum.total,
            getTimestamp = Ext.perf.Accumulator.getTimestamp,
            count = 0,
            frame,
            endTime,
            startTime;

        startTime = getTimestamp();

        do {
            frame = accum.enter();
            frame.leave();
            ++count;
        } while (total.sum < 100);

        endTime = getTimestamp();

        return (endTime - startTime) / count;
    },

    get: function (name) {
        var me = this,
            accum = me.accumulatorsByName[name];

        if (!accum) {
            me.accumulatorsByName[name] = accum = new Ext.perf.Accumulator(name);
            me.accumulators.push(accum);
        }

        return accum;
    },

    enter: function (name) {
        return this.get(name).enter();
    },

    monitor: function (name, fn, scope) {
        this.get(name).monitor(fn, scope);
    },

    report: function () {
        var me = this,
            accumulators = me.accumulators,
            calibration = me.calibrate();

        accumulators.sort(function (a, b) {
            return (a.name < b.name) ? -1 : ((b.name < a.name) ? 1 : 0);
        });

        me.updateGC();

        Ext.log('Calibration: ' + Math.round(calibration * 100) / 100 + ' msec/sample');
        Ext.each(accumulators, function (accum) {
            Ext.log(accum.format(calibration));
        });
    },

    getData: function (all) {
        var ret = {},
            accumulators = this.accumulators;

        Ext.each(accumulators, function (accum) {
            if (all || accum.count) {
                ret[accum.name] = accum.getData();
            }
        });

        return ret;
    },

    reset: function(){
        Ext.each(this.accumulators, function(accum){
            var me = accum;
            me.count = me.childCount = me.depth = me.maxDepth = 0;
            me.pure = {
                min: Number.MAX_VALUE,
                max: 0,
                sum: 0
            };
            me.total = {
                min: Number.MAX_VALUE,
                max: 0,
                sum: 0
            };
        });
    },

    updateGC: function () {
        var accumGC = this.accumulatorsByName.GC,
            toolbox = Ext.senchaToolbox,
            bucket;

        if (accumGC) {
            accumGC.count = toolbox.garbageCollectionCounter || 0;

            if (accumGC.count) {
                bucket = accumGC.pure;
                accumGC.total.sum = bucket.sum = toolbox.garbageCollectionMilliseconds;
                bucket.min = bucket.max = bucket.sum / accumGC.count;
                bucket = accumGC.total;
                bucket.min = bucket.max = bucket.sum / accumGC.count;
            }
        }
    },

    watchGC: function () {
        Ext.perf.getTimestamp(); 

        var toolbox = Ext.senchaToolbox;

        if (toolbox) {
            this.get("GC");
            toolbox.watchGarbageCollector(false); 
        }
    },

    setup: function (config) {
        if (!config) {
            config = {
                
                






                render: {
                    'Ext.AbstractComponent': 'render'
                },

































                layout: {
                    'Ext.layout.Context': 'run'
                }
            };
        }

        this.currentConfig = config;

        var key, prop,
            accum, className, methods;
        for (key in config) {
            if (config.hasOwnProperty(key)) {
                prop = config[key];
                accum = Ext.Perf.get(key);

                for (className in prop) {
                    if (prop.hasOwnProperty(className)) {
                        methods = prop[className];
                        accum.tap(className, methods);
                    }
                }
            }
        }

        this.watchGC();
    }
});






Ext.is = {
    init : function(navigator) {
        var platforms = this.platforms,
            ln = platforms.length,
            i, platform;

        navigator = navigator || window.navigator;

        for (i = 0; i < ln; i++) {
            platform = platforms[i];
            this[platform.identity] = platform.regex.test(navigator[platform.property]);
        }

        
        this.Desktop = this.Mac || this.Windows || (this.Linux && !this.Android);
        
        this.Tablet = this.iPad;
        
        this.Phone = !this.Desktop && !this.Tablet;
        
        this.iOS = this.iPhone || this.iPad || this.iPod;
        
        
        this.Standalone = !!window.navigator.standalone;
    },
    
    
    platforms: [{
        property: 'platform',
        regex: /iPhone/i,
        identity: 'iPhone'
    },
    
    
    {
        property: 'platform',
        regex: /iPod/i,
        identity: 'iPod'
    },
    
    
    {
        property: 'userAgent',
        regex: /iPad/i,
        identity: 'iPad'
    },
    
    
    {
        property: 'userAgent',
        regex: /Blackberry/i,
        identity: 'Blackberry'
    },
    
    
    {
        property: 'userAgent',
        regex: /Android/i,
        identity: 'Android'
    },
    
    
    {
        property: 'platform',
        regex: /Mac/i,
        identity: 'Mac'
    },
    
    
    {
        property: 'platform',
        regex: /Win/i,
        identity: 'Windows'
    },
    
    
    {
        property: 'platform',
        regex: /Linux/i,
        identity: 'Linux'
    }]
};

Ext.is.init();


(function(){

    
    
    
    var getStyle = function(element, styleName){
        var view = element.ownerDocument.defaultView,
            style = (view ? view.getComputedStyle(element, null) : element.currentStyle) || element.style;
        return style[styleName];
    },
    supportsVectors = {
        'IE6-quirks':  [0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,0],
        'IE6-strict':  [0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,1,1,0,0,1,0,1,0,0,0],
        'IE7-quirks':  [0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,0],
        'IE7-strict':  [0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,1,0,0,1,0,1,0,0,0],
        'IE8-quirks':  [0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,0],
        'IE8-strict':  [0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,1,0,0,1,0,1,0,0,1],
        'IE9-quirks':  [0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,0,0,0,1,0,0,1,0,0,1,0,1,0,0,0],
        'IE9-strict':  [0,1,0,0,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,0,0,0,0,1],
        'IE10-quirks': [1,1,0,0,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,1],
        'IE10-strict': [1,1,0,0,1,1,1,1,0,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,0,0,0,0,1]
    };

function getBrowserKey() {
    var browser = Ext.isIE6 ? 'IE6' : Ext.isIE7 ? 'IE7' : Ext.isIE8 ? 'IE8' :
        Ext.isIE9 ? 'IE9': Ext.isIE10 ? 'IE10' : '';

    return browser ? browser + (Ext.isStrict ? '-strict' : '-quirks') : '';
}

Ext.supports = {
    
    init : function() {
        var me = this,
            doc = document,
            toRun = me.toRun || me.tests,
            n = toRun.length,
            div = n && Ext.isReady && doc.createElement('div'),
            notRun = [],
            browserKey = getBrowserKey(),
            test, vector, value;

        if (div) {
            div.innerHTML = [
                '
', '
', '
', '
', '
', '
', '
', '
' ].join(''); doc.body.appendChild(div); } vector = supportsVectors[browserKey]; while (n--) { test = toRun[n]; value = vector && vector[n]; if (value !== undefined) { me[test.identity] = value; } else if (div || test.early) { me[test.identity] = test.fn.call(me, doc, div); } else { notRun.push(test); } } if (div) { doc.body.removeChild(div); } me.toRun = notRun; }, PointerEvents: 'pointerEvents' in document.documentElement.style, LocalStorage: (function() { try { return 'localStorage' in window && window['localStorage'] !== null; } catch (e) { return false; } })(), CSS3BoxShadow: 'boxShadow' in document.documentElement.style || 'WebkitBoxShadow' in document.documentElement.style || 'MozBoxShadow' in document.documentElement.style, ClassList: !!document.documentElement.classList, OrientationChange: ((typeof window.orientation != 'undefined') && ('onorientationchange' in window)), DeviceMotion: ('ondevicemotion' in window), Touch: ('ontouchstart' in window) && (!Ext.is.Desktop), TimeoutActualLateness: (function(){ setTimeout(function(){ Ext.supports.TimeoutActualLateness = arguments.length !== 0; }, 0); }()), tests: [ { identity: 'Transitions', fn: function(doc, div) { var prefix = [ 'webkit', 'Moz', 'o', 'ms', 'khtml' ], TE = 'TransitionEnd', transitionEndName = [ prefix[0] + TE, 'transitionend', prefix[2] + TE, prefix[3] + TE, prefix[4] + TE ], ln = prefix.length, i = 0, out = false; for (; i < ln; i++) { if (getStyle(div, prefix[i] + "TransitionProperty")) { Ext.supports.CSS3Prefix = prefix[i]; Ext.supports.CSS3TransitionEnd = transitionEndName[i]; out = true; break; } } return out; } }, { identity: 'RightMargin', fn: function(doc, div) { var view = doc.defaultView; return !(view && view.getComputedStyle(div.firstChild.firstChild, null).marginRight != '0px'); } }, { identity: 'DisplayChangeInputSelectionBug', early: true, fn: function() { var webKitVersion = Ext.webKitVersion; return 0 < webKitVersion && webKitVersion < 533; } }, { identity: 'DisplayChangeTextAreaSelectionBug', early: true, fn: function() { var webKitVersion = Ext.webKitVersion; return 0 < webKitVersion && webKitVersion < 534.24; } }, { identity: 'TransparentColor', fn: function(doc, div, view) { view = doc.defaultView; return !(view && view.getComputedStyle(div.lastChild, null).backgroundColor != 'transparent'); } }, { identity: 'ComputedStyle', fn: function(doc, div, view) { view = doc.defaultView; return view && view.getComputedStyle; } }, { identity: 'Svg', fn: function(doc) { return !!doc.createElementNS && !!doc.createElementNS( "http:/" + "/www.w3.org/2000/svg", "svg").createSVGRect; } }, { identity: 'Canvas', fn: function(doc) { return !!doc.createElement('canvas').getContext; } }, { identity: 'Vml', fn: function(doc) { var d = doc.createElement("div"); d.innerHTML = ""; return (d.childNodes.length == 2); } }, { identity: 'Float', fn: function(doc, div) { return !!div.lastChild.style.cssFloat; } }, { identity: 'AudioTag', fn: function(doc) { return !!doc.createElement('audio').canPlayType; } }, { identity: 'History', fn: function() { var history = window.history; return !!(history && history.pushState); } }, { identity: 'CSS3DTransform', fn: function() { return (typeof WebKitCSSMatrix != 'undefined' && new WebKitCSSMatrix().hasOwnProperty('m41')); } }, { identity: 'CSS3LinearGradient', fn: function(doc, div) { var property = 'background-image:', webkit = '-webkit-gradient(linear, left top, right bottom, from(black), to(white))', w3c = 'linear-gradient(left top, black, white)', moz = '-moz-' + w3c, ms = '-ms-' + w3c, opera = '-o-' + w3c, options = [property + webkit, property + w3c, property + moz, property + ms, property + opera]; div.style.cssText = options.join(';'); return (("" + div.style.backgroundImage).indexOf('gradient') !== -1) && !Ext.isIE9; } }, { identity: 'CSS3BorderRadius', fn: function(doc, div) { var domPrefixes = ['borderRadius', 'BorderRadius', 'MozBorderRadius', 'WebkitBorderRadius', 'OBorderRadius', 'KhtmlBorderRadius'], pass = false, i; for (i = 0; i < domPrefixes.length; i++) { if (document.body.style[domPrefixes[i]] !== undefined) { return true; } } return pass; } }, { identity: 'GeoLocation', fn: function() { return (typeof navigator != 'undefined' && 'geolocation' in navigator) || (typeof google != 'undefined' && typeof google.gears != 'undefined'); } }, { identity: 'MouseEnterLeave', fn: function(doc, div){ return ('onmouseenter' in div && 'onmouseleave' in div); } }, { identity: 'MouseWheel', fn: function(doc, div) { return ('onmousewheel' in div); } }, { identity: 'Opacity', fn: function(doc, div){ if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) { return false; } div.firstChild.style.cssText = 'opacity:0.73'; return div.firstChild.style.opacity == '0.73'; } }, { identity: 'Placeholder', fn: function(doc) { return 'placeholder' in doc.createElement('input'); } }, { identity: 'Direct2DBug', fn: function() { return Ext.isString(document.body.style.msTransformOrigin) && Ext.isIE10m; } }, { identity: 'BoundingClientRect', fn: function(doc, div) { return Ext.isFunction(div.getBoundingClientRect); } }, { identity: 'RotatedBoundingClientRect', fn: function() { var body = document.body, supports = false, el = document.createElement('div'), style = el.style; if (el.getBoundingClientRect) { style.WebkitTransform = style.MozTransform = style.OTransform = style.transform = 'rotate(90deg)'; style.width = '100px'; style.height = '30px'; body.appendChild(el) supports = el.getBoundingClientRect().height !== 100; body.removeChild(el); } return supports; } }, { identity: 'IncludePaddingInWidthCalculation', fn: function(doc, div){ return div.childNodes[1].firstChild.offsetWidth == 210; } }, { identity: 'IncludePaddingInHeightCalculation', fn: function(doc, div){ return div.childNodes[1].firstChild.offsetHeight == 210; } }, { identity: 'ArraySort', fn: function() { var a = [1,2,3,4,5].sort(function(){ return 0; }); return a[0] === 1 && a[1] === 2 && a[2] === 3 && a[3] === 4 && a[4] === 5; } }, { identity: 'Range', fn: function() { return !!document.createRange; } }, { identity: 'CreateContextualFragment', fn: function() { var range = Ext.supports.Range ? document.createRange() : false; return range && !!range.createContextualFragment; } }, { identity: 'WindowOnError', fn: function () { return Ext.isIE || Ext.isGecko || Ext.webKitVersion >= 534.16; } }, { identity: 'TextAreaMaxLength', fn: function(){ var el = document.createElement('textarea'); return ('maxlength' in el); } }, { identity: 'GetPositionPercentage', fn: function(doc, div){ return getStyle(div.childNodes[2], 'left') == '10%'; } }, { identity: 'PercentageHeightOverflowBug', fn: function(doc) { var hasBug = false, style, el; if (Ext.getScrollbarSize().height) { el = doc.createElement('div'); style = el.style; style.height = '50px'; style.width = '50px'; style.overflow = 'auto'; style.position = 'absolute'; el.innerHTML = [ '
', '
', '
' ].join(''); doc.body.appendChild(el); if (el.firstChild.offsetHeight === 50) { hasBug = true; } doc.body.removeChild(el); } return hasBug; } }, { identity: 'xOriginBug', fn: function(doc, div) { div.innerHTML = '
' + '
' + '
' + '
'; var outerBox = document.getElementById('b1').getBoundingClientRect(), b2 = document.getElementById('b2').getBoundingClientRect(), b3 = document.getElementById('b3').getBoundingClientRect(); return (b2.left !== outerBox.left && b3.right !== outerBox.right); } }, { identity: 'ScrollWidthInlinePaddingBug', fn: function(doc) { var hasBug = false, style, el; el = doc.createElement('div'); style = el.style; style.height = '50px'; style.width = '50px'; style.padding = '10px'; style.overflow = 'hidden'; style.position = 'absolute'; el.innerHTML = ''; doc.body.appendChild(el); if (el.scrollWidth === 70) { hasBug = true; } doc.body.removeChild(el); return hasBug; } } ] }; }()); Ext.supports.init(); Ext.util.DelayedTask = function(fn, scope, args, cancelOnDelay) { var me = this, delay, call = function() { clearInterval(me.id); me.id = null; fn.apply(scope, args || []); Ext.EventManager.idleEvent.fire(); }; cancelOnDelay = typeof cancelOnDelay === 'boolean' ? cancelOnDelay : true; me.id = null; me.delay = function(newDelay, newFn, newScope, newArgs) { if (cancelOnDelay) { me.cancel(); } if (typeof newDelay === 'number') { delay = newDelay; } fn = newFn || fn; scope = newScope || scope; args = newArgs || args; if (!me.id) { me.id = setInterval(call, delay); } }; me.cancel = function() { if (me.id) { clearInterval(me.id); me.id = null; } }; }; Ext.define('Ext.util.Event', function() { var arraySlice = Array.prototype.slice, arrayInsert = Ext.Array.insert, toArray = Ext.Array.toArray, DelayedTask = Ext.util.DelayedTask; return { isEvent: true, suspended: 0, noOptions: {}, constructor: function(observable, name) { this.name = name; this.observable = observable; this.listeners = []; }, addListener: function(fn, scope, options) { var me = this, listeners, listener, priority, isNegativePriority, highestNegativePriorityIndex, hasNegativePriorityIndex, length, index, i, listenerPriority; scope = scope || me.observable; if (!me.isListening(fn, scope)) { listener = me.createListener(fn, scope, options); if (me.firing) { me.listeners = me.listeners.slice(0); } listeners = me.listeners; index = length = listeners.length; priority = options && options.priority; highestNegativePriorityIndex = me._highestNegativePriorityIndex; hasNegativePriorityIndex = (highestNegativePriorityIndex !== undefined); if (priority) { isNegativePriority = (priority < 0); if (!isNegativePriority || hasNegativePriorityIndex) { for(i = (isNegativePriority ? highestNegativePriorityIndex : 0); i < length; i++) { listenerPriority = listeners[i].o ? listeners[i].o.priority||0 : 0; if (listenerPriority < priority) { index = i; break; } } } else { me._highestNegativePriorityIndex = index; } } else if (hasNegativePriorityIndex) { index = highestNegativePriorityIndex; } if (!isNegativePriority && index <= highestNegativePriorityIndex) { me._highestNegativePriorityIndex ++; } if (index === length) { me.listeners[length] = listener; } else { arrayInsert(me.listeners, index, [listener]); } } }, createListener: function(fn, scope, o) { scope = scope || this.observable; var me = this, listener = { fn: fn, scope: scope, ev: me }, handler = fn; if (o) { listener.o = o; if (o.single) { handler = me.createSingle(handler, listener, o, scope); } if (o.target) { handler = me.createTargeted(handler, listener, o, scope); } if (o.delay) { handler = me.createDelayed(handler, listener, o, scope); } if (o.buffer) { handler = me.createBuffered(handler, listener, o, scope); } } listener.fireFn = handler; return listener; }, findListener: function(fn, scope) { var listeners = this.listeners, i = listeners.length, listener, s; while (i--) { listener = listeners[i]; if (listener) { s = listener.scope; if (listener.fn == fn && (s == (scope || this.observable))) { return i; } } } return - 1; }, isListening: function(fn, scope) { return this.findListener(fn, scope) !== -1; }, removeListener: function(fn, scope) { var me = this, index, listener, highestNegativePriorityIndex, k; index = me.findListener(fn, scope); if (index != -1) { listener = me.listeners[index]; highestNegativePriorityIndex = me._highestNegativePriorityIndex; if (me.firing) { me.listeners = me.listeners.slice(0); } if (listener.task) { listener.task.cancel(); delete listener.task; } k = listener.tasks && listener.tasks.length; if (k) { while (k--) { listener.tasks[k].cancel(); } delete listener.tasks; } me.listeners.splice(index, 1); if (highestNegativePriorityIndex) { if (index < highestNegativePriorityIndex) { me._highestNegativePriorityIndex --; } else if (index === highestNegativePriorityIndex && index === me.listeners.length) { delete me._highestNegativePriorityIndex; } } return true; } return false; }, clearListeners: function() { var listeners = this.listeners, i = listeners.length; while (i--) { this.removeListener(listeners[i].fn, listeners[i].scope); } }, suspend: function() { this.suspended += 1; }, resume: function() { if (this.suspended) { this.suspended--; } }, fire: function() { var me = this, listeners = me.listeners, count = listeners.length, i, args, listener, len; if (!me.suspended && count > 0) { me.firing = true; args = arguments.length ? arraySlice.call(arguments, 0) : [] len = args.length; for (i = 0; i < count; i++) { listener = listeners[i]; if (listener.o) { args[len] = listener.o; } if (listener && listener.fireFn.apply(listener.scope || me.observable, args) === false) { return (me.firing = false); } } } me.firing = false; return true; }, createTargeted: function (handler, listener, o, scope) { return function(){ if (o.target === arguments[0]){ handler.apply(scope, arguments); } }; }, createBuffered: function (handler, listener, o, scope) { listener.task = new DelayedTask(); return function() { listener.task.delay(o.buffer, handler, scope, toArray(arguments)); }; }, createDelayed: function (handler, listener, o, scope) { return function() { var task = new DelayedTask(); if (!listener.tasks) { listener.tasks = []; } listener.tasks.push(task); task.delay(o.delay || 10, handler, scope, toArray(arguments)); }; }, createSingle: function (handler, listener, o, scope) { return function() { var event = listener.ev; if (event.removeListener(listener.fn, scope) && event.observable) { event.observable.hasListeners[event.name]--; } return handler.apply(scope, arguments); }; } }; }); Ext.EventManager = new function() { var EventManager = this, doc = document, win = window, escapeRx = /\\/g, prefix = Ext.baseCSSPrefix, supportsAddEventListener = !Ext.isIE9 && 'addEventListener' in doc, readyEvent, initExtCss = function() { var bd = doc.body || doc.getElementsByTagName('body')[0], cls = [], htmlCls = [], supportsLG = Ext.supports.CSS3LinearGradient, supportsBR = Ext.supports.CSS3BorderRadius, html; if (!Ext.scopeCss) { cls.push(prefix + 'body'); } if (!bd) { return false; } html = bd.parentNode; function add (c) { cls.push(prefix + c); } if (Ext.isIE && Ext.isIE9m) { add('ie'); if (Ext.isIE6) { add('ie6'); } else { add('ie7p'); if (Ext.isIE7) { add('ie7'); } else { add('ie8p'); if (Ext.isIE8) { add('ie8'); } else { add('ie9p'); if (Ext.isIE9) { add('ie9'); } } } } if (Ext.isIE7m) { add('ie7m'); } if (Ext.isIE8m) { add('ie8m'); } if (Ext.isIE9m) { add('ie9m'); } if (Ext.isIE7 || Ext.isIE8) { add('ie78'); } } if (Ext.isIE10) { add('ie10'); } if (Ext.isGecko) { add('gecko'); if (Ext.isGecko3) { add('gecko3'); } if (Ext.isGecko4) { add('gecko4'); } if (Ext.isGecko5) { add('gecko5'); } } if (Ext.isOpera) { add('opera'); } if (Ext.isWebKit) { add('webkit'); } if (Ext.isSafari) { add('safari'); if (Ext.isSafari2) { add('safari2'); } if (Ext.isSafari3) { add('safari3'); } if (Ext.isSafari4) { add('safari4'); } if (Ext.isSafari5) { add('safari5'); } if (Ext.isSafari5_0) { add('safari5_0') } } if (Ext.isChrome) { add('chrome'); } if (Ext.isMac) { add('mac'); } if (Ext.isLinux) { add('linux'); } if (!supportsBR) { add('nbr'); } if (!supportsLG) { add('nlg'); } if (html) { if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) { Ext.isBorderBox = false; } else { Ext.isBorderBox = true; } if(!Ext.isBorderBox) { htmlCls.push(prefix + 'content-box'); } if (Ext.isStrict) { htmlCls.push(prefix + 'strict'); } else { htmlCls.push(prefix + 'quirks'); } Ext.fly(html, '_internal').addCls(htmlCls); } Ext.fly(bd, '_internal').addCls(cls); return true; }; Ext.apply(EventManager, { hasBoundOnReady: false, hasFiredReady: false, deferReadyEvent : 1, onReadyChain : [], readyEvent: (function () { readyEvent = new Ext.util.Event(); readyEvent.fire = function () { Ext._beforeReadyTime = Ext._beforeReadyTime || new Date().getTime(); readyEvent.self.prototype.fire.apply(readyEvent, arguments); Ext._afterReadytime = new Date().getTime(); }; return readyEvent; }()), idleEvent: new Ext.util.Event(), isReadyPaused: function(){ return (/[?&]ext-pauseReadyFire\b/i.test(location.search) && !Ext._continueFireReady); }, bindReadyEvent: function() { if (EventManager.hasBoundOnReady) { return; } if ( doc.readyState == 'complete' ) { EventManager.onReadyEvent({ type: doc.readyState || 'body' }); } else { doc.addEventListener('DOMContentLoaded', EventManager.onReadyEvent, false); win.addEventListener('load', EventManager.onReadyEvent, false); EventManager.hasBoundOnReady = true; } }, onReadyEvent : function(e) { if (e && e.type) { EventManager.onReadyChain.push(e.type); } if (EventManager.hasBoundOnReady) { doc.removeEventListener('DOMContentLoaded', EventManager.onReadyEvent, false); win.removeEventListener('load', EventManager.onReadyEvent, false); } if (!Ext.isReady) { EventManager.fireDocReady(); } }, fireDocReady: function() { if (!Ext.isReady) { Ext._readyTime = new Date().getTime(); Ext.isReady = true; Ext.supports.init(); EventManager.onWindowUnload(); readyEvent.onReadyChain = EventManager.onReadyChain; if (Ext.isNumber(EventManager.deferReadyEvent)) { Ext.Function.defer(EventManager.fireReadyEvent, EventManager.deferReadyEvent); EventManager.hasDocReadyTimer = true; } else { EventManager.fireReadyEvent(); } } }, fireReadyEvent: function() { EventManager.hasDocReadyTimer = false; EventManager.isFiring = true; while (readyEvent.listeners.length && !EventManager.isReadyPaused()) { readyEvent.fire(); } EventManager.isFiring = false; EventManager.hasFiredReady = true; Ext.EventManager.idleEvent.fire(); }, onDocumentReady: function(fn, scope, options) { options = options || {}; options.single = true; readyEvent.addListener(fn, scope, options); if (!(EventManager.isFiring || EventManager.hasDocReadyTimer)) { if (Ext.isReady) { EventManager.fireReadyEvent(); } else { EventManager.bindReadyEvent(); } } }, stoppedMouseDownEvent: new Ext.util.Event(), propRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|freezeEvent)$/, getId : function(element) { var id; element = Ext.getDom(element); if (element === doc || element === win) { id = element === doc ? Ext.documentId : Ext.windowId; } else { id = Ext.id(element); } if (!Ext.cache[id]) { Ext.addCacheEntry(id, null, element); } return id; }, prepareListenerConfig: function(element, config, isRemove) { var propRe = EventManager.propRe, key, value, args; for (key in config) { if (config.hasOwnProperty(key)) { if (!propRe.test(key)) { value = config[key]; if (typeof value == 'function') { args = [element, key, value, config.scope, config]; } else { args = [element, key, value.fn, value.scope, value]; } if (isRemove) { EventManager.removeListener.apply(EventManager, args); } else { EventManager.addListener.apply(EventManager, args); } } } } }, mouseEnterLeaveRe: /mouseenter|mouseleave/, normalizeEvent: function(eventName, fn) { if (EventManager.mouseEnterLeaveRe.test(eventName) && !Ext.supports.MouseEnterLeave) { if (fn) { fn = Ext.Function.createInterceptor(fn, EventManager.contains); } eventName = eventName == 'mouseenter' ? 'mouseover' : 'mouseout'; } else if (eventName == 'mousewheel' && !Ext.supports.MouseWheel && !Ext.isOpera) { eventName = 'DOMMouseScroll'; } return { eventName: eventName, fn: fn }; }, contains: function(event) { event = event.browserEvent || event; var parent = event.currentTarget, child = EventManager.getRelatedTarget(event); if (parent && parent.firstChild) { while (child) { if (child === parent) { return false; } child = child.parentNode; if (child && (child.nodeType != 1)) { child = null; } } } return true; }, addListener: function(element, eventName, fn, scope, options) { if (typeof eventName !== 'string') { EventManager.prepareListenerConfig(element, eventName); return; } var dom = element.dom || Ext.getDom(element), hasAddEventListener, bind, wrap, cache, id, cacheItem, capture; if (typeof fn === 'string') { fn = Ext.resolveMethod(fn, scope || element); } options = options || {}; bind = EventManager.normalizeEvent(eventName, fn); wrap = EventManager.createListenerWrap(dom, eventName, bind.fn, scope, options); cache = EventManager.getEventListenerCache(element.dom ? element : dom, eventName); eventName = bind.eventName; hasAddEventListener = supportsAddEventListener || (Ext.isIE9 && !dom.attachEvent); if (!hasAddEventListener) { id = EventManager.normalizeId(dom); if (id) { cacheItem = Ext.cache[id][eventName]; if (cacheItem && cacheItem.firing) { cache = EventManager.cloneEventListenerCache(dom, eventName); } } } capture = !!options.capture; cache.push({ fn: fn, wrap: wrap, scope: scope, capture: capture }); if (!hasAddEventListener) { if (cache.length === 1) { id = EventManager.normalizeId(dom, true); fn = Ext.Function.bind(EventManager.handleSingleEvent, EventManager, [id, eventName], true); Ext.cache[id][eventName] = { firing: false, fn: fn }; dom.attachEvent('on' + eventName, fn); } } else { dom.addEventListener(eventName, wrap, capture); } if (dom == doc && eventName == 'mousedown') { EventManager.stoppedMouseDownEvent.addListener(wrap); } }, normalizeId: function(dom, force) { var id; if (dom === document) { id = Ext.documentId; } else if (dom === window) { id = Ext.windowId; } else { id = dom.id; } if (!id && force) { id = EventManager.getId(dom); } return id; }, handleSingleEvent: function(e, id, eventName) { var listenerCache = EventManager.getEventListenerCache(id, eventName), attachItem = Ext.cache[id][eventName], len, i; if (attachItem.firing) { return; } attachItem.firing = true; for (i = 0, len = listenerCache.length; i < len; ++i) { listenerCache[i].wrap(e); } attachItem.firing = false; }, removeListener : function(element, eventName, fn, scope) { if (typeof eventName !== 'string') { EventManager.prepareListenerConfig(element, eventName, true); return; } var dom = Ext.getDom(element), id, el = element.dom ? element : Ext.get(dom), cache = EventManager.getEventListenerCache(el, eventName), bindName = EventManager.normalizeEvent(eventName).eventName, i = cache.length, j, cacheItem, hasRemoveEventListener, listener, wrap; if (!dom) { return; } hasRemoveEventListener = supportsAddEventListener || (Ext.isIE9 && !dom.detachEvent); if (typeof fn === 'string') { fn = Ext.resolveMethod(fn, scope || element); } while (i--) { listener = cache[i]; if (listener && (!fn || listener.fn == fn) && (!scope || listener.scope === scope)) { wrap = listener.wrap; if (wrap.task) { clearTimeout(wrap.task); delete wrap.task; } j = wrap.tasks && wrap.tasks.length; if (j) { while (j--) { clearTimeout(wrap.tasks[j]); } delete wrap.tasks; } if (!hasRemoveEventListener) { id = EventManager.normalizeId(dom, true); cacheItem = Ext.cache[id][bindName]; if (cacheItem && cacheItem.firing) { cache = EventManager.cloneEventListenerCache(dom, bindName); } if (cache.length === 1) { fn = cacheItem.fn; delete Ext.cache[id][bindName]; dom.detachEvent('on' + bindName, fn); } } else { dom.removeEventListener(bindName, wrap, listener.capture); } if (wrap && dom == doc && eventName == 'mousedown') { EventManager.stoppedMouseDownEvent.removeListener(wrap); } Ext.Array.erase(cache, i, 1); } } }, removeAll : function(element) { var id = (typeof element === 'string') ? element : element.id, cache, events, eventName; if (id && (cache = Ext.cache[id])) { events = cache.events; for (eventName in events) { if (events.hasOwnProperty(eventName)) { EventManager.removeListener(element, eventName); } } cache.events = {}; } }, purgeElement : function(element, eventName) { var dom = Ext.getDom(element), i = 0, len, childNodes; if (eventName) { EventManager.removeListener(element, eventName); } else { EventManager.removeAll(element); } if (dom && dom.childNodes) { childNodes = dom.childNodes; for (len = childNodes.length; i < len; i++) { EventManager.purgeElement(childNodes[i], eventName); } } }, createListenerWrap : function(dom, ename, fn, scope, options) { options = options || {}; var gen, wrap = function(e, args) { var f; if (!gen) { f = ['if(!' + Ext.name + ') {return;}']; if (options.buffer || options.delay || options.freezeEvent) { if (options.freezeEvent) { f.push('e = X.EventObject.setEvent(e);'); } f.push('e = new X.EventObjectImpl(e, ' + (options.freezeEvent ? 'true' : 'false' ) + ');'); } else { f.push('e = X.EventObject.setEvent(e);'); } if (options.delegate) { f.push('var result, t = e.getTarget("' + (options.delegate + '').replace(escapeRx, '\\\\') + '", this);'); f.push('if(!t) {return;}'); } else { f.push('var t = e.target, result;'); } if (options.target) { f.push('if(e.target !== options.target) {return;}'); } if (options.stopEvent) { f.push('e.stopEvent();'); } else { if(options.preventDefault) { f.push('e.preventDefault();'); } if(options.stopPropagation) { f.push('e.stopPropagation();'); } } if (options.normalized === false) { f.push('e = e.browserEvent;'); } if (options.buffer) { f.push('(wrap.task && clearTimeout(wrap.task));'); f.push('wrap.task = setTimeout(function() {'); } if (options.delay) { f.push('wrap.tasks = wrap.tasks || [];'); f.push('wrap.tasks.push(setTimeout(function() {'); } f.push('result = fn.call(scope || dom, e, t, options);'); if (options.single) { f.push('evtMgr.removeListener(dom, ename, fn, scope);'); } if (ename !== 'mousemove' && ename !== 'unload') { f.push('if (evtMgr.idleEvent.listeners.length) {'); f.push('evtMgr.idleEvent.fire();'); f.push('}'); } if (options.delay) { f.push('}, ' + options.delay + '));'); } if (options.buffer) { f.push('}, ' + options.buffer + ');'); } f.push('return result;'); gen = Ext.cacheableFunctionFactory('e', 'options', 'fn', 'scope', 'ename', 'dom', 'wrap', 'args', 'X', 'evtMgr', f.join('\n')); } return gen.call(dom, e, options, fn, scope, ename, dom, wrap, args, Ext, EventManager); }; return wrap; }, getEventCache: function(element) { var elementCache, eventCache, id; if (!element) { return []; } if (element.$cache) { elementCache = element.$cache; } else { if (typeof element === 'string') { id = element; } else { id = EventManager.getId(element); } elementCache = Ext.cache[id]; } eventCache = elementCache.events || (elementCache.events = {}); return eventCache; }, getEventListenerCache : function(element, eventName) { var eventCache = EventManager.getEventCache(element); return eventCache[eventName] || (eventCache[eventName] = []); }, cloneEventListenerCache: function(element, eventName){ var eventCache = EventManager.getEventCache(element), out; if (eventCache[eventName]) { out = eventCache[eventName].slice(0); } else { out = []; } eventCache[eventName] = out; return out; }, mouseLeaveRe: /(mouseout|mouseleave)/, mouseEnterRe: /(mouseover|mouseenter)/, stopEvent: function(event) { EventManager.stopPropagation(event); EventManager.preventDefault(event); }, stopPropagation: function(event) { event = event.browserEvent || event; if (event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; } }, preventDefault: function(event) { event = event.browserEvent || event; if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; try { if (event.ctrlKey || event.keyCode > 111 && event.keyCode < 124) { event.keyCode = -1; } } catch (e) { } } }, getRelatedTarget: function(event) { event = event.browserEvent || event; var target = event.relatedTarget; if (!target) { if (EventManager.mouseLeaveRe.test(event.type)) { target = event.toElement; } else if (EventManager.mouseEnterRe.test(event.type)) { target = event.fromElement; } } return EventManager.resolveTextNode(target); }, getPageX: function(event) { return EventManager.getPageXY(event)[0]; }, getPageY: function(event) { return EventManager.getPageXY(event)[1]; }, getPageXY: function(event) { event = event.browserEvent || event; var x = event.pageX, y = event.pageY, docEl = doc.documentElement, body = doc.body; if (!x && x !== 0) { x = event.clientX + (docEl && docEl.scrollLeft || body && body.scrollLeft || 0) - (docEl && docEl.clientLeft || body && body.clientLeft || 0); y = event.clientY + (docEl && docEl.scrollTop || body && body.scrollTop || 0) - (docEl && docEl.clientTop || body && body.clientTop || 0); } return [x, y]; }, getTarget: function(event) { event = event.browserEvent || event; return EventManager.resolveTextNode(event.target || event.srcElement); }, resolveTextNode: Ext.isGecko ? function(node) { if (node) { var s = HTMLElement.prototype.toString.call(node); if (s !== '[xpconnect wrapped native prototype]' && s !== '[object XULElement]') { return node.nodeType == 3 ? node.parentNode: node; } } } : function(node) { return node && node.nodeType == 3 ? node.parentNode: node; }, curWidth: 0, curHeight: 0, onWindowResize: function(fn, scope, options) { var resize = EventManager.resizeEvent; if (!resize) { EventManager.resizeEvent = resize = new Ext.util.Event(); EventManager.on(win, 'resize', EventManager.fireResize, null, {buffer: 100}); } resize.addListener(fn, scope, options); }, fireResize: function() { var w = Ext.Element.getViewWidth(), h = Ext.Element.getViewHeight(); if (EventManager.curHeight != h || EventManager.curWidth != w) { EventManager.curHeight = h; EventManager.curWidth = w; EventManager.resizeEvent.fire(w, h); } }, removeResizeListener: function(fn, scope) { var resize = EventManager.resizeEvent; if (resize) { resize.removeListener(fn, scope); } }, onWindowUnload: function(fn, scope, options) { var unload = EventManager.unloadEvent; if (!unload) { EventManager.unloadEvent = unload = new Ext.util.Event(); EventManager.addListener(win, 'unload', EventManager.fireUnload); } if (fn) { unload.addListener(fn, scope, options); } }, fireUnload: function() { try { doc = win = undefined; var gridviews, i, ln, el, cache; EventManager.unloadEvent.fire(); if (Ext.isGecko3) { gridviews = Ext.ComponentQuery.query('gridview'); i = 0; ln = gridviews.length; for (; i < ln; i++) { gridviews[i].scrollToTop(); } } cache = Ext.cache; for (el in cache) { if (cache.hasOwnProperty(el)) { EventManager.removeAll(el); } } } catch(e) { } }, removeUnloadListener: function(fn, scope) { var unload = EventManager.unloadEvent; if (unload) { unload.removeListener(fn, scope); } }, useKeyDown: Ext.isWebKit ? parseInt(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1], 10) >= 525 : !((Ext.isGecko && !Ext.isWindows) || (Ext.isOpera && Ext.operaVersion < 12)), getKeyEvent: function() { return EventManager.useKeyDown ? 'keydown' : 'keypress'; } }); if(!supportsAddEventListener && document.attachEvent) { Ext.apply( EventManager, { pollScroll : function() { var scrollable = true; try { document.documentElement.doScroll('left'); } catch(e) { scrollable = false; } if (scrollable && document.body) { EventManager.onReadyEvent({ type:'doScroll' }); } else { EventManager.scrollTimeout = setTimeout(EventManager.pollScroll, 20); } return scrollable; }, scrollTimeout: null, readyStatesRe : /complete/i, checkReadyState: function() { var state = document.readyState; if (EventManager.readyStatesRe.test(state)) { EventManager.onReadyEvent({ type: state }); } }, bindReadyEvent: function() { var topContext = true; if (EventManager.hasBoundOnReady) { return; } try { topContext = window.frameElement === undefined; } catch(e) { topContext = false; } if (!topContext || !doc.documentElement.doScroll) { EventManager.pollScroll = Ext.emptyFn; } if (EventManager.pollScroll() === true) { return; } if (doc.readyState == 'complete' ) { EventManager.onReadyEvent({type: 'already ' + (doc.readyState || 'body') }); } else { doc.attachEvent('onreadystatechange', EventManager.checkReadyState); window.attachEvent('onload', EventManager.onReadyEvent); EventManager.hasBoundOnReady = true; } }, onReadyEvent : function(e) { if (e && e.type) { EventManager.onReadyChain.push(e.type); } if (EventManager.hasBoundOnReady) { document.detachEvent('onreadystatechange', EventManager.checkReadyState); window.detachEvent('onload', EventManager.onReadyEvent); } if (Ext.isNumber(EventManager.scrollTimeout)) { clearTimeout(EventManager.scrollTimeout); delete EventManager.scrollTimeout; } if (!Ext.isReady) { EventManager.fireDocReady(); } }, onReadyChain : [] }); } Ext.onReady = function(fn, scope, options) { Ext.Loader.onReady(fn, scope, true, options); }; Ext.onDocumentReady = EventManager.onDocumentReady; EventManager.on = EventManager.addListener; EventManager.un = EventManager.removeListener; Ext.onReady(initExtCss); }; Ext.define('Ext.util.Observable', function(Observable) { var emptyFn = Ext.emptyFn, emptyArray = [], arrayProto = Array.prototype, arraySlice = arrayProto.slice, ExtEvent = Ext.util.Event, ListenerRemover = function(observable) { if (observable instanceof ListenerRemover) { return observable; } this.observable = observable; if (arguments[1].isObservable) { this.managedListeners = true; } this.args = arraySlice.call(arguments, 1); }; ListenerRemover.prototype.destroy = function() { this.observable[this.managedListeners ? 'mun' : 'un'].apply(this.observable, this.args); }; return { statics: { releaseCapture: function(o) { o.fireEventArgs = this.prototype.fireEventArgs; }, capture: function(o, fn, scope) { var newFn = function(eventName, args) { return fn.apply(scope, [eventName].concat(args)); } this.captureArgs(o, newFn, scope); }, captureArgs: function(o, fn, scope) { o.fireEventArgs = Ext.Function.createInterceptor(o.fireEventArgs, fn, scope); }, observe: function(cls, listeners) { if (cls) { if (!cls.isObservable) { Ext.applyIf(cls, new this()); this.captureArgs(cls.prototype, cls.fireEventArgs, cls); } if (Ext.isObject(listeners)) { cls.on(listeners); } } return cls; }, prepareClass: function (T, mixin) { if (!T.HasListeners) { var HasListeners = function () {}, SuperHL = T.superclass.HasListeners || (mixin && mixin.HasListeners) || Observable.HasListeners; T.prototype.HasListeners = T.HasListeners = HasListeners; HasListeners.prototype = T.hasListeners = new SuperHL(); } } }, isObservable: true, eventsSuspended: 0, constructor: function(config) { var me = this; Ext.apply(me, config); if (!me.hasListeners) { me.hasListeners = new me.HasListeners(); } me.events = me.events || {}; if (me.listeners) { me.on(me.listeners); me.listeners = null; } if (me.bubbleEvents) { me.enableBubble(me.bubbleEvents); } }, onClassExtended: function (T) { if (!T.HasListeners) { Observable.prepareClass(T); } }, eventOptionsRe : /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|element|destroyable|vertical|horizontal|freezeEvent|priority)$/, addManagedListener: function(item, ename, fn, scope, options, noDestroy) { var me = this, managedListeners = me.managedListeners = me.managedListeners || [], config, passedOptions; if (typeof ename !== 'string') { passedOptions = arguments.length > 4 ? options : ename; options = ename; for (ename in options) { if (options.hasOwnProperty(ename)) { config = options[ename]; if (!me.eventOptionsRe.test(ename)) { me.addManagedListener(item, ename, config.fn || config, config.scope || options.scope || scope, config.fn ? config : passedOptions, true); } } } if (options && options.destroyable) { return new ListenerRemover(me, item, options); } } else { if (typeof fn === 'string') { scope = scope || me; fn = Ext.resolveMethod(fn, scope); } if (fn !== emptyFn) { managedListeners.push({ item: item, ename: ename, fn: fn, scope: scope, options: options }); item.on(ename, fn, scope, options); if (!noDestroy && options && options.destroyable) { return new ListenerRemover(me, item, ename, fn, scope); } } } }, removeManagedListener: function(item, ename, fn, scope) { var me = this, options, config, managedListeners, length, i; if (typeof ename !== 'string') { options = ename; for (ename in options) { if (options.hasOwnProperty(ename)) { config = options[ename]; if (!me.eventOptionsRe.test(ename)) { me.removeManagedListener(item, ename, config.fn || config, config.scope || options.scope || scope); } } } } else { managedListeners = me.managedListeners ? me.managedListeners.slice() : []; if (typeof fn === 'string') { scope = scope || me; fn = Ext.resolveMethod(fn, scope); } for (i = 0, length = managedListeners.length; i < length; i++) { me.removeManagedListenerItem(false, managedListeners[i], item, ename, fn, scope); } } }, fireEvent: function(eventName) { return this.fireEventArgs(eventName, arraySlice.call(arguments, 1)); }, fireEventArgs: function(eventName, args) { eventName = eventName.toLowerCase(); var me = this, events = me.events, event = events && events[eventName], ret = true; if (event && me.hasListeners[eventName]) { ret = me.continueFireEvent(eventName, args || emptyArray, event.bubble); } return ret; }, continueFireEvent: function(eventName, args, bubbles) { var target = this, queue, event, ret = true; do { if (target.eventsSuspended) { if ((queue = target.eventQueue)) { queue.push([eventName, args, bubbles]); } return ret; } else { event = target.events[eventName]; if (event && event !== true) { if ((ret = event.fire.apply(event, args)) === false) { break; } } } } while (bubbles && (target = target.getBubbleParent())); return ret; }, getBubbleParent: function() { var me = this, parent = me.getBubbleTarget && me.getBubbleTarget(); if (parent && parent.isObservable) { return parent; } return null; }, addListener: function(ename, fn, scope, options) { var me = this, config, event, prevListenerCount = 0; if (typeof ename !== 'string') { options = ename; for (ename in options) { if (options.hasOwnProperty(ename)) { config = options[ename]; if (!me.eventOptionsRe.test(ename)) { me.addListener(ename, config.fn || config, config.scope || options.scope, config.fn ? config : options); } } } if (options && options.destroyable) { return new ListenerRemover(me, options); } } else { ename = ename.toLowerCase(); event = me.events[ename]; if (event && event.isEvent) { prevListenerCount = event.listeners.length; } else { me.events[ename] = event = new ExtEvent(me, ename); } if (typeof fn === 'string') { scope = scope || me; fn = Ext.resolveMethod(fn, scope); } if (fn !== emptyFn) { event.addListener(fn, scope, options); if (event.listeners.length !== prevListenerCount) { me.hasListeners._incr_(ename); } if (options && options.destroyable) { return new ListenerRemover(me, ename, fn, scope, options); } } } }, removeListener: function(ename, fn, scope) { var me = this, config, event, options; if (typeof ename !== 'string') { options = ename; for (ename in options) { if (options.hasOwnProperty(ename)) { config = options[ename]; if (!me.eventOptionsRe.test(ename)) { me.removeListener(ename, config.fn || config, config.scope || options.scope); } } } } else { ename = ename.toLowerCase(); event = me.events[ename]; if (event && event.isEvent) { if (typeof fn === 'string') { scope = scope || me; fn = Ext.resolveMethod(fn, scope); } if (event.removeListener(fn, scope)) { me.hasListeners._decr_(ename); } } } }, clearListeners: function() { var events = this.events, hasListeners = this.hasListeners, event, key; for (key in events) { if (events.hasOwnProperty(key)) { event = events[key]; if (event.isEvent) { delete hasListeners[key]; event.clearListeners(); } } } this.clearManagedListeners(); }, clearManagedListeners : function() { var managedListeners = this.managedListeners || [], i = 0, len = managedListeners.length; for (; i < len; i++) { this.removeManagedListenerItem(true, managedListeners[i]); } this.managedListeners = []; }, removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){ if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) { managedListener.item.un(managedListener.ename, managedListener.fn, managedListener.scope); if (!isClear) { Ext.Array.remove(this.managedListeners, managedListener); } } }, addEvents: function(o) { var me = this, events = me.events || (me.events = {}), arg, args, i; if (typeof o == 'string') { for (args = arguments, i = args.length; i--; ) { arg = args[i]; if (!events[arg]) { events[arg] = true; } } } else { Ext.applyIf(me.events, o); } }, hasListener: function(ename) { return !!this.hasListeners[ename.toLowerCase()]; }, suspendEvents: function(queueSuspended) { this.eventsSuspended += 1; if (queueSuspended && !this.eventQueue) { this.eventQueue = []; } }, suspendEvent: function(eventName) { var len = arguments.length, i, event; for (i = 0; i < len; i++) { event = this.events[arguments[i]]; if (event && event.suspend) { event.suspend(); } } }, resumeEvent: function() { var len = arguments.length, i, event; for (i = 0; i < len; i++) { event = this.events[arguments[i]]; if (event && event.resume) { event.resume(); } } }, resumeEvents: function() { var me = this, queued = me.eventQueue, qLen, q; if (me.eventsSuspended && ! --me.eventsSuspended) { delete me.eventQueue; if (queued) { qLen = queued.length; for (q = 0; q < qLen; q++) { me.continueFireEvent.apply(me, queued[q]); } } } }, relayEvents : function(origin, events, prefix) { var me = this, len = events.length, i = 0, oldName, relayers = {}; for (; i < len; i++) { oldName = events[i]; relayers[oldName] = me.createRelayer(prefix ? prefix + oldName : oldName); } me.mon(origin, relayers, null, null, undefined); return new ListenerRemover(me, origin, relayers); }, createRelayer: function(newName, beginEnd) { var me = this; return function() { return me.fireEventArgs.call(me, newName, beginEnd ? arraySlice.apply(arguments, beginEnd) : arguments); }; }, enableBubble: function(eventNames) { if (eventNames) { var me = this, names = (typeof eventNames == 'string') ? arguments : eventNames, length = names.length, events = me.events, ename, event, i; for (i = 0; i < length; ++i) { ename = names[i].toLowerCase(); event = events[ename]; if (!event || typeof event == 'boolean') { events[ename] = event = new ExtEvent(me, ename); } me.hasListeners._incr_(ename); event.bubble = true; } } } }; }, function() { var Observable = this, proto = Observable.prototype, HasListeners = function () {}, prepareMixin = function (T) { if (!T.HasListeners) { var proto = T.prototype; Observable.prepareClass(T, this); T.onExtended(function (U) { Observable.prepareClass(U); }); if (proto.onClassMixedIn) { Ext.override(T, { onClassMixedIn: function (U) { prepareMixin.call(this, U); this.callParent(arguments); } }); } else { proto.onClassMixedIn = function (U) { prepareMixin.call(this, U); }; } } }, globalEvents; HasListeners.prototype = { _decr_: function (ev) { if (! --this[ev]) { delete this[ev]; } }, _incr_: function (ev) { if (this.hasOwnProperty(ev)) { ++this[ev]; } else { this[ev] = 1; } } }; proto.HasListeners = Observable.HasListeners = HasListeners; Observable.createAlias({ on: 'addListener', un: 'removeListener', mon: 'addManagedListener', mun: 'removeManagedListener' }); Observable.observeClass = Observable.observe; Ext.globalEvents = globalEvents = new Observable({ events: { idle: Ext.EventManager.idleEvent, ready: Ext.EventManager.readyEvent } }); Ext.on = function() { return globalEvents.addListener.apply(globalEvents, arguments); }; Ext.un = function() { return globalEvents.removeListener.apply(globalEvents, arguments); }; function getMethodEvent(method){ var e = (this.methodEvents = this.methodEvents || {})[method], returnValue, v, cancel, obj = this, makeCall; if (!e) { this.methodEvents[method] = e = {}; e.originalFn = this[method]; e.methodName = method; e.before = []; e.after = []; makeCall = function(fn, scope, args){ if((v = fn.apply(scope || obj, args)) !== undefined){ if (typeof v == 'object') { if(v.returnValue !== undefined){ returnValue = v.returnValue; }else{ returnValue = v; } cancel = !!v.cancel; } else if (v === false) { cancel = true; } else { returnValue = v; } } }; this[method] = function(){ var args = Array.prototype.slice.call(arguments, 0), b, i, len; returnValue = v = undefined; cancel = false; for(i = 0, len = e.before.length; i < len; i++){ b = e.before[i]; makeCall(b.fn, b.scope, args); if (cancel) { return returnValue; } } if((v = e.originalFn.apply(obj, args)) !== undefined){ returnValue = v; } for(i = 0, len = e.after.length; i < len; i++){ b = e.after[i]; makeCall(b.fn, b.scope, args); if (cancel) { return returnValue; } } return returnValue; }; } return e; } Ext.apply(proto, { onClassMixedIn: prepareMixin, beforeMethod : function(method, fn, scope){ getMethodEvent.call(this, method).before.push({ fn: fn, scope: scope }); }, afterMethod : function(method, fn, scope){ getMethodEvent.call(this, method).after.push({ fn: fn, scope: scope }); }, removeMethodListener: function(method, fn, scope){ var e = this.getMethodEvent(method), i, len; for(i = 0, len = e.before.length; i < len; i++){ if(e.before[i].fn == fn && e.before[i].scope == scope){ Ext.Array.erase(e.before, i, 1); return; } } for(i = 0, len = e.after.length; i < len; i++){ if(e.after[i].fn == fn && e.after[i].scope == scope){ Ext.Array.erase(e.after, i, 1); return; } } }, toggleEventLogging: function(toggle) { Ext.util.Observable[toggle ? 'capture' : 'releaseCapture'](this, function(en) { if (Ext.isDefined(Ext.global.console)) { Ext.global.console.log(en, arguments); } }); } }); }); Ext.define('Ext.EventObjectImpl', { BACKSPACE: 8, TAB: 9, NUM_CENTER: 12, ENTER: 13, RETURN: 13, SHIFT: 16, CTRL: 17, ALT: 18, PAUSE: 19, CAPS_LOCK: 20, ESC: 27, SPACE: 32, PAGE_UP: 33, PAGE_DOWN: 34, END: 35, HOME: 36, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, PRINT_SCREEN: 44, INSERT: 45, DELETE: 46, ZERO: 48, ONE: 49, TWO: 50, THREE: 51, FOUR: 52, FIVE: 53, SIX: 54, SEVEN: 55, EIGHT: 56, NINE: 57, A: 65, B: 66, C: 67, D: 68, E: 69, F: 70, G: 71, H: 72, I: 73, J: 74, K: 75, L: 76, M: 77, N: 78, O: 79, P: 80, Q: 81, R: 82, S: 83, T: 84, U: 85, V: 86, W: 87, X: 88, Y: 89, Z: 90, CONTEXT_MENU: 93, NUM_ZERO: 96, NUM_ONE: 97, NUM_TWO: 98, NUM_THREE: 99, NUM_FOUR: 100, NUM_FIVE: 101, NUM_SIX: 102, NUM_SEVEN: 103, NUM_EIGHT: 104, NUM_NINE: 105, NUM_MULTIPLY: 106, NUM_PLUS: 107, NUM_MINUS: 109, NUM_PERIOD: 110, NUM_DIVISION: 111, F1: 112, F2: 113, F3: 114, F4: 115, F5: 116, F6: 117, F7: 118, F8: 119, F9: 120, F10: 121, F11: 122, F12: 123, WHEEL_SCALE: (function () { var scale; if (Ext.isGecko) { scale = 3; } else if (Ext.isMac) { if (Ext.isSafari && Ext.webKitVersion >= 532.0) { scale = 120; } else { scale = 12; } scale *= 3; } else { scale = 120; } return scale; }()), clickRe: /(dbl)?click/, safariKeys: { 3: 13, 63234: 37, 63235: 39, 63232: 38, 63233: 40, 63276: 33, 63277: 34, 63272: 46, 63273: 36, 63275: 35 }, btnMap: Ext.isIE ? { 1: 0, 4: 1, 2: 2 } : { 0: 0, 1: 1, 2: 2 }, constructor: function(event, freezeEvent){ if (event) { this.setEvent(event.browserEvent || event, freezeEvent); } }, setEvent: function(event, freezeEvent){ var me = this, button; if (event === me || (event && event.browserEvent)) { return event; } me.browserEvent = event; if (event) { button = event.button ? me.btnMap[event.button] : (event.which ? event.which - 1 : -1); if (me.clickRe.test(event.type) && button == -1) { button = 0; } me.type = event.type; me.button = button; me.shiftKey = event.shiftKey; me.ctrlKey = event.ctrlKey || event.metaKey || false; me.altKey = event.altKey; me.keyCode = event.keyCode; me.charCode = event.charCode; me.target = Ext.EventManager.getTarget(event); me.relatedTarget = Ext.EventManager.getRelatedTarget(event); me.currentTarget = event.currentTarget; me.xy = (freezeEvent ? me.getXY() : null); } else { me.button = -1; me.shiftKey = false; me.ctrlKey = false; me.altKey = false; me.keyCode = 0; me.charCode = 0; me.target = null; me.xy = [0, 0]; } return me; }, clone: function() { return new this.self(this.browserEvent, this); }, stopEvent: function(){ this.stopPropagation(); this.preventDefault(); }, preventDefault: function(){ if (this.browserEvent) { Ext.EventManager.preventDefault(this.browserEvent); } }, stopPropagation: function(){ var browserEvent = this.browserEvent; if (browserEvent) { if (browserEvent.type == 'mousedown') { Ext.EventManager.stoppedMouseDownEvent.fire(this); } Ext.EventManager.stopPropagation(browserEvent); } }, getCharCode: function(){ return this.charCode || this.keyCode; }, getKey: function(){ return this.normalizeKey(this.keyCode || this.charCode); }, normalizeKey: function(key){ return Ext.isWebKit ? (this.safariKeys[key] || key) : key; }, getPageX: function(){ return this.getX(); }, getPageY: function(){ return this.getY(); }, getX: function() { return this.getXY()[0]; }, getY: function() { return this.getXY()[1]; }, getXY: function() { if (!this.xy) { this.xy = Ext.EventManager.getPageXY(this.browserEvent); } return this.xy; }, getTarget : function(selector, maxDepth, returnEl){ if (selector) { return Ext.fly(this.target).findParent(selector, maxDepth, returnEl); } return returnEl ? Ext.get(this.target) : this.target; }, getRelatedTarget : function(selector, maxDepth, returnEl){ if (selector && this.relatedTarget) { return Ext.fly(this.relatedTarget).findParent(selector, maxDepth, returnEl); } return returnEl ? Ext.get(this.relatedTarget) : this.relatedTarget; }, correctWheelDelta : function (delta) { var scale = this.WHEEL_SCALE, ret = Math.round(delta / scale); if (!ret && delta) { ret = (delta < 0) ? -1 : 1; } return ret; }, getWheelDeltas : function () { var me = this, event = me.browserEvent, dx = 0, dy = 0; if (Ext.isDefined(event.wheelDeltaX)) { dx = event.wheelDeltaX; dy = event.wheelDeltaY; } else if (event.wheelDelta) { dy = event.wheelDelta; } else if (event.detail) { dy = -event.detail; if (dy > 100) { dy = 3; } else if (dy < -100) { dy = -3; } if (Ext.isDefined(event.axis) && event.axis === event.HORIZONTAL_AXIS) { dx = dy; dy = 0; } } return { x: me.correctWheelDelta(dx), y: me.correctWheelDelta(dy) }; }, getWheelDelta : function(){ var deltas = this.getWheelDeltas(); return deltas.y; }, within : function(el, related, allowEl){ if(el){ var t = related ? this.getRelatedTarget() : this.getTarget(), result; if (t) { result = Ext.fly(el, '_internal').contains(t); if (!result && allowEl) { result = t == Ext.getDom(el); } return result; } } return false; }, isNavKeyPress : function(){ var me = this, k = this.normalizeKey(me.keyCode); return (k >= 33 && k <= 40) || k == me.RETURN || k == me.TAB || k == me.ESC; }, isSpecialKey : function(){ var k = this.normalizeKey(this.keyCode); return (this.type == 'keypress' && this.ctrlKey) || this.isNavKeyPress() || (k == this.BACKSPACE) || (k >= 16 && k <= 20) || (k >= 44 && k <= 46); }, getPoint : function(){ var xy = this.getXY(); return new Ext.util.Point(xy[0], xy[1]); }, hasModifier : function(){ return this.ctrlKey || this.altKey || this.shiftKey || this.metaKey; }, injectEvent: (function () { var API, dispatchers = {}, crazyIEButtons; if (!Ext.isIE9m && document.createEvent) { API = { createHtmlEvent: function (doc, type, bubbles, cancelable) { var event = doc.createEvent('HTMLEvents'); event.initEvent(type, bubbles, cancelable); return event; }, createMouseEvent: function (doc, type, bubbles, cancelable, detail, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget) { var event = doc.createEvent('MouseEvents'), view = doc.defaultView || window; if (event.initMouseEvent) { event.initMouseEvent(type, bubbles, cancelable, view, detail, clientX, clientY, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget); } else { event = doc.createEvent('UIEvents'); event.initEvent(type, bubbles, cancelable); event.view = view; event.detail = detail; event.screenX = clientX; event.screenY = clientY; event.clientX = clientX; event.clientY = clientY; event.ctrlKey = ctrlKey; event.altKey = altKey; event.metaKey = metaKey; event.shiftKey = shiftKey; event.button = button; event.relatedTarget = relatedTarget; } return event; }, createUIEvent: function (doc, type, bubbles, cancelable, detail) { var event = doc.createEvent('UIEvents'), view = doc.defaultView || window; event.initUIEvent(type, bubbles, cancelable, view, detail); return event; }, fireEvent: function (target, type, event) { target.dispatchEvent(event); }, fixTarget: function (target) { if (target == window && !target.dispatchEvent) { return document; } return target; } }; } else if (document.createEventObject) { crazyIEButtons = { 0: 1, 1: 4, 2: 2 }; API = { createHtmlEvent: function (doc, type, bubbles, cancelable) { var event = doc.createEventObject(); event.bubbles = bubbles; event.cancelable = cancelable; return event; }, createMouseEvent: function (doc, type, bubbles, cancelable, detail, clientX, clientY, ctrlKey, altKey, shiftKey, metaKey, button, relatedTarget) { var event = doc.createEventObject(); event.bubbles = bubbles; event.cancelable = cancelable; event.detail = detail; event.screenX = clientX; event.screenY = clientY; event.clientX = clientX; event.clientY = clientY; event.ctrlKey = ctrlKey; event.altKey = altKey; event.shiftKey = shiftKey; event.metaKey = metaKey; event.button = crazyIEButtons[button] || button; event.relatedTarget = relatedTarget; return event; }, createUIEvent: function (doc, type, bubbles, cancelable, detail) { var event = doc.createEventObject(); event.bubbles = bubbles; event.cancelable = cancelable; return event; }, fireEvent: function (target, type, event) { target.fireEvent('on' + type, event); }, fixTarget: function (target) { if (target == document) { return document.documentElement; } return target; } }; } Ext.Object.each({ load: [false, false], unload: [false, false], select: [true, false], change: [true, false], submit: [true, true], reset: [true, false], resize: [true, false], scroll: [true, false] }, function (name, value) { var bubbles = value[0], cancelable = value[1]; dispatchers[name] = function (targetEl, srcEvent) { var e = API.createHtmlEvent(name, bubbles, cancelable); API.fireEvent(targetEl, name, e); }; }); function createMouseEventDispatcher (type, detail) { var cancelable = (type != 'mousemove'); return function (targetEl, srcEvent) { var xy = srcEvent.getXY(), e = API.createMouseEvent(targetEl.ownerDocument, type, true, cancelable, detail, xy[0], xy[1], srcEvent.ctrlKey, srcEvent.altKey, srcEvent.shiftKey, srcEvent.metaKey, srcEvent.button, srcEvent.relatedTarget); API.fireEvent(targetEl, type, e); }; } Ext.each(['click', 'dblclick', 'mousedown', 'mouseup', 'mouseover', 'mousemove', 'mouseout'], function (eventName) { dispatchers[eventName] = createMouseEventDispatcher(eventName, 1); }); Ext.Object.each({ focusin: [true, false], focusout: [true, false], activate: [true, true], focus: [false, false], blur: [false, false] }, function (name, value) { var bubbles = value[0], cancelable = value[1]; dispatchers[name] = function (targetEl, srcEvent) { var e = API.createUIEvent(targetEl.ownerDocument, name, bubbles, cancelable, 1); API.fireEvent(targetEl, name, e); }; }); if (!API) { dispatchers = {}; API = { fixTarget: Ext.identityFn }; } function cannotInject (target, srcEvent) { } return function (target) { var me = this, dispatcher = dispatchers[me.type] || cannotInject, t = target ? (target.dom || target) : me.getTarget(); t = API.fixTarget(t); dispatcher(t, me); }; }()) }, function() { Ext.EventObject = new Ext.EventObjectImpl(); }); Ext.define('Ext.dom.AbstractQuery', { select: function(q, root) { var results = [], nodes, i, j, qlen, nlen; root = root || document; if (typeof root == 'string') { root = document.getElementById(root); } q = q.split(","); for (i = 0,qlen = q.length; i < qlen; i++) { if (typeof q[i] == 'string') { if (typeof q[i][0] == '@') { nodes = root.getAttributeNode(q[i].substring(1)); results.push(nodes); } else { nodes = root.querySelectorAll(q[i]); for (j = 0,nlen = nodes.length; j < nlen; j++) { results.push(nodes[j]); } } } } return results; }, selectNode: function(q, root) { return this.select(q, root)[0]; }, is: function(el, q) { if (typeof el == "string") { el = document.getElementById(el); } return this.select(q).indexOf(el) !== -1; } }); Ext.define('Ext.dom.AbstractHelper', { emptyTags : /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i, confRe : /^(?:tag|children|cn|html|tpl|tplData)$/i, endRe : /end/i, styleSepRe: /\s*(?::|;)\s*/, attributeTransform: { cls : 'class', htmlFor : 'for' }, closeTags: {}, decamelizeName : (function () { var camelCaseRe = /([a-z])([A-Z])/g, cache = {}; function decamel (match, p1, p2) { return p1 + '-' + p2.toLowerCase(); } return function (s) { return cache[s] || (cache[s] = s.replace(camelCaseRe, decamel)); }; }()), generateMarkup: function(spec, buffer) { var me = this, specType = typeof spec, attr, val, tag, i, closeTags; if (specType == "string" || specType == "number") { buffer.push(spec); } else if (Ext.isArray(spec)) { for (i = 0; i < spec.length; i++) { if (spec[i]) { me.generateMarkup(spec[i], buffer); } } } else { tag = spec.tag || 'div'; buffer.push('<', tag); for (attr in spec) { if (spec.hasOwnProperty(attr)) { val = spec[attr]; if (!me.confRe.test(attr)) { if (typeof val == "object") { buffer.push(' ', attr, '="'); me.generateStyles(val, buffer, true).push('"'); } else { buffer.push(' ', me.attributeTransform[attr] || attr, '="', val, '"'); } } } } if (me.emptyTags.test(tag)) { buffer.push('/>'); } else { buffer.push('>'); if ((val = spec.tpl)) { val.applyOut(spec.tplData, buffer); } if ((val = spec.html)) { buffer.push(val); } if ((val = spec.cn || spec.children)) { me.generateMarkup(val, buffer); } closeTags = me.closeTags; buffer.push(closeTags[tag] || (closeTags[tag] = '')); } } return buffer; }, generateStyles: function (styles, buffer, encode) { var a = buffer || [], name, val; for (name in styles) { if (styles.hasOwnProperty(name)) { val = styles[name]; name = this.decamelizeName(name); if (encode && Ext.String.hasHtmlCharacters(val)) { val = Ext.String.htmlEncode(val); } a.push(name, ':', val, ';'); } } return buffer || a.join(''); }, markup: function(spec) { if (typeof spec == "string") { return spec; } var buf = this.generateMarkup(spec, []); return buf.join(''); }, applyStyles: function(el, styles) { if (styles) { var i = 0, len; el = Ext.fly(el, '_applyStyles'); if (typeof styles == 'function') { styles = styles.call(); } if (typeof styles == 'string') { styles = Ext.util.Format.trim(styles).split(this.styleSepRe); for (len = styles.length; i < len;) { el.setStyle(styles[i++], styles[i++]); } } else if (Ext.isObject(styles)) { el.setStyle(styles); } } }, insertHtml: function(where, el, html) { var hash = {}, setStart, range, frag, rangeEl; where = where.toLowerCase(); hash.beforebegin = ['BeforeBegin', 'previousSibling']; hash.afterend = ['AfterEnd', 'nextSibling']; range = el.ownerDocument.createRange(); setStart = 'setStart' + (this.endRe.test(where) ? 'After' : 'Before'); if (hash[where]) { range[setStart](el); frag = range.createContextualFragment(html); el.parentNode.insertBefore(frag, where == 'beforebegin' ? el : el.nextSibling); return el[(where == 'beforebegin' ? 'previous' : 'next') + 'Sibling']; } else { rangeEl = (where == 'afterbegin' ? 'first' : 'last') + 'Child'; if (el.firstChild) { range[setStart](el[rangeEl]); frag = range.createContextualFragment(html); if (where == 'afterbegin') { el.insertBefore(frag, el.firstChild); } else { el.appendChild(frag); } } else { el.innerHTML = html; } return el[rangeEl]; } throw 'Illegal insertion point -> "' + where + '"'; }, insertBefore: function(el, o, returnElement) { return this.doInsert(el, o, returnElement, 'beforebegin'); }, insertAfter: function(el, o, returnElement) { return this.doInsert(el, o, returnElement, 'afterend', 'nextSibling'); }, insertFirst: function(el, o, returnElement) { return this.doInsert(el, o, returnElement, 'afterbegin', 'firstChild'); }, append: function(el, o, returnElement) { return this.doInsert(el, o, returnElement, 'beforeend', '', true); }, overwrite: function(el, o, returnElement) { el = Ext.getDom(el); el.innerHTML = this.markup(o); return returnElement ? Ext.get(el.firstChild) : el.firstChild; }, doInsert: function(el, o, returnElement, pos, sibling, append) { var newNode = this.insertHtml(pos, Ext.getDom(el), this.markup(o)); return returnElement ? Ext.get(newNode, true) : newNode; } }); Ext.define('Ext.dom.AbstractElement_static', { override: 'Ext.dom.AbstractElement', inheritableStatics: { unitRe: /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i, camelRe: /(-[a-z])/gi, msRe: /^-ms-/, cssRe: /([a-z0-9\-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*)?;?/gi, opacityRe: /alpha\(opacity=(.*)\)/i, propertyCache: {}, defaultUnit : "px", borders: {l: 'border-left-width', r: 'border-right-width', t: 'border-top-width', b: 'border-bottom-width'}, paddings: {l: 'padding-left', r: 'padding-right', t: 'padding-top', b: 'padding-bottom'}, margins: {l: 'margin-left', r: 'margin-right', t: 'margin-top', b: 'margin-bottom'}, addUnits: function(size, units) { if (typeof size == 'number') { return size + (units || this.defaultUnit || 'px'); } if (size === "" || size == "auto" || size === undefined || size === null) { return size || ''; } if (!this.unitRe.test(size)) { return size || ''; } return size; }, isAncestor: function(p, c) { var ret = false; p = Ext.getDom(p); c = Ext.getDom(c); if (p && c) { if (p.contains) { return p.contains(c); } else if (p.compareDocumentPosition) { return !!(p.compareDocumentPosition(c) & 16); } else { while ((c = c.parentNode)) { ret = c == p || ret; } } } return ret; }, parseBox: function(box) { box = box || 0; var type = typeof box, parts, ln; if (type === 'number') { return { top : box, right : box, bottom: box, left : box }; } else if (type !== 'string') { return box; } parts = box.split(' '); ln = parts.length; if (ln == 1) { parts[1] = parts[2] = parts[3] = parts[0]; } else if (ln == 2) { parts[2] = parts[0]; parts[3] = parts[1]; } else if (ln == 3) { parts[3] = parts[1]; } return { top :parseFloat(parts[0]) || 0, right :parseFloat(parts[1]) || 0, bottom:parseFloat(parts[2]) || 0, left :parseFloat(parts[3]) || 0 }; }, unitizeBox: function(box, units) { var a = this.addUnits, b = this.parseBox(box); return a(b.top, units) + ' ' + a(b.right, units) + ' ' + a(b.bottom, units) + ' ' + a(b.left, units); }, camelReplaceFn: function(m, a) { return a.charAt(1).toUpperCase(); }, normalize: function(prop) { if (prop == 'float') { prop = Ext.supports.Float ? 'cssFloat' : 'styleFloat'; } return this.propertyCache[prop] || (this.propertyCache[prop] = prop.replace(this.msRe, 'ms-').replace(this.camelRe, this.camelReplaceFn)); }, getDocumentHeight: function() { return Math.max(!Ext.isStrict ? document.body.scrollHeight : document.documentElement.scrollHeight, this.getViewportHeight()); }, getDocumentWidth: function() { return Math.max(!Ext.isStrict ? document.body.scrollWidth : document.documentElement.scrollWidth, this.getViewportWidth()); }, getViewportHeight: function(){ return window.innerHeight; }, getViewportWidth: function() { return window.innerWidth; }, getViewSize: function() { return { width: window.innerWidth, height: window.innerHeight }; }, getOrientation: function() { if (Ext.supports.OrientationChange) { return (window.orientation == 0) ? 'portrait' : 'landscape'; } return (window.innerHeight > window.innerWidth) ? 'portrait' : 'landscape'; }, fromPoint: function(x, y) { return Ext.get(document.elementFromPoint(x, y)); }, parseStyles: function(styles){ var out = {}, cssRe = this.cssRe, matches; if (styles) { cssRe.lastIndex = 0; while ((matches = cssRe.exec(styles))) { out[matches[1]] = matches[2]||''; } } return out; } } }, function () { var doc = document, activeElement = null, isCSS1 = doc.compatMode == "CSS1Compat"; if (!('activeElement' in doc) && doc.addEventListener) { doc.addEventListener('focus', function (ev) { if (ev && ev.target) { activeElement = (ev.target == doc) ? null : ev.target; } }, true); } function makeSelectionRestoreFn (activeEl, start, end) { return function () { activeEl.selectionStart = start; activeEl.selectionEnd = end; }; } this.addInheritableStatics({ getActiveElement: function () { var active; try { active = doc.activeElement; } catch(e) {} active = active || activeElement; if (!active) { active = activeElement = document.body; } return active; }, getRightMarginFixCleaner: function (target) { var supports = Ext.supports, hasInputBug = supports.DisplayChangeInputSelectionBug, hasTextAreaBug = supports.DisplayChangeTextAreaSelectionBug, activeEl, tag, start, end; if (hasInputBug || hasTextAreaBug) { activeEl = doc.activeElement || activeElement; tag = activeEl && activeEl.tagName; if ((hasTextAreaBug && tag == 'TEXTAREA') || (hasInputBug && tag == 'INPUT' && activeEl.type == 'text')) { if (Ext.dom.Element.isAncestor(target, activeEl)) { start = activeEl.selectionStart; end = activeEl.selectionEnd; if (Ext.isNumber(start) && Ext.isNumber(end)) { return makeSelectionRestoreFn(activeEl, start, end); } } } } return Ext.emptyFn; }, getViewWidth: function(full) { return full ? Ext.dom.Element.getDocumentWidth() : Ext.dom.Element.getViewportWidth(); }, getViewHeight: function(full) { return full ? Ext.dom.Element.getDocumentHeight() : Ext.dom.Element.getViewportHeight(); }, getDocumentHeight: function() { return Math.max(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, Ext.dom.Element.getViewportHeight()); }, getDocumentWidth: function() { return Math.max(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, Ext.dom.Element.getViewportWidth()); }, getViewportHeight: function(){ return Ext.isIE9m ? (Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) : self.innerHeight; }, getViewportWidth: function() { return (!Ext.isStrict && !Ext.isOpera) ? doc.body.clientWidth : Ext.isIE9m ? doc.documentElement.clientWidth : self.innerWidth; }, serializeForm: function(form) { var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements, hasSubmit = false, encoder = encodeURIComponent, data = '', eLen = fElements.length, element, name, type, options, hasValue, e, o, oLen, opt; for (e = 0; e < eLen; e++) { element = fElements[e]; name = element.name; type = element.type; options = element.options; if (!element.disabled && name) { if (/select-(one|multiple)/i.test(type)) { oLen = options.length; for (o = 0; o < oLen; o++) { opt = options[o]; if (opt.selected) { hasValue = opt.hasAttribute ? opt.hasAttribute('value') : opt.getAttributeNode('value').specified; data += Ext.String.format("{0}={1}&", encoder(name), encoder(hasValue ? opt.value : opt.text)); } } } else if (!(/file|undefined|reset|button/i.test(type))) { if (!(/radio|checkbox/i.test(type) && !element.checked) && !(type == 'submit' && hasSubmit)) { data += encoder(name) + '=' + encoder(element.value) + '&'; hasSubmit = /submit/i.test(type); } } } } return data.substr(0, data.length - 1); } }); }); Ext.define('Ext.dom.AbstractElement_insertion', { override: 'Ext.dom.AbstractElement', appendChild: function(el, returnDom) { var me = this, insertEl, eLen, e, oldUseDom; if (el.nodeType || el.dom || typeof el == 'string') { el = Ext.getDom(el); me.dom.appendChild(el); return !returnDom ? Ext.get(el) : el; } else if (el.length) { insertEl = Ext.fly(document.createDocumentFragment(), '_internal'); eLen = el.length; Ext.DomHelper.useDom = true; for (e = 0; e < eLen; e++) { insertEl.appendChild(el[e], returnDom); } Ext.DomHelper.useDom = oldUseDom; me.dom.appendChild(insertEl.dom); return returnDom ? insertEl.dom : insertEl; } else { return me.createChild(el, null, returnDom); } }, appendTo: function(el) { Ext.getDom(el).appendChild(this.dom); return this; }, insertBefore: function(el) { el = Ext.getDom(el); el.parentNode.insertBefore(this.dom, el); return this; }, insertAfter: function(el) { el = Ext.getDom(el); el.parentNode.insertBefore(this.dom, el.nextSibling); return this; }, insertFirst: function(el, returnDom) { el = el || {}; if (el.nodeType || el.dom || typeof el == 'string') { el = Ext.getDom(el); this.dom.insertBefore(el, this.dom.firstChild); return !returnDom ? Ext.get(el) : el; } else { return this.createChild(el, this.dom.firstChild, returnDom); } }, insertSibling: function(el, where, returnDom) { var me = this, DomHelper = Ext.core.DomHelper, oldUseDom = DomHelper.useDom, isAfter = (where || 'before').toLowerCase() == 'after', rt, insertEl, eLen, e; if (Ext.isArray(el)) { insertEl = Ext.fly(document.createDocumentFragment(), '_internal'); eLen = el.length; DomHelper.useDom = true; for (e = 0; e < eLen; e++) { rt = insertEl.appendChild(el[e], returnDom); } DomHelper.useDom = oldUseDom; me.dom.parentNode.insertBefore(insertEl.dom, isAfter ? me.dom.nextSibling : me.dom); return rt; } el = el || {}; if (el.nodeType || el.dom) { rt = me.dom.parentNode.insertBefore(Ext.getDom(el), isAfter ? me.dom.nextSibling : me.dom); if (!returnDom) { rt = Ext.get(rt); } } else { if (isAfter && !me.dom.nextSibling) { rt = DomHelper.append(me.dom.parentNode, el, !returnDom); } else { rt = DomHelper[isAfter ? 'insertAfter' : 'insertBefore'](me.dom, el, !returnDom); } } return rt; }, replace: function(el) { el = Ext.get(el); this.insertBefore(el); el.remove(); return this; }, replaceWith: function(el){ var me = this; if (el.nodeType || el.dom || typeof el == 'string') { el = Ext.get(el); me.dom.parentNode.insertBefore(el.dom, me.dom); } else { el = Ext.core.DomHelper.insertBefore(me.dom, el); } delete Ext.cache[me.id]; Ext.removeNode(me.dom); me.id = Ext.id(me.dom = el); Ext.dom.AbstractElement.addToCache(me.isFlyweight ? new Ext.dom.AbstractElement(me.dom) : me); return me; }, createChild: function(config, insertBefore, returnDom) { config = config || {tag:'div'}; if (insertBefore) { return Ext.core.DomHelper.insertBefore(insertBefore, config, returnDom !== true); } else { return Ext.core.DomHelper.append(this.dom, config, returnDom !== true); } }, wrap: function(config, returnDom, selector) { var newEl = Ext.core.DomHelper.insertBefore(this.dom, config || {tag: "div"}, true), target = newEl; if (selector) { target = Ext.DomQuery.selectNode(selector, newEl.dom); } target.appendChild(this.dom); return returnDom ? newEl.dom : newEl; }, insertHtml: function(where, html, returnEl) { var el = Ext.core.DomHelper.insertHtml(where, this.dom, html); return returnEl ? Ext.get(el) : el; } }); Ext.define('Ext.dom.AbstractElement_style', { override: 'Ext.dom.AbstractElement' }, function() { var Element = this, wordsRe = /\w/g, spacesRe = /\s+/, transparentRe = /^(?:transparent|(?:rgba[(](?:\s*\d+\s*[,]){3}\s*0\s*[)]))$/i, hasClassList = Ext.supports.ClassList, PADDING = 'padding', MARGIN = 'margin', BORDER = 'border', LEFT_SUFFIX = '-left', RIGHT_SUFFIX = '-right', TOP_SUFFIX = '-top', BOTTOM_SUFFIX = '-bottom', WIDTH = '-width', borders = {l: BORDER + LEFT_SUFFIX + WIDTH, r: BORDER + RIGHT_SUFFIX + WIDTH, t: BORDER + TOP_SUFFIX + WIDTH, b: BORDER + BOTTOM_SUFFIX + WIDTH}, paddings = {l: PADDING + LEFT_SUFFIX, r: PADDING + RIGHT_SUFFIX, t: PADDING + TOP_SUFFIX, b: PADDING + BOTTOM_SUFFIX}, margins = {l: MARGIN + LEFT_SUFFIX, r: MARGIN + RIGHT_SUFFIX, t: MARGIN + TOP_SUFFIX, b: MARGIN + BOTTOM_SUFFIX}, internalFly = new Element.Fly(); Ext.override(Element, { styleHooks: {}, addStyles : function(sides, styles){ var totalSize = 0, sidesArr = (sides || '').match(wordsRe), i, len = sidesArr.length, side, styleSides = []; if (len == 1) { totalSize = Math.abs(parseFloat(this.getStyle(styles[sidesArr[0]])) || 0); } else if (len) { for (i = 0; i < len; i++) { side = sidesArr[i]; styleSides.push(styles[side]); } styleSides = this.getStyle(styleSides); for (i=0; i < len; i++) { side = sidesArr[i]; totalSize += Math.abs(parseFloat(styleSides[styles[side]]) || 0); } } return totalSize; }, addCls: (function(){ var addWithClassList = function(className) { var me = this, dom = me.dom, trimRe = me.trimRe, origClassName = className, classList, newCls, i, len, cls; if (typeof(className) == 'string') { className = className.replace(trimRe, '').split(spacesRe); } if (dom && className && !!(len = className.length)) { if (!dom.className) { dom.className = className.join(' '); } else { classList = dom.classList; if (classList) { for (i = 0; i < len; ++i) { cls = className[i]; if (cls) { if (!classList.contains(cls)) { if (newCls) { newCls.push(cls); } else { newCls = dom.className.replace(trimRe, ''); newCls = newCls ? [newCls, cls] : [cls]; } } } } if (newCls) { dom.className = newCls.join(' '); } } else { addWithoutClassList(origClassName); } } } return me; }, addWithoutClassList = function(className) { var me = this, dom = me.dom, elClasses; if (dom && className && className.length) { elClasses = Ext.Element.mergeClsList(dom.className, className); if (elClasses.changed) { dom.className = elClasses.join(' '); } } return me; }; return hasClassList ? addWithClassList : addWithoutClassList; })(), removeCls: function(className) { var me = this, dom = me.dom, classList, len, elClasses; if (typeof(className) == 'string') { className = className.replace(me.trimRe, '').split(spacesRe); } if (dom && dom.className && className && !!(len = className.length)) { classList = dom.classList; if (len === 1 && classList) { if (className[0]) { classList.remove(className[0]); } } else { elClasses = Ext.Element.removeCls(dom.className, className); if (elClasses.changed) { dom.className = elClasses.join(' '); } } } return me; }, radioCls: function(className) { var cn = this.dom.parentNode.childNodes, v, i, len; className = Ext.isArray(className) ? className: [className]; for (i = 0, len = cn.length; i < len; i++) { v = cn[i]; if (v && v.nodeType == 1) { internalFly.attach(v).removeCls(className); } } return this.addCls(className); }, toggleCls: (function(){ var toggleWithClassList = function(className){ var me = this, dom = me.dom, classList; if (dom) { className = className.replace(me.trimRe, ''); if (className) { classList = dom.classList; if (classList) { classList.toggle(className); } else { toggleWithoutClassList(className); } } } return me; }, toggleWithoutClassList = function(className){ return this.hasCls(className) ? this.removeCls(className) : this.addCls(className); }; return hasClassList ? toggleWithClassList : toggleWithoutClassList; })(), hasCls: (function(){ var hasClsWithClassList = function(className) { var dom = this.dom, out = false, classList; if (dom && className) { classList = dom.classList; if (classList) { out = classList.contains(className); } else { out = hasClsWithoutClassList(className); } } return out; }, hasClsWithoutClassList = function(className){ var dom = this.dom; return dom ? className && (' '+dom.className+' ').indexOf(' '+className+' ') !== -1 : false; }; return hasClassList ? hasClsWithClassList : hasClsWithoutClassList; })(), replaceCls: function(oldClassName, newClassName){ return this.removeCls(oldClassName).addCls(newClassName); }, isStyle: function(style, val) { return this.getStyle(style) == val; }, getStyle: function (property, inline) { var me = this, dom = me.dom, multiple = typeof property != 'string', hooks = me.styleHooks, prop = property, props = prop, len = 1, domStyle, camel, values, hook, out, style, i; if (multiple) { values = {}; prop = props[0]; i = 0; if (!(len = props.length)) { return values; } } if (!dom || dom.documentElement) { return values || ''; } domStyle = dom.style; if (inline) { style = domStyle; } else { style = dom.ownerDocument.defaultView.getComputedStyle(dom, null); if (!style) { inline = true; style = domStyle; } } do { hook = hooks[prop]; if (!hook) { hooks[prop] = hook = { name: Element.normalize(prop) }; } if (hook.get) { out = hook.get(dom, me, inline, style); } else { camel = hook.name; out = style[camel]; } if (!multiple) { return out; } values[prop] = out; prop = props[++i]; } while (i < len); return values; }, getStyles: function () { var props = Ext.Array.slice(arguments), len = props.length, inline; if (len && typeof props[len-1] == 'boolean') { inline = props.pop(); } return this.getStyle(props, inline); }, isTransparent: function (prop) { var value = this.getStyle(prop); return value ? transparentRe.test(value) : false; }, setStyle: function(prop, value) { var me = this, dom = me.dom, hooks = me.styleHooks, style = dom.style, name = prop, hook; if (typeof name == 'string') { hook = hooks[name]; if (!hook) { hooks[name] = hook = { name: Element.normalize(name) }; } value = (value == null) ? '' : value; if (hook.set) { hook.set(dom, value, me); } else { style[hook.name] = value; } if (hook.afterSet) { hook.afterSet(dom, value, me); } } else { for (name in prop) { if (prop.hasOwnProperty(name)) { hook = hooks[name]; if (!hook) { hooks[name] = hook = { name: Element.normalize(name) }; } value = prop[name]; value = (value == null) ? '' : value; if (hook.set) { hook.set(dom, value, me); } else { style[hook.name] = value; } if (hook.afterSet) { hook.afterSet(dom, value, me); } } } } return me; }, getHeight: function(contentHeight) { var dom = this.dom, height = contentHeight ? (dom.clientHeight - this.getPadding("tb")) : dom.offsetHeight; return height > 0 ? height: 0; }, getWidth: function(contentWidth) { var dom = this.dom, width = contentWidth ? (dom.clientWidth - this.getPadding("lr")) : dom.offsetWidth; return width > 0 ? width: 0; }, setWidth: function(width) { var me = this; me.dom.style.width = Element.addUnits(width); return me; }, setHeight: function(height) { var me = this; me.dom.style.height = Element.addUnits(height); return me; }, getBorderWidth: function(side){ return this.addStyles(side, borders); }, getPadding: function(side){ return this.addStyles(side, paddings); }, margins : margins, applyStyles: function(styles) { if (styles) { var i, len, dom = this.dom; if (typeof styles == 'function') { styles = styles.call(); } if (typeof styles == 'string') { styles = Ext.util.Format.trim(styles).split(/\s*(?::|;)\s*/); for (i = 0, len = styles.length; i < len;) { dom.style[Element.normalize(styles[i++])] = styles[i++]; } } else if (typeof styles == 'object') { this.setStyle(styles); } } }, setSize: function(width, height) { var me = this, style = me.dom.style; if (Ext.isObject(width)) { height = width.height; width = width.width; } style.width = Element.addUnits(width); style.height = Element.addUnits(height); return me; }, getViewSize: function() { var doc = document, dom = this.dom; if (dom == doc || dom == doc.body) { return { width: Element.getViewportWidth(), height: Element.getViewportHeight() }; } else { return { width: dom.clientWidth, height: dom.clientHeight }; } }, getSize: function(contentSize) { var dom = this.dom; return { width: Math.max(0, contentSize ? (dom.clientWidth - this.getPadding("lr")) : dom.offsetWidth), height: Math.max(0, contentSize ? (dom.clientHeight - this.getPadding("tb")) : dom.offsetHeight) }; }, repaint: function() { var dom = this.dom; this.addCls(Ext.baseCSSPrefix + 'repaint'); setTimeout(function(){ internalFly.attach(dom).removeCls(Ext.baseCSSPrefix + 'repaint'); }, 1); return this; }, getMargin: function(side){ var me = this, hash = {t:"top", l:"left", r:"right", b: "bottom"}, key, o, margins; if (!side) { margins = []; for (key in me.margins) { if(me.margins.hasOwnProperty(key)) { margins.push(me.margins[key]); } } o = me.getStyle(margins); if(o && typeof o == 'object') { for (key in me.margins) { if(me.margins.hasOwnProperty(key)) { o[hash[key]] = parseFloat(o[me.margins[key]]) || 0; } } } return o; } else { return me.addStyles(side, me.margins); } }, mask: function(msg, msgCls, transparent) { var me = this, dom = me.dom, data = (me.$cache || me.getCache()).data, el = data.mask, mask, size, cls = '', prefix = Ext.baseCSSPrefix; me.addCls(prefix + 'masked'); if (me.getStyle("position") == "static") { me.addCls(prefix + 'masked-relative'); } if (el) { el.remove(); } if (msgCls && typeof msgCls == 'string' ) { cls = ' ' + msgCls; } else { cls = ' ' + prefix + 'mask-gray'; } mask = me.createChild({ role: 'presentation', cls: prefix + 'mask' + ((transparent !== false) ? '' : (' ' + prefix + 'mask-gray')), html: msg ? ('') : '' }); size = me.getSize(); data.mask = mask; if (dom === document.body) { size.height = window.innerHeight; if (me.orientationHandler) { Ext.EventManager.unOrientationChange(me.orientationHandler, me); } me.orientationHandler = function() { size = me.getSize(); size.height = window.innerHeight; mask.setSize(size); }; Ext.EventManager.onOrientationChange(me.orientationHandler, me); } mask.setSize(size); if (Ext.is.iPad) { Ext.repaint(); } }, unmask: function() { var me = this, data = (me.$cache || me.getCache()).data, mask = data.mask, prefix = Ext.baseCSSPrefix; if (mask) { mask.remove(); delete data.mask; } me.removeCls([prefix + 'masked', prefix + 'masked-relative']); if (me.dom === document.body) { Ext.EventManager.unOrientationChange(me.orientationHandler, me); delete me.orientationHandler; } } }); Ext.onReady(function () { var supports = Ext.supports, styleHooks, colorStyles, i, name, camel; function fixTransparent (dom, el, inline, style) { var value = style[this.name] || ''; return transparentRe.test(value) ? 'transparent' : value; } function fixRightMargin (dom, el, inline, style) { var result = style.marginRight, domStyle, display; if (result != '0px') { domStyle = dom.style; display = domStyle.display; domStyle.display = 'inline-block'; result = (inline ? style : dom.ownerDocument.defaultView.getComputedStyle(dom, null)).marginRight; domStyle.display = display; } return result; } function fixRightMarginAndInputFocus (dom, el, inline, style) { var result = style.marginRight, domStyle, cleaner, display; if (result != '0px') { domStyle = dom.style; cleaner = Element.getRightMarginFixCleaner(dom); display = domStyle.display; domStyle.display = 'inline-block'; result = (inline ? style : dom.ownerDocument.defaultView.getComputedStyle(dom, '')).marginRight; domStyle.display = display; cleaner(); } return result; } styleHooks = Element.prototype.styleHooks; if (supports.init) { supports.init(); } if (!supports.RightMargin) { styleHooks.marginRight = styleHooks['margin-right'] = { name: 'marginRight', get: (supports.DisplayChangeInputSelectionBug || supports.DisplayChangeTextAreaSelectionBug) ? fixRightMarginAndInputFocus : fixRightMargin }; } if (!supports.TransparentColor) { colorStyles = ['background-color', 'border-color', 'color', 'outline-color']; for (i = colorStyles.length; i--; ) { name = colorStyles[i]; camel = Element.normalize(name); styleHooks[name] = styleHooks[camel] = { name: camel, get: fixTransparent }; } } }); }); Ext.define('Ext.dom.AbstractElement_traversal', { override: 'Ext.dom.AbstractElement', findParent: function(simpleSelector, limit, returnEl) { var target = this.dom, topmost = document.documentElement, depth = 0, stopEl; limit = limit || 50; if (isNaN(limit)) { stopEl = Ext.getDom(limit); limit = Number.MAX_VALUE; } while (target && target.nodeType == 1 && depth < limit && target != topmost && target != stopEl) { if (Ext.DomQuery.is(target, simpleSelector)) { return returnEl ? Ext.get(target) : target; } depth++; target = target.parentNode; } return null; }, findParentNode: function(simpleSelector, limit, returnEl) { var p = Ext.fly(this.dom.parentNode, '_internal'); return p ? p.findParent(simpleSelector, limit, returnEl) : null; }, up: function(simpleSelector, limit, returnDom) { return this.findParentNode(simpleSelector, limit, !returnDom); }, select: function(selector, composite) { return Ext.dom.Element.select(selector, this.dom, composite); }, query: function(selector) { return Ext.DomQuery.select(selector, this.dom); }, down: function(selector, returnDom) { var n = Ext.DomQuery.selectNode(selector, this.dom); return returnDom ? n : Ext.get(n); }, child: function(selector, returnDom) { var node, me = this, id; id = Ext.id(me.dom); id = Ext.escapeId(id); node = Ext.DomQuery.selectNode('#' + id + " > " + selector, me.dom); return returnDom ? node : Ext.get(node); }, parent: function(selector, returnDom) { return this.matchNode('parentNode', 'parentNode', selector, returnDom); }, next: function(selector, returnDom) { return this.matchNode('nextSibling', 'nextSibling', selector, returnDom); }, prev: function(selector, returnDom) { return this.matchNode('previousSibling', 'previousSibling', selector, returnDom); }, first: function(selector, returnDom) { return this.matchNode('nextSibling', 'firstChild', selector, returnDom); }, last: function(selector, returnDom) { return this.matchNode('previousSibling', 'lastChild', selector, returnDom); }, matchNode: function(dir, start, selector, returnDom) { if (!this.dom) { return null; } var n = this.dom[start]; while (n) { if (n.nodeType == 1 && (!selector || Ext.DomQuery.is(n, selector))) { return !returnDom ? Ext.get(n) : n; } n = n[dir]; } return null; }, isAncestor: function(element) { return this.self.isAncestor.call(this.self, this.dom, element); } }); Ext.define('Ext.dom.AbstractElement', { trimRe: /^\s+|\s+$/g, whitespaceRe: /\s/, inheritableStatics: { trimRe: /^\s+|\s+$/g, whitespaceRe: /\s/, get: function(el) { var me = this, document = window.document, El = Ext.dom.Element, cacheItem, docEl, extEl, dom, id; if (!el) { return null; } if (el.isFly) { el = el.dom; } if (typeof el == "string") { if (el == Ext.windowId) { return El.get(window); } else if (el == Ext.documentId) { return El.get(document); } cacheItem = Ext.cache[el]; if (cacheItem && cacheItem.skipGarbageCollection) { extEl = cacheItem.el; return extEl; } if (!(dom = document.getElementById(el))) { return null; } if (cacheItem && cacheItem.el) { extEl = Ext.updateCacheEntry(cacheItem, dom).el; } else { extEl = new El(dom, !!cacheItem); } return extEl; } else if (el.tagName) { if (!(id = el.id)) { id = Ext.id(el); } cacheItem = Ext.cache[id]; if (cacheItem && cacheItem.el) { extEl = Ext.updateCacheEntry(cacheItem, el).el; } else { extEl = new El(el, !!cacheItem); } return extEl; } else if (el instanceof me) { if (el != me.docEl && el != me.winEl) { id = el.id; cacheItem = Ext.cache[id]; if (cacheItem) { Ext.updateCacheEntry(cacheItem, document.getElementById(id) || el.dom); } } return el; } else if (el.isComposite) { return el; } else if (Ext.isArray(el)) { return me.select(el); } else if (el === document) { if (!me.docEl) { docEl = me.docEl = Ext.Object.chain(El.prototype); docEl.dom = document; docEl.el = docEl; docEl.id = Ext.id(document); me.addToCache(docEl); } return me.docEl; } else if (el === window) { if (!me.winEl) { me.winEl = Ext.Object.chain(El.prototype); me.winEl.dom = window; me.winEl.id = Ext.id(window); me.addToCache(me.winEl); } return me.winEl; } return null; }, addToCache: function(el, id) { if (el) { Ext.addCacheEntry(id, el); } return el; }, addMethods: function() { this.override.apply(this, arguments); }, mergeClsList: function() { var clsList, clsHash = {}, i, length, j, listLength, clsName, result = [], changed = false, trimRe = this.trimRe, whitespaceRe = this.whitespaceRe; for (i = 0, length = arguments.length; i < length; i++) { clsList = arguments[i]; if (Ext.isString(clsList)) { clsList = clsList.replace(trimRe, '').split(whitespaceRe); } if (clsList) { for (j = 0, listLength = clsList.length; j < listLength; j++) { clsName = clsList[j]; if (!clsHash[clsName]) { if (i) { changed = true; } clsHash[clsName] = true; } } } } for (clsName in clsHash) { result.push(clsName); } result.changed = changed; return result; }, removeCls: function(existingClsList, removeClsList) { var clsHash = {}, i, length, clsName, result = [], changed = false, whitespaceRe = this.whitespaceRe; if (existingClsList) { if (Ext.isString(existingClsList)) { existingClsList = existingClsList.replace(this.trimRe, '').split(whitespaceRe); } for (i = 0, length = existingClsList.length; i < length; i++) { clsHash[existingClsList[i]] = true; } } if (removeClsList) { if (Ext.isString(removeClsList)) { removeClsList = removeClsList.split(whitespaceRe); } for (i = 0, length = removeClsList.length; i < length; i++) { clsName = removeClsList[i]; if (clsHash[clsName]) { changed = true; delete clsHash[clsName]; } } } for (clsName in clsHash) { result.push(clsName); } result.changed = changed; return result; }, VISIBILITY: 1, DISPLAY: 2, OFFSETS: 3, ASCLASS: 4 }, constructor: function(element, forceNew) { var me = this, dom = typeof element == 'string' ? document.getElementById(element) : element, id; me.el = me; if (!dom) { return null; } id = dom.id; if (!forceNew && id && Ext.cache[id]) { return Ext.cache[id].el; } me.dom = dom; me.id = id || Ext.id(dom); me.self.addToCache(me); }, set: function(o, useSet) { var el = this.dom, attr, value; for (attr in o) { if (o.hasOwnProperty(attr)) { value = o[attr]; if (attr == 'style') { this.applyStyles(value); } else if (attr == 'cls') { el.className = value; } else if (useSet !== false) { if (value === undefined) { el.removeAttribute(attr); } else { el.setAttribute(attr, value); } } else { el[attr] = value; } } } return this; }, defaultUnit: "px", is: function(simpleSelector) { return Ext.DomQuery.is(this.dom, simpleSelector); }, getValue: function(asNumber) { var val = this.dom.value; return asNumber ? parseInt(val, 10) : val; }, remove: function() { var me = this, dom = me.dom; if (me.isAnimate) { me.stopAnimation(); } if (dom) { Ext.removeNode(dom); delete me.dom; } }, contains: (function () { var isXpc = function (el) { var s; try { el = el.dom || el; } catch (e) { return true; } s = HTMLElement.prototype.toString.call(el); return s === '[xpconnect wrapped native prototype]' || s === '[object XULElement]'; }; return function (el) { if (!el || (Ext.isGecko3 && isXpc(el))) { return false; } var me = this, dom = el.dom || el; return (dom === me.dom) || Ext.dom.AbstractElement.isAncestor(me.dom, dom); }; }()), getAttribute: function(name, ns) { var dom = this.dom; return dom.getAttributeNS(ns, name) || dom.getAttribute(ns + ":" + name) || dom.getAttribute(name) || dom[name]; }, update: function(html) { if (this.dom) { this.dom.innerHTML = html; } return this; }, setHTML: function(html) { if(this.dom) { this.dom.innerHTML = html; } return this; }, getHTML: function() { return this.dom ? this.dom.innerHTML : ''; }, hide: function() { this.setVisible(false); return this; }, show: function() { this.setVisible(true); return this; }, setVisible: function(visible, animate) { var me = this, statics = me.self, mode = me.getVisibilityMode(), prefix = Ext.baseCSSPrefix; switch (mode) { case statics.VISIBILITY: me.removeCls([prefix + 'hidden-display', prefix + 'hidden-offsets']); me[visible ? 'removeCls' : 'addCls'](prefix + 'hidden-visibility'); break; case statics.DISPLAY: me.removeCls([prefix + 'hidden-visibility', prefix + 'hidden-offsets']); me[visible ? 'removeCls' : 'addCls'](prefix + 'hidden-display'); break; case statics.OFFSETS: me.removeCls([prefix + 'hidden-visibility', prefix + 'hidden-display']); me[visible ? 'removeCls' : 'addCls'](prefix + 'hidden-offsets'); break; } return me; }, getVisibilityMode: function() { var data = (this.$cache || this.getCache()).data, visMode = data.visibilityMode; if (visMode === undefined) { data.visibilityMode = visMode = this.self.DISPLAY; } return visMode; }, setVisibilityMode: function(mode) { (this.$cache || this.getCache()).data.visibilityMode = mode; return this; }, getCache: function() { var me = this, id = me.dom.id || Ext.id(me.dom); me.$cache = Ext.cache[id] || Ext.addCacheEntry(id, null, me.dom); return me.$cache; } }, function() { var AbstractElement = this; Ext.getDetachedBody = function () { var detachedEl = AbstractElement.detachedBodyEl; if (!detachedEl) { detachedEl = document.createElement('div'); AbstractElement.detachedBodyEl = detachedEl = new AbstractElement.Fly(detachedEl); detachedEl.isDetachedBody = true; } return detachedEl; }; Ext.getElementById = function (id) { var el = document.getElementById(id), detachedBodyEl; if (!el && (detachedBodyEl = AbstractElement.detachedBodyEl)) { el = detachedBodyEl.dom.querySelector('#' + Ext.escapeId(id)); } return el; }; Ext.get = function(el) { return Ext.dom.Element.get(el); }; this.addStatics({ Fly: new Ext.Class({ extend: AbstractElement, isFly: true, constructor: function(dom) { this.dom = dom; this.el = this; }, attach: function (dom) { this.dom = dom; this.$cache = dom && dom.id ? Ext.cache[dom.id] : null; return this; } }), _flyweights: {}, fly: function(dom, named) { var fly = null, _flyweights = AbstractElement._flyweights; named = named || '_global'; dom = Ext.getDom(dom); if (dom) { fly = _flyweights[named] || (_flyweights[named] = new AbstractElement.Fly()); fly.dom = dom; fly.$cache = dom.id ? Ext.cache[dom.id] : null; } return fly; } }); Ext.fly = function() { return AbstractElement.fly.apply(AbstractElement, arguments); }; (function (proto) { proto.destroy = proto.remove; if (document.querySelector) { proto.getById = function (id, asDom) { var dom = document.getElementById(id) || this.dom.querySelector('#'+Ext.escapeId(id)); return asDom ? dom : (dom ? Ext.get(dom) : null); }; } else { proto.getById = function (id, asDom) { var dom = document.getElementById(id); return asDom ? dom : (dom ? Ext.get(dom) : null); }; } }(this.prototype)); }); Ext.define('Ext.dom.Helper', (function() { var afterbegin = 'afterbegin', afterend = 'afterend', beforebegin = 'beforebegin', beforeend = 'beforeend', ts = '', te = '
', tbs = ts+'', tbe = ''+te, trs = tbs + '', tre = ''+tbe, detachedDiv = document.createElement('div'), bbValues = ['BeforeBegin', 'previousSibling'], aeValues = ['AfterEnd', 'nextSibling'], bb_ae_PositionHash = { beforebegin: bbValues, afterend: aeValues }, fullPositionHash = { beforebegin: bbValues, afterend: aeValues, afterbegin: ['AfterBegin', 'firstChild'], beforeend: ['BeforeEnd', 'lastChild'] }; return { extend: Ext.dom.AbstractHelper , tableRe: /^(?:table|thead|tbody|tr|td)$/i, tableElRe: /td|tr|tbody|thead/i, useDom : false, createDom: function(o, parentNode){ var el, doc = document, useSet, attr, val, cn, i, l; if (Ext.isArray(o)) { el = doc.createDocumentFragment(); for (i = 0, l = o.length; i < l; i++) { this.createDom(o[i], el); } } else if (typeof o == 'string') { el = doc.createTextNode(o); } else { el = doc.createElement(o.tag || 'div'); useSet = !!el.setAttribute; for (attr in o) { if (!this.confRe.test(attr)) { val = o[attr]; if (attr == 'cls') { el.className = val; } else { if (useSet) { el.setAttribute(attr, val); } else { el[attr] = val; } } } } Ext.DomHelper.applyStyles(el, o.style); if ((cn = o.children || o.cn)) { this.createDom(cn, el); } else if (o.html) { el.innerHTML = o.html; } } if (parentNode) { parentNode.appendChild(el); } return el; }, ieTable: function(depth, openingTags, htmlContent, closingTags){ detachedDiv.innerHTML = [openingTags, htmlContent, closingTags].join(''); var i = -1, el = detachedDiv, ns; while (++i < depth) { el = el.firstChild; } ns = el.nextSibling; if (ns) { ns = el; el = document.createDocumentFragment(); while (ns) { nx = ns.nextSibling; el.appendChild(ns); ns = nx; } } return el; }, insertIntoTable: function(tag, where, destinationEl, html) { var node, before, bb = where == beforebegin, ab = where == afterbegin, be = where == beforeend, ae = where == afterend; if (tag == 'td' && (ab || be) || !this.tableElRe.test(tag) && (bb || ae)) { return null; } before = bb ? destinationEl : ae ? destinationEl.nextSibling : ab ? destinationEl.firstChild : null; if (bb || ae) { destinationEl = destinationEl.parentNode; } if (tag == 'td' || (tag == 'tr' && (be || ab))) { node = this.ieTable(4, trs, html, tre); } else if (((tag == 'tbody' || tag == 'thead') && (be || ab)) || (tag == 'tr' && (bb || ae))) { node = this.ieTable(3, tbs, html, tbe); } else { node = this.ieTable(2, ts, html, te); } destinationEl.insertBefore(node, before); return node; }, createContextualFragment: function(html) { var fragment = document.createDocumentFragment(), length, childNodes; detachedDiv.innerHTML = html; childNodes = detachedDiv.childNodes; length = childNodes.length; while (length--) { fragment.appendChild(childNodes[0]); } return fragment; }, applyStyles: function(el, styles) { if (styles) { if (typeof styles == "function") { styles = styles.call(); } if (typeof styles == "string") { styles = Ext.dom.Element.parseStyles(styles); } if (typeof styles == "object") { Ext.fly(el, '_applyStyles').setStyle(styles); } } }, createHtml: function(spec) { return this.markup(spec); }, doInsert: function(el, o, returnElement, pos, sibling, append) { el = el.dom || Ext.getDom(el); var newNode; if (this.useDom) { newNode = this.createDom(o, null); if (append) { el.appendChild(newNode); } else { (sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el); } } else { newNode = this.insertHtml(pos, el, this.markup(o)); } return returnElement ? Ext.get(newNode, true) : newNode; }, overwrite: function(el, html, returnElement) { var newNode; el = Ext.getDom(el); html = this.markup(html); if (Ext.isIE && this.tableRe.test(el.tagName)) { while (el.firstChild) { el.removeChild(el.firstChild); } if (html) { newNode = this.insertHtml('afterbegin', el, html); return returnElement ? Ext.get(newNode) : newNode; } return null; } el.innerHTML = html; return returnElement ? Ext.get(el.firstChild) : el.firstChild; }, insertHtml: function(where, el, html) { var hashVal, range, rangeEl, setStart, frag; where = where.toLowerCase(); if (el.insertAdjacentHTML) { if (Ext.isIE && this.tableRe.test(el.tagName) && (frag = this.insertIntoTable(el.tagName.toLowerCase(), where, el, html))) { return frag; } if ((hashVal = fullPositionHash[where])) { if (Ext.global.MSApp && Ext.global.MSApp.execUnsafeLocalFunction) { MSApp.execUnsafeLocalFunction(function () { el.insertAdjacentHTML(hashVal[0], html); }); } else { el.insertAdjacentHTML(hashVal[0], html); } return el[hashVal[1]]; } } else { if (el.nodeType === 3) { where = where === 'afterbegin' ? 'beforebegin' : where; where = where === 'beforeend' ? 'afterend' : where; } range = Ext.supports.CreateContextualFragment ? el.ownerDocument.createRange() : undefined; setStart = 'setStart' + (this.endRe.test(where) ? 'After' : 'Before'); if (bb_ae_PositionHash[where]) { if (range) { range[setStart](el); frag = range.createContextualFragment(html); } else { frag = this.createContextualFragment(html); } el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling); return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling']; } else { rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child'; if (el.firstChild) { if (range) { range[setStart](el[rangeEl]); frag = range.createContextualFragment(html); } else { frag = this.createContextualFragment(html); } if (where == afterbegin) { el.insertBefore(frag, el.firstChild); } else { el.appendChild(frag); } } else { el.innerHTML = html; } return el[rangeEl]; } } }, createTemplate: function(o) { var html = this.markup(o); return new Ext.Template(html); } }; })(), function() { Ext.ns('Ext.core'); Ext.DomHelper = Ext.core.DomHelper = new this; }); Ext.define('Ext.Template', { inheritableStatics: { from: function(el, config) { el = Ext.getDom(el); return new this(el.value || el.innerHTML, config || ''); } }, constructor: function(html) { var me = this, args = arguments, buffer = [], i = 0, length = args.length, value; me.initialConfig = {}; if (length === 1 && Ext.isArray(html)) { args = html; length = args.length; } if (length > 1) { for (; i < length; i++) { value = args[i]; if (typeof value == 'object') { Ext.apply(me.initialConfig, value); Ext.apply(me, value); } else { buffer.push(value); } } } else { buffer.push(html); } me.html = buffer.join(''); if (me.compiled) { me.compile(); } }, isTemplate: true, disableFormats: false, re: /\{([\w\-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g, apply: function(values) { var me = this, useFormat = me.disableFormats !== true, fm = Ext.util.Format, tpl = me, ret; if (me.compiled) { return me.compiled(values).join(''); } function fn(m, name, format, args) { if (format && useFormat) { if (args) { args = [values[name]].concat(Ext.functionFactory('return ['+ args +'];')()); } else { args = [values[name]]; } if (format.substr(0, 5) == "this.") { return tpl[format.substr(5)].apply(tpl, args); } else { return fm[format].apply(fm, args); } } else { return values[name] !== undefined ? values[name] : ""; } } ret = me.html.replace(me.re, fn); return ret; }, applyOut: function(values, out) { var me = this; if (me.compiled) { out.push.apply(out, me.compiled(values)); } else { out.push(me.apply(values)); } return out; }, applyTemplate: function () { return this.apply.apply(this, arguments); }, set: function(html, compile) { var me = this; me.html = html; me.compiled = null; return compile ? me.compile() : me; }, compileARe: /\\/g, compileBRe: /(\r\n|\n)/g, compileCRe: /'/g, /** * Compiles the template into an internal function, eliminating the RegEx overhead. * @return {Ext.Template} this */ compile: function() { var me = this, fm = Ext.util.Format, useFormat = me.disableFormats !== true, body, bodyReturn; function fn(m, name, format, args) { if (format && useFormat) { args = args ? ',' + args: ""; if (format.substr(0, 5) != "this.") { format = "fm." + format + '('; } else { format = 'this.' + format.substr(5) + '('; } } else { args = ''; format = "(values['" + name + "'] == undefined ? '' : "; } return "'," + format + "values['" + name + "']" + args + ") ,'"; } bodyReturn = me.html.replace(me.compileARe, '\\\\').replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn); body = "this.compiled = function(values){ return ['" + bodyReturn + "'];};"; eval(body); return me; }, /** * Applies the supplied values to the template and inserts the new node(s) as the first child of el. * * @param {String/HTMLElement/Ext.Element} el The context element * @param {Object/Array} values The template values. See {@link #applyTemplate} for details. * @param {Boolean} returnElement (optional) true to return a Ext.Element. * @return {HTMLElement/Ext.Element} The new node or Element */ insertFirst: function(el, values, returnElement) { return this.doInsert('afterBegin', el, values, returnElement); }, /** * Applies the supplied values to the template and inserts the new node(s) before el. * * @param {String/HTMLElement/Ext.Element} el The context element * @param {Object/Array} values The template values. See {@link #applyTemplate} for details. * @param {Boolean} returnElement (optional) true to return a Ext.Element. * @return {HTMLElement/Ext.Element} The new node or Element */ insertBefore: function(el, values, returnElement) { return this.doInsert('beforeBegin', el, values, returnElement); }, /** * Applies the supplied values to the template and inserts the new node(s) after el. * * @param {String/HTMLElement/Ext.Element} el The context element * @param {Object/Array} values The template values. See {@link #applyTemplate} for details. * @param {Boolean} returnElement (optional) true to return a Ext.Element. * @return {HTMLElement/Ext.Element} The new node or Element */ insertAfter: function(el, values, returnElement) { return this.doInsert('afterEnd', el, values, returnElement); }, /** * Applies the supplied `values` to the template and appends the new node(s) to the specified `el`. * * For example usage see {@link Ext.Template Ext.Template class docs}. * * @param {String/HTMLElement/Ext.Element} el The context element * @param {Object/Array} values The template values. See {@link #applyTemplate} for details. * @param {Boolean} returnElement (optional) true to return an Ext.Element. * @return {HTMLElement/Ext.Element} The new node or Element */ append: function(el, values, returnElement) { return this.doInsert('beforeEnd', el, values, returnElement); }, doInsert: function(where, el, values, returnElement) { var newNode = Ext.DomHelper.insertHtml(where, Ext.getDom(el), this.apply(values)); return returnElement ? Ext.get(newNode) : newNode; }, /** * Applies the supplied values to the template and overwrites the content of el with the new node(s). * * @param {String/HTMLElement/Ext.Element} el The context element * @param {Object/Array} values The template values. See {@link #applyTemplate} for details. * @param {Boolean} returnElement (optional) true to return a Ext.Element. * @return {HTMLElement/Ext.Element} The new node or Element */ overwrite: function(el, values, returnElement) { var newNode = Ext.DomHelper.overwrite(Ext.getDom(el), this.apply(values)); return returnElement ? Ext.get(newNode) : newNode; } }); // @tag core /** * This class parses the XTemplate syntax and calls abstract methods to process the parts. * @private */ Ext.define('Ext.XTemplateParser', { constructor: function (config) { Ext.apply(this, config); }, /** * @property {Number} level The 'for' or 'foreach' loop context level. This is adjusted * up by one prior to calling {@link #doFor} or {@link #doForEach} and down by one after * calling the corresponding {@link #doEnd} that closes the loop. This will be 1 on the * first {@link #doFor} or {@link #doForEach} call. */ /** * This method is called to process a piece of raw text from the tpl. * @param {String} text * @method doText */ // doText: function (text) /** * This method is called to process expressions (like `{[expr]}`). * @param {String} expr The body of the expression (inside "{[" and "]}"). * @method doExpr */ // doExpr: function (expr) /** * This method is called to process simple tags (like `{tag}`). * @method doTag */ // doTag: function (tag) /** * This method is called to process ``. * @method doElse */ // doElse: function () /** * This method is called to process `{% text %}`. * @param {String} text * @method doEval */ // doEval: function (text) /** * This method is called to process ``. If there are other attributes, * these are passed in the actions object. * @param {String} action * @param {Object} actions Other actions keyed by the attribute name (such as 'exec'). * @method doIf */ // doIf: function (action, actions) /** * This method is called to process ``. If there are other attributes, * these are passed in the actions object. * @param {String} action * @param {Object} actions Other actions keyed by the attribute name (such as 'exec'). * @method doElseIf */ // doElseIf: function (action, actions) /** * This method is called to process ``. If there are other attributes, * these are passed in the actions object. * @param {String} action * @param {Object} actions Other actions keyed by the attribute name (such as 'exec'). * @method doSwitch */ // doSwitch: function (action, actions) /** * This method is called to process ``. If there are other attributes, * these are passed in the actions object. * @param {String} action * @param {Object} actions Other actions keyed by the attribute name (such as 'exec'). * @method doCase */ // doCase: function (action, actions) /** * This method is called to process ``. * @method doDefault */ // doDefault: function () /** * This method is called to process ``. It is given the action type that started * the tpl and the set of additional actions. * @param {String} type The type of action that is being ended. * @param {Object} actions The other actions keyed by the attribute name (such as 'exec'). * @method doEnd */ // doEnd: function (type, actions) /** * This method is called to process ``. If there are other attributes, * these are passed in the actions object. * @param {String} action * @param {Object} actions Other actions keyed by the attribute name (such as 'exec'). * @method doFor */ // doFor: function (action, actions) /** * This method is called to process ``. If there are other * attributes, these are passed in the actions object. * @param {String} action * @param {Object} actions Other actions keyed by the attribute name (such as 'exec'). * @method doForEach */ // doForEach: function (action, actions) /** * This method is called to process ``. If there are other attributes, * these are passed in the actions object. * @param {String} action * @param {Object} actions Other actions keyed by the attribute name. * @method doExec */ // doExec: function (action, actions) /** * This method is called to process an empty ``. This is unlikely to need to be * implemented, so a default (do nothing) version is provided. * @method */ doTpl: Ext.emptyFn, parse: function (str) { var me = this, len = str.length, aliases = { elseif: 'elif' }, topRe = me.topRe, actionsRe = me.actionsRe, index, stack, s, m, t, prev, frame, subMatch, begin, end, actions, prop; me.level = 0; me.stack = stack = []; for (index = 0; index < len; index = end) { topRe.lastIndex = index; m = topRe.exec(str); if (!m) { me.doText(str.substring(index, len)); break; } begin = m.index; end = topRe.lastIndex; if (index < begin) { me.doText(str.substring(index, begin)); } if (m[1]) { end = str.indexOf('%}', begin+2); me.doEval(str.substring(begin+2, end)); end += 2; } else if (m[2]) { end = str.indexOf(']}', begin+2); me.doExpr(str.substring(begin+2, end)); end += 2; } else if (m[3]) { // if ('{' token) me.doTag(m[3]); } else if (m[4]) { // content of a tag actions = null; while ((subMatch = actionsRe.exec(m[4])) !== null) { s = subMatch[2] || subMatch[3]; if (s) { s = Ext.String.htmlDecode(s); // decode attr value t = subMatch[1]; t = aliases[t] || t; actions = actions || {}; prev = actions[t]; if (typeof prev == 'string') { actions[t] = [prev, s]; } else if (prev) { actions[t].push(s); } else { actions[t] = s; } } } if (!actions) { if (me.elseRe.test(m[4])) { me.doElse(); } else if (me.defaultRe.test(m[4])) { me.doDefault(); } else { me.doTpl(); stack.push({ type: 'tpl' }); } } else if (actions['if']) { me.doIf(actions['if'], actions); stack.push({ type: 'if' }); } else if (actions['switch']) { me.doSwitch(actions['switch'], actions); stack.push({ type: 'switch' }); } else if (actions['case']) { me.doCase(actions['case'], actions); } else if (actions['elif']) { me.doElseIf(actions['elif'], actions); } else if (actions['for']) { ++me.level; // Extract property name to use from indexed item if (prop = me.propRe.exec(m[4])) { actions.propName = prop[1] || prop[2]; } me.doFor(actions['for'], actions); stack.push({ type: 'for', actions: actions }); } else if (actions['foreach']) { ++me.level; // Extract property name to use from indexed item if (prop = me.propRe.exec(m[4])) { actions.propName = prop[1] || prop[2]; } me.doForEach(actions['foreach'], actions); stack.push({ type: 'foreach', actions: actions }); } else if (actions.exec) { me.doExec(actions.exec, actions); stack.push({ type: 'exec', actions: actions }); } /* else { // todo - error } */ } else if (m[0].length === 5) { // if the length of m[0] is 5, assume that we're dealing with an opening tpl tag with no attributes (e.g. ...) // in this case no action is needed other than pushing it on to the stack stack.push({ type: 'tpl' }); } else { frame = stack.pop(); me.doEnd(frame.type, frame.actions); if (frame.type == 'for' || frame.type == 'foreach') { --me.level; } } } }, // Internal regexes topRe: /(?:(\{\%)|(\{\[)|\{([^{}]+)\})|(?:]*)\>)|(?:<\/tpl>)/g, actionsRe: /\s*(elif|elseif|if|for|foreach|exec|switch|case|eval|between)\s*\=\s*(?:(?:"([^"]*)")|(?:'([^']*)'))\s*/g, propRe: /prop=(?:(?:"([^"]*)")|(?:'([^']*)'))/, defaultRe: /^\s*default\s*$/, elseRe: /^\s*else\s*$/ }); Ext.define('Ext.XTemplateCompiler', { extend: Ext.XTemplateParser , useEval: Ext.isGecko, useIndex: Ext.isIE8m, useFormat: true, propNameRe: /^[\w\d\$]*$/, compile: function (tpl) { var me = this, code = me.generate(tpl); return me.useEval ? me.evalTpl(code) : (new Function('Ext', code))(Ext); }, generate: function (tpl) { var me = this, definitions = 'var fm=Ext.util.Format,ts=Object.prototype.toString;', code; me.maxLevel = 0; me.body = [ 'var c0=values, a0=' + me.createArrayTest(0) + ', p0=parent, n0=xcount, i0=xindex, k0, v;\n' ]; if (me.definitions) { if (typeof me.definitions === 'string') { me.definitions = [me.definitions, definitions ]; } else { me.definitions.push(definitions); } } else { me.definitions = [ definitions ]; } me.switches = []; me.parse(tpl); me.definitions.push( (me.useEval ? '$=' : 'return') + ' function (' + me.fnArgs + ') {', me.body.join(''), '}' ); code = me.definitions.join('\n'); me.definitions.length = me.body.length = me.switches.length = 0; delete me.definitions; delete me.body; delete me.switches; return code; }, doText: function (text) { var me = this, out = me.body; text = text.replace(me.aposRe, "\\'").replace(me.newLineRe, '\\n'); if (me.useIndex) { out.push('out[out.length]=\'', text, '\'\n'); } else { out.push('out.push(\'', text, '\')\n'); } }, doExpr: function (expr) { var out = this.body; out.push('if ((v=' + expr + ') != null) out'); if (this.useIndex) { out.push('[out.length]=v+\'\'\n'); } else { out.push('.push(v+\'\')\n'); } }, doTag: function (tag) { var expr = this.parseTag(tag); if (expr) { this.doExpr(expr); } else { this.doText('{' + tag + '}'); } }, doElse: function () { this.body.push('} else {\n'); }, doEval: function (text) { this.body.push(text, '\n'); }, doIf: function (action, actions) { var me = this; if (action === '.') { me.body.push('if (values) {\n'); } else if (me.propNameRe.test(action)) { me.body.push('if (', me.parseTag(action), ') {\n'); } else { me.body.push('if (', me.addFn(action), me.callFn, ') {\n'); } if (actions.exec) { me.doExec(actions.exec); } }, doElseIf: function (action, actions) { var me = this; if (action === '.') { me.body.push('else if (values) {\n'); } else if (me.propNameRe.test(action)) { me.body.push('} else if (', me.parseTag(action), ') {\n'); } else { me.body.push('} else if (', me.addFn(action), me.callFn, ') {\n'); } if (actions.exec) { me.doExec(actions.exec); } }, doSwitch: function (action) { var me = this; if (action === '.') { me.body.push('switch (values) {\n'); } else if (me.propNameRe.test(action)) { me.body.push('switch (', me.parseTag(action), ') {\n'); } else { me.body.push('switch (', me.addFn(action), me.callFn, ') {\n'); } me.switches.push(0); }, doCase: function (action) { var me = this, cases = Ext.isArray(action) ? action : [action], n = me.switches.length - 1, match, i; if (me.switches[n]) { me.body.push('break;\n'); } else { me.switches[n]++; } for (i = 0, n = cases.length; i < n; ++i) { match = me.intRe.exec(cases[i]); cases[i] = match ? match[1] : ("'" + cases[i].replace(me.aposRe,"\\'") + "'"); } me.body.push('case ', cases.join(': case '), ':\n'); }, doDefault: function () { var me = this, n = me.switches.length - 1; if (me.switches[n]) { me.body.push('break;\n'); } else { me.switches[n]++; } me.body.push('default:\n'); }, doEnd: function (type, actions) { var me = this, L = me.level-1; if (type == 'for' || type == 'foreach') { if (actions.exec) { me.doExec(actions.exec); } me.body.push('}\n'); me.body.push('parent=p',L,';values=r',L+1,';xcount=n'+L+';xindex=i',L,'+1;xkey=k',L,';\n'); } else if (type == 'if' || type == 'switch') { me.body.push('}\n'); } }, doFor: function (action, actions) { var me = this, s, L = me.level, up = L-1, parentAssignment; if (action === '.') { s = 'values'; } else if (me.propNameRe.test(action)) { s = me.parseTag(action); } else { s = me.addFn(action) + me.callFn; } if (me.maxLevel < L) { me.maxLevel = L; me.body.push('var '); } if (action == '.') { parentAssignment = 'c' + L; } else { parentAssignment = 'a' + up + '?c' + up + '[i' + up + ']:c' + up; } me.body.push('i',L,'=0,n', L, '=0,c',L,'=',s,',a',L,'=', me.createArrayTest(L),',r',L,'=values,p',L,',k',L,';\n', 'p',L,'=parent=',parentAssignment,'\n', 'if (c',L,'){if(a',L,'){n', L,'=c', L, '.length;}else if (c', L, '.isMixedCollection){c',L,'=c',L,'.items;n',L,'=c',L,'.length;}else if(c',L,'.isStore){c',L,'=c',L,'.data.items;n',L,'=c',L,'.length;}else{c',L,'=[c',L,'];n',L,'=1;}}\n', 'for (xcount=n',L,';i',L,'1){ out.push("',actions.between,'"); } \n'); } }, doForEach: function (action, actions) { var me = this, s, L = me.level, up = L-1, parentAssignment; if (action === '.') { s = 'values'; } else if (me.propNameRe.test(action)) { s = me.parseTag(action); } else { s = me.addFn(action) + me.callFn; } if (me.maxLevel < L) { me.maxLevel = L; me.body.push('var '); } if (action == '.') { parentAssignment = 'c' + L; } else { parentAssignment = 'a' + up + '?c' + up + '[i' + up + ']:c' + up; } me.body.push('i',L,'=-1,n',L,'=0,c',L,'=',s,',a',L,'=',me.createArrayTest(L),',r',L,'=values,p',L,',k',L,';\n', 'p',L,'=parent=',parentAssignment,'\n', 'for(k',L,' in c',L,'){\n', 'xindex=++i',L,'+1;\n', 'xkey=k',L,';\n', 'values=c',L,'[k',L,'];'); if (actions.propName) { me.body.push('.', actions.propName); } if (actions.between) { me.body.push('if(xindex>1){ out.push("',actions.between,'"); } \n'); } }, createArrayTest: ('isArray' in Array) ? function(L) { return 'Array.isArray(c' + L + ')'; } : function(L) { return 'ts.call(c' + L + ')==="[object Array]"'; }, doExec: function (action, actions) { var me = this, name = 'f' + me.definitions.length; me.definitions.push('function ' + name + '(' + me.fnArgs + ') {', ' try { with(values) {', ' ' + action, ' }} catch(e) {', '}', '}'); me.body.push(name + me.callFn + '\n'); }, addFn: function (body) { var me = this, name = 'f' + me.definitions.length; if (body === '.') { me.definitions.push('function ' + name + '(' + me.fnArgs + ') {', ' return values', '}'); } else if (body === '..') { me.definitions.push('function ' + name + '(' + me.fnArgs + ') {', ' return parent', '}'); } else { me.definitions.push('function ' + name + '(' + me.fnArgs + ') {', ' try { with(values) {', ' return(' + body + ')', ' }} catch(e) {', '}', '}'); } return name; }, parseTag: function (tag) { var me = this, m = me.tagRe.exec(tag), name, format, args, math, v; if (!m) { return null; } name = m[1]; format = m[2]; args = m[3]; math = m[4]; if (name == '.') { if (!me.validTypes) { me.definitions.push('var validTypes={string:1,number:1,boolean:1};'); me.validTypes = true; } v = 'validTypes[typeof values] || ts.call(values) === "[object Date]" ? values : ""'; } else if (name == '#') { v = 'xindex'; } else if (name == '$') { v = 'xkey'; } else if (name.substr(0, 7) == "parent.") { v = name; } else if (isNaN(name) && name.indexOf('-') == -1 && name.indexOf('.') != -1) { v = "values." + name; } else { v = "values['" + name + "']"; } if (math) { v = '(' + v + math + ')'; } if (format && me.useFormat) { args = args ? ',' + args : ""; if (format.substr(0, 5) != "this.") { format = "fm." + format + '('; } else { format += '('; } } else { return v; } return format + v + args + ')'; }, evalTpl: function ($) { eval($); return $; }, newLineRe: /\r\n|\r|\n/g, aposRe: /[']/g, intRe: /^\s*(\d+)\s*$/, tagRe: /^([\w-\.\#\$]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\/]\s?[\d\.\+\-\*\/\(\)]+)?$/ }, function () { var proto = this.prototype; proto.fnArgs = 'out,values,parent,xindex,xcount,xkey'; proto.callFn = '.call(this,' + proto.fnArgs + ')'; }); // @tag core /** * A template class that supports advanced functionality like: * * - Autofilling arrays using templates and sub-templates * - Conditional processing with basic comparison operators * - Basic math function support * - Execute arbitrary inline code with special built-in template variables * - Custom member functions * - Many special tags and built-in operators that aren't defined as part of the API, but are supported in the templates that can be created * * XTemplate provides the templating mechanism built into {@link Ext.view.View}. * * The {@link Ext.Template} describes the acceptable parameters to pass to the constructor. The following examples * demonstrate all of the supported features. * * # Sample Data * * This is the data object used for reference in each code example: * * var data = { * name: 'Don Griffin', * title: 'Senior Technomage', * company: 'Sencha Inc.', * drinks: ['Coffee', 'Water', 'More Coffee'], * kids: [ * { name: 'Aubrey', age: 17 }, * { name: 'Joshua', age: 13 }, * { name: 'Cale', age: 10 }, * { name: 'Nikol', age: 5 }, * { name: 'Solomon', age: 0 } * ] * }; * * # Auto filling of arrays * * The **tpl** tag and the **for** operator are used to process the provided data object: * * - If the value specified in for is an array, it will auto-fill, repeating the template block inside the tpl * tag for each item in the array. * - If for="." is specified, the data object provided is examined. * - If between="..." is specified, the provided value will be inserted between the items. * This is also supported in the "foreach" looping template. * - While processing an array, the special variable {#} will provide the current array index + 1 (starts at 1, not 0). * * Examples: * * ... * ... * ... * ... * * Using the sample data above: * * var tpl = new Ext.XTemplate( * '

Kids: ', * '', * '

{#}. {name}

', * '

' * ); * tpl.overwrite(panel.body, data.kids); * * An example illustrating how the **for** property can be leveraged to access specified members of the provided data * object to populate the template: * * var tpl = new Ext.XTemplate( * '

Name: {name}

', * '

Title: {title}

', * '

Company: {company}

', * '

Kids: ', * '', * '

{name}

', * '

' * ); * tpl.overwrite(panel.body, data); * * Flat arrays that contain values (and not objects) can be auto-rendered using the special **`{.}`** variable inside a * loop. This variable will represent the value of the array at the current index: * * var tpl = new Ext.XTemplate( * '

{name}\'s favorite beverages:

', * '', * '
- {.}
', * '
' * ); * tpl.overwrite(panel.body, data); * * When processing a sub-template, for example while looping through a child array, you can access the parent object's * members via the **parent** object: * * var tpl = new Ext.XTemplate( * '

Name: {name}

', * '

Kids: ', * '', * '', * '

{name}

', * '

Dad: {parent.name}

', * '
', * '

' * ); * tpl.overwrite(panel.body, data); * * The **foreach** operator is used to loop over an object's properties. The following * example demonstrates looping over the main data object's properties: * * var tpl = new Ext.XTemplate( * '
', * '', * '
{$}
', // the special **`{$}`** variable contains the property name * '
{.}
', // within the loop, the **`{.}`** variable is set to the property value * '
', * '
' * ); * tpl.overwrite(panel.body, data); * * # Conditional processing with basic comparison operators * * The **tpl** tag and the **if** operator are used to provide conditional checks for deciding whether or not to render * specific parts of the template. * * Using the sample data above: * * var tpl = new Ext.XTemplate( * '

Name: {name}

', * '

Kids: ', * '', * '', * '

{name}

', * '
', * '

' * ); * tpl.overwrite(panel.body, data); * * More advanced conditionals are also supported: * * var tpl = new Ext.XTemplate( * '

Name: {name}

', * '

Kids: ', * '', * '

{name} is a ', * '', * '

teenager

', * '', * '

kid

', * '', * '

baby

', * '
', * '

' * ); * * var tpl = new Ext.XTemplate( * '

Name: {name}

', * '

Kids: ', * '', * '

{name} is a ', * '', * '', * '

girl

', * '', * '

boy

', * '
', * '

' * ); * * A `break` is implied between each case and default, however, multiple cases can be listed * in a single <tpl> tag. * * # Using double quotes * * Examples: * * var tpl = new Ext.XTemplate( * "Child", * "Teenager", * "...", * '...', * "", * "Hello" * ); * * # Basic math support * * The following basic math operators may be applied directly on numeric data values: * * + - * / * * For example: * * var tpl = new Ext.XTemplate( * '

Name: {name}

', * '

Kids: ', * '', * '', * '

{#}: {name}

', * '

In 5 Years: {age+5}

', * '

Dad: {parent.name}

', * '
', * '

' * ); * tpl.overwrite(panel.body, data); * * # Execute arbitrary inline code with special built-in template variables * * Anything between `{[ ... ]}` is considered code to be executed in the scope of the template. * The expression is evaluated and the result is included in the generated result. There are * some special variables available in that code: * * - **out**: The output array into which the template is being appended (using `push` to later * `join`). * - **values**: The values in the current scope. If you are using scope changing sub-templates, * you can change what values is. * - **parent**: The scope (values) of the ancestor template. * - **xindex**: If you are in a "for" or "foreach" looping template, the index of the loop you are in (1-based). * - **xcount**: If you are in a "for" looping template, the total length of the array you are looping. * - **xkey**: If you are in a "foreach" looping template, the key of the current property * being examined. * * This example demonstrates basic row striping using an inline code block and the xindex variable: * * var tpl = new Ext.XTemplate( * '

Name: {name}

', * '

Company: {[values.company.toUpperCase() + ", " + values.title]}

', * '

Kids: ', * '', * '

', * '{name}', * '
', * '

' * ); * * Any code contained in "verbatim" blocks (using "{% ... %}") will be inserted directly in * the generated code for the template. These blocks are not included in the output. This * can be used for simple things like break/continue in a loop, or control structures or * method calls (when they don't produce output). The `this` references the template instance. * * var tpl = new Ext.XTemplate( * '

Name: {name}

', * '

Company: {[values.company.toUpperCase() + ", " + values.title]}

', * '

Kids: ', * '', * '{% if (xindex % 2 === 0) continue; %}', * '{name}', * '{% if (xindex > 100) break; %}', * '

', * '

' * ); * * # Template member functions * * One or more member functions can be specified in a configuration object passed into the XTemplate constructor for * more complex processing: * * var tpl = new Ext.XTemplate( * '

Name: {name}

', * '

Kids: ', * '', * '', * '

Girl: {name} - {age}

', * '', * '

Boy: {name} - {age}

', * '
', * '', * '

{name} is a baby!

', * '
', * '

', * { * // XTemplate configuration: * disableFormats: true, * // member functions: * isGirl: function(name){ * return name == 'Aubrey' || name == 'Nikol'; * }, * isBaby: function(age){ * return age < 1; * } * } * ); * tpl.overwrite(panel.body, data); */ Ext.define('Ext.XTemplate', { extend: Ext.Template , /** * @private */ emptyObj: {}, /** * @cfg {Boolean} compiled * Only applies to {@link Ext.Template}, XTemplates are compiled automatically on the * first call to {@link #apply} or {@link #applyOut}. * @hide */ /** * @cfg {String/Array} definitions * Optional. A statement, or array of statements which set up `var`s which may then * be accessed within the scope of the generated function. */ apply: function(values, parent) { return this.applyOut(values, [], parent).join(''); }, applyOut: function(values, out, parent) { var me = this, compiler; if (!me.fn) { compiler = new Ext.XTemplateCompiler({ useFormat: me.disableFormats !== true, definitions: me.definitions }); me.fn = compiler.compile(me.html); } try { me.fn(out, values, parent || me.emptyObj, 1, 1); } catch (e) { } return out; }, /** * Does nothing. XTemplates are compiled automatically, so this function simply returns this. * @return {Ext.XTemplate} this */ compile: function() { return this; }, statics: { /** * Gets an `XTemplate` from an object (an instance of an {@link Ext#define}'d class). * Many times, templates are configured high in the class hierarchy and are to be * shared by all classes that derive from that base. To further complicate matters, * these templates are seldom actual instances but are rather configurations. For * example: * * Ext.define('MyApp.Class', { * extraCls: 'extra-class', * * someTpl: [ * '
', * { * * emitClass: function(out) { * out.push(this.owner.extraCls); * } * }] * }); * * The goal being to share that template definition with all instances and even * instances of derived classes, until `someTpl` is overridden. This method will * "upgrade" these configurations to be real `XTemplate` instances *in place* (to * avoid creating one instance per object). * * The resulting XTemplate will have an `owner` reference injected which refers back * to the owning object whether that is an object which has an *own instance*, or a * class prototype. Through this link, XTemplate member functions will be able to access * prototype properties of its owning class. * * @param {Object} instance The object from which to get the `XTemplate` (must be * an instance of an {@link Ext#define}'d class). * @param {String} name The name of the property by which to get the `XTemplate`. * @return {Ext.XTemplate} The `XTemplate` instance or null if not found. * @protected * @static */ getTpl: function (instance, name) { var tpl = instance[name], // go for it! 99% of the time we will get it! owner; if (tpl && !tpl.isTemplate) { // tpl is just a configuration (not an instance) // create the template instance from the configuration: tpl = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl); // and replace the reference with the new instance: if (instance.hasOwnProperty(name)) { // the tpl is on the instance owner = instance; } else { // must be somewhere in the prototype chain for (owner = instance.self.prototype; owner && !owner.hasOwnProperty(name); owner = owner.superclass) { } } owner[name] = tpl; tpl.owner = owner; } // else !tpl (no such tpl) or the tpl is an instance already... either way, tpl // is ready to return return tpl || null; } } }); // @tag dom,core // @require Helper.js // @define Ext.dom.Query // @define Ext.core.DomQuery // @define Ext.DomQuery /* * This is code is also distributed under MIT license for use * with jQuery and prototype JavaScript libraries. */ /** * @class Ext.dom.Query * @alternateClassName Ext.DomQuery * @alternateClassName Ext.core.DomQuery * @singleton * * Provides high performance selector/xpath processing by compiling queries into reusable functions. New pseudo classes * and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in). * * DomQuery supports most of the [CSS3 selectors spec][1], along with some custom selectors and basic XPath. * * All selectors, attribute filters and pseudos below can be combined infinitely in any order. For example * `div.foo:nth-child(odd)[@foo=bar].bar:first` would be a perfectly valid selector. Node filters are processed * in the order in which they appear, which allows you to optimize your queries for your document structure. * * ## Simple Selectors * * For performance reasons, some query methods accept selectors that are termed as **simple selectors**. A simple * selector is a selector that does not include contextual information about any parent/sibling elements. * * Some examples of valid simple selectors: * * var simple = '.foo'; // Only asking for the class name on the element * var simple = 'div.bar'; // Only asking for the tag/class name on the element * var simple = '[href];' // Asking for an attribute on the element. * var simple = ':not(.foo)'; // Only asking for the non-matches against the class name * var simple = 'span:first-child'; // Doesn't require any contextual information about the parent node * * Simple examples of invalid simple selectors: * * var notSimple = 'div.foo div.bar'; * var notSimple = 'span + div'; * * ## Element Selectors: * * - **`*`** any element * - **`E`** an element with the tag E * - **`E F`** All descendent elements of E that have the tag F * - **`E > F`** or **E/F** all direct children elements of E that have the tag F * - **`E + F`** all elements with the tag F that are immediately preceded by an element with the tag E * - **`E ~ F`** all elements with the tag F that are preceded by a sibling element with the tag E * * ## Attribute Selectors: * * The use of `@` and quotes are optional. For example, `div[@foo='bar']` is also a valid attribute selector. * * - **`E[foo]`** has an attribute "foo" * - **`E[foo=bar]`** has an attribute "foo" that equals "bar" * - **`E[foo^=bar]`** has an attribute "foo" that starts with "bar" * - **`E[foo$=bar]`** has an attribute "foo" that ends with "bar" * - **`E[foo*=bar]`** has an attribute "foo" that contains the substring "bar" * - **`E[foo%=2]`** has an attribute "foo" that is evenly divisible by 2 * - **`E[foo!=bar]`** attribute "foo" does not equal "bar" * * ## Pseudo Classes: * * - **`E:first-child`** E is the first child of its parent * - **`E:last-child`** E is the last child of its parent * - **`E:nth-child(_n_)`** E is the _n_th child of its parent (1 based as per the spec) * - **`E:nth-child(odd)`** E is an odd child of its parent * - **`E:nth-child(even)`** E is an even child of its parent * - **`E:only-child`** E is the only child of its parent * - **`E:checked`** E is an element that is has a checked attribute that is true (e.g. a radio or checkbox) * - **`E:first`** the first E in the resultset * - **`E:last`** the last E in the resultset * - **`E:nth(_n_)`** the _n_th E in the resultset (1 based) * - **`E:odd`** shortcut for :nth-child(odd) * - **`E:even`** shortcut for :nth-child(even) * - **`E:contains(foo)`** E's innerHTML contains the substring "foo" * - **`E:nodeValue(foo)`** E contains a textNode with a nodeValue that equals "foo" * - **`E:not(S)`** an E element that does not match simple selector S * - **`E:has(S)`** an E element that has a descendent that matches simple selector S * - **`E:next(S)`** an E element whose next sibling matches simple selector S * - **`E:prev(S)`** an E element whose previous sibling matches simple selector S * - **`E:any(S1|S2|S2)`** an E element which matches any of the simple selectors S1, S2 or S3 * - **`E:visible(true)`** an E element which is deeply visible according to {@link Ext.dom.Element#isVisible} * * ## CSS Value Selectors: * * - **`E{display=none}`** css value "display" that equals "none" * - **`E{display^=none}`** css value "display" that starts with "none" * - **`E{display$=none}`** css value "display" that ends with "none" * - **`E{display*=none}`** css value "display" that contains the substring "none" * - **`E{display%=2}`** css value "display" that is evenly divisible by 2 * - **`E{display!=none}`** css value "display" that does not equal "none" * * ## XML Namespaces: * - **`ns|E`** an element with tag E and namespace prefix ns * * [1]: http://www.w3.org/TR/2005/WD-css3-selectors-20051215/#selectors */ Ext.ns('Ext.core'); Ext.dom.Query = Ext.core.DomQuery = Ext.DomQuery = (function() { var DQ, doc = document, cache = {}, simpleCache = {}, valueCache = {}, useClassList = !!doc.documentElement.classList, useElementPointer = !!doc.documentElement.firstElementChild, useChildrenCollection = (function() { var d = doc.createElement('div'); d.innerHTML = 'text'; return d.children && (d.children.length === 0); })(), nonSpace = /\S/, trimRe = /^\s+|\s+$/g, tplRe = /\{(\d+)\}/g, modeRe = /^(\s?[\/>+~]\s?|\s|$)/, tagTokenRe = /^(#)?([\w\-\*\|\\]+)/, nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/, startIdRe = /^\s*#/, // This is for IE MSXML which does not support expandos. // IE runs the same speed using setAttribute, however FF slows way down // and Safari completely fails so they need to continue to use expandos. isIE = window.ActiveXObject ? true : false, key = 30803, longHex = /\\([0-9a-fA-F]{6})/g, shortHex = /\\([0-9a-fA-F]{1,6})\s{0,1}/g, nonHex = /\\([^0-9a-fA-F]{1})/g, escapes = /\\/g, num, hasEscapes, // True if the browser supports the following syntax: // document.getElementsByTagName('namespacePrefix:tagName') supportsColonNsSeparator = (function () { var xmlDoc, xmlString = ''; if (window.DOMParser) { xmlDoc = (new DOMParser()).parseFromString(xmlString, "application/xml"); } else { xmlDoc = new ActiveXObject("Microsoft.XMLDOM"); xmlDoc.loadXML(xmlString); } return !!xmlDoc.getElementsByTagName('a:b').length; })(), // replaces a long hex regex match group with the appropriate ascii value // $args indicate regex match pos longHexToChar = function($0, $1) { return String.fromCharCode(parseInt($1, 16)); }, // converts a shortHex regex match to the long form shortToLongHex = function($0, $1) { while ($1.length < 6) { $1 = '0' + $1; } return '\\' + $1; }, // converts a single char escape to long escape form charToLongHex = function($0, $1) { num = $1.charCodeAt(0).toString(16); if (num.length === 1) { num = '0' + num; } return '\\0000' + num; }, // Un-escapes an input selector string. Assumes all escape sequences have been // normalized to the css '\\0000##' 6-hex-digit style escape sequence : // will not handle any other escape formats unescapeCssSelector = function(selector) { return (hasEscapes) ? selector.replace(longHex, longHexToChar) : selector; }, // checks if the path has escaping & does any appropriate replacements setupEscapes = function(path) { hasEscapes = (path.indexOf('\\') > -1); if (hasEscapes) { path = path .replace(shortHex, shortToLongHex) .replace(nonHex, charToLongHex) .replace(escapes, '\\\\'); // double the '\' for js compilation } return path; }; // this eval is stop the compressor from // renaming the variable to something shorter eval("var batch = 30803, child, next, prev, byClassName;"); // Retrieve the child node from a particular // parent at the specified index. child = useChildrenCollection ? function child(parent, index) { return parent.children[index]; } : function child(parent, index) { var i = 0, n = parent.firstChild; while (n) { if (n.nodeType == 1) { if (++i == index) { return n; } } n = n.nextSibling; } return null; }; // retrieve the next element node next = useElementPointer ? function(n) { return n.nextElementSibling; } : function(n) { while ((n = n.nextSibling) && n.nodeType != 1); return n; }; // retrieve the previous element node prev = useElementPointer ? function(n) { return n.previousElementSibling; } : function(n) { while ((n = n.previousSibling) && n.nodeType != 1); return n; }; // Mark each child node with a nodeIndex skipping and // removing empty text nodes. function children(parent) { var n = parent.firstChild, nodeIndex = -1, nextNode; while (n) { nextNode = n.nextSibling; // clean worthless empty nodes. if (n.nodeType == 3 && !nonSpace.test(n.nodeValue)) { parent.removeChild(n); } else { // add an expando nodeIndex n.nodeIndex = ++nodeIndex; } n = nextNode; } return this; } // nodeSet - array of nodes // cls - CSS Class byClassName = useClassList ? // Use classList API where available: http://jsperf.com/classlist-vs-old-school-check/ function (nodeSet, cls) { cls = unescapeCssSelector(cls); if (!cls) { return nodeSet; } var result = [], ri = -1, i, ci, classList; for (i = 0; ci = nodeSet[i]; i++) { classList = ci.classList; if (classList) { if (classList.contains(cls)) { result[++ri] = ci; } } else if ((' ' + ci.className + ' ').indexOf(cls) !== -1) { // Some elements types (SVG) may not always have a classList // in some browsers, so fallback to the old style here result[++ri] = ci; } } return result; } : function (nodeSet, cls) { cls = unescapeCssSelector(cls); if (!cls) { return nodeSet; } var result = [], ri = -1, i, ci; for (i = 0; ci = nodeSet[i]; i++) { if ((' ' + ci.className + ' ').indexOf(cls) !== -1) { result[++ri] = ci; } } return result; }; function attrValue(n, attr) { // if its an array, use the first node. if (!n.tagName && typeof n.length != "undefined") { n = n[0]; } if (!n) { return null; } if (attr == "for") { return n.htmlFor; } if (attr == "class" || attr == "className") { return n.className; } return n.getAttribute(attr) || n[attr]; } // ns - nodes // mode - false, /, >, +, ~ // tagName - defaults to "*" function getNodes(ns, mode, tagName) { var result = [], ri = -1, cs, i, ni, j, ci, cn, utag, n, cj; if (!ns) { return result; } tagName = tagName.replace('|', ':') || "*"; // convert to array if (typeof ns.getElementsByTagName != "undefined") { ns = [ns]; } // no mode specified, grab all elements by tagName // at any depth if (!mode) { tagName = unescapeCssSelector(tagName); if (!supportsColonNsSeparator && DQ.isXml(ns[0]) && tagName.indexOf(':') !== -1) { // Some browsers (e.g. WebKit and Opera do not support the following syntax // in xml documents: getElementsByTagName('ns:tagName'). To work around // this, we remove the namespace prefix from the tagName, get the elements // by tag name only, and then compare each element's tagName property to for (i = 0; ni = ns[i]; i++) { cs = ni.getElementsByTagName(tagName.split(':').pop()); for (j = 0; ci = cs[j]; j++) { if (ci.tagName === tagName) { result[++ri] = ci; } } } } else { for (i = 0; ni = ns[i]; i++) { cs = ni.getElementsByTagName(tagName); for (j = 0; ci = cs[j]; j++) { result[++ri] = ci; } } } } else if (mode == "/" || mode == ">") { utag = tagName.toUpperCase(); for (i = 0; ni = ns[i]; i++) { cn = ni.childNodes; for (j = 0; cj = cn[j]; j++) { if (cj.nodeName == utag || cj.nodeName == tagName || tagName == '*') { result[++ri] = cj; } } } } else if (mode == "+") { utag = tagName.toUpperCase(); for (i = 0; n = ns[i]; i++) { while ((n = n.nextSibling) && n.nodeType != 1); if (n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')) { result[++ri] = n; } } } else if (mode == "~") { utag = tagName.toUpperCase(); for (i = 0; n = ns[i]; i++) { while ((n = n.nextSibling)) { if (n.nodeName == utag || n.nodeName == tagName || tagName == '*') { result[++ri] = n; } } } } return result; } function concat(a, b) { a.push.apply(a, b); return a; } function byTag(cs, tagName) { if (cs.tagName || cs === doc) { cs = [cs]; } if (!tagName) { return cs; } var result = [], ri = -1, i, ci; tagName = tagName.toLowerCase(); for (i = 0; ci = cs[i]; i++) { if (ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName) { result[++ri] = ci; } } return result; } function byId(cs, id) { id = unescapeCssSelector(id); if (cs.tagName || cs === doc) { cs = [cs]; } if (!id) { return cs; } var result = [], ri = -1, i, ci; for (i = 0; ci = cs[i]; i++) { if (ci && ci.id == id) { result[++ri] = ci; return result; } } return result; } function byAttribute(cs, attr, value, op, custom) { var result = [], ri = -1, useGetStyle = custom == "{", fn = DQ.operators[op], a, xml, hasXml, i, ci; value = unescapeCssSelector(value); for (i = 0; ci = cs[i]; i++) { if (ci.nodeType === 1) { if (!hasXml) { xml = DQ.isXml(ci); hasXml = true; } if (!xml) { if (useGetStyle) { a = DQ.getStyle(ci, attr); } else if (attr == "class" || attr == "className") { a = ci.className; } else if (attr == "for") { a = ci.htmlFor; } else if (attr == "href") { a = ci.getAttribute("href", 2); } else { a = ci.getAttribute(attr); } } else { a = ci.getAttribute(attr); } if ((fn && fn(a, value)) || (!fn && a)) { result[++ri] = ci; } } } return result; } function byPseudo(cs, name, value) { value = unescapeCssSelector(value); return DQ.pseudos[name](cs, value); } function nodupIEXml(cs) { var d = ++key, r, i, len, c; cs[0].setAttribute("_nodup", d); r = [cs[0]]; for (i = 1, len = cs.length; i < len; i++) { c = cs[i]; if (!c.getAttribute("_nodup") != d) { c.setAttribute("_nodup", d); r[r.length] = c; } } for (i = 0, len = cs.length; i < len; i++) { cs[i].removeAttribute("_nodup"); } return r; } function nodup(cs) { if (!cs) { return []; } var len = cs.length, c, i, r = cs, cj, ri = -1, d, j; if (!len || typeof cs.nodeType != "undefined" || len == 1) { return cs; } if (isIE && typeof cs[0].selectSingleNode != "undefined") { return nodupIEXml(cs); } d = ++key; cs[0]._nodup = d; for (i = 1; c = cs[i]; i++) { if (c._nodup != d) { c._nodup = d; } else { r = []; for (j = 0; j < i; j++) { r[++ri] = cs[j]; } for (j = i + 1; cj = cs[j]; j++) { if (cj._nodup != d) { cj._nodup = d; r[++ri] = cj; } } return r; } } return r; } function quickDiffIEXml(c1, c2) { var d = ++key, r = [], i, len; for (i = 0, len = c1.length; i < len; i++) { c1[i].setAttribute("_qdiff", d); } for (i = 0, len = c2.length; i < len; i++) { if (c2[i].getAttribute("_qdiff") != d) { r[r.length] = c2[i]; } } for (i = 0, len = c1.length; i < len; i++) { c1[i].removeAttribute("_qdiff"); } return r; } function quickDiff(c1, c2) { var len1 = c1.length, d = ++key, r = [], i, len; if (!len1) { return c2; } if (isIE && typeof c1[0].selectSingleNode != "undefined") { return quickDiffIEXml(c1, c2); } for (i = 0; i < len1; i++) { c1[i]._qdiff = d; } for (i = 0, len = c2.length; i < len; i++) { if (c2[i]._qdiff != d) { r[r.length] = c2[i]; } } return r; } function quickId(ns, mode, root, id) { if (ns == root) { id = unescapeCssSelector(id); var d = root.ownerDocument || root; return d.getElementById(id); } ns = getNodes(ns, mode, "*"); return byId(ns, id); } return DQ = { getStyle: function(el, name) { return Ext.fly(el, '_DomQuery').getStyle(name); }, compile: function(path, type) { type = type || "select"; var fn = ["var f = function(root) {\n var mode; ++batch; var n = root || document;\n"], lastPath, matchers = DQ.matchers, matchersLn = matchers.length, modeMatch, lmode = path.match(modeRe), tokenMatch, matched, j, t, m; path = setupEscapes(path); if (lmode && lmode[1]) { fn[fn.length] = 'mode="' + lmode[1].replace(trimRe, "") + '";'; path = path.replace(lmode[1], ""); } while (path.substr(0, 1) == "/") { path = path.substr(1); } while (path && lastPath != path) { lastPath = path; tokenMatch = path.match(tagTokenRe); if (type == "select") { if (tokenMatch) { if (tokenMatch[1] == "#") { fn[fn.length] = 'n = quickId(n, mode, root, "' + tokenMatch[2] + '");'; } else { fn[fn.length] = 'n = getNodes(n, mode, "' + tokenMatch[2] + '");'; } path = path.replace(tokenMatch[0], ""); } else if (path.substr(0, 1) != '@') { fn[fn.length] = 'n = getNodes(n, mode, "*");'; } } else { if (tokenMatch) { if (tokenMatch[1] == "#") { fn[fn.length] = 'n = byId(n, "' + tokenMatch[2] + '");'; } else { fn[fn.length] = 'n = byTag(n, "' + tokenMatch[2] + '");'; } path = path.replace(tokenMatch[0], ""); } } while (!(modeMatch = path.match(modeRe))) { matched = false; for (j = 0; j < matchersLn; j++) { t = matchers[j]; m = path.match(t.re); if (m) { fn[fn.length] = t.select.replace(tplRe, function(x, i) { return m[i]; }); path = path.replace(m[0], ""); matched = true; break; } } if (!matched) { Ext.Error.raise({ sourceClass:'Ext.DomQuery', sourceMethod:'compile', msg:'Error parsing selector. Parsing failed at "' + path + '"' }); } } if (modeMatch[1]) { fn[fn.length] = 'mode="' + modeMatch[1].replace(trimRe, "") + '";'; path = path.replace(modeMatch[1], ""); } } fn[fn.length] = "return nodup(n);\n}"; eval(fn.join("")); return f; }, jsSelect: function(path, root, type) { root = root || doc; if (typeof root == "string") { root = doc.getElementById(root); } var paths = path.split(","), results = [], i, len, subPath, result; for (i = 0, len = paths.length; i < len; i++) { subPath = paths[i].replace(trimRe, ""); if (!cache[subPath]) { cache[subPath] = DQ.compile(subPath, type); if (!cache[subPath]) { Ext.Error.raise({ sourceClass:'Ext.DomQuery', sourceMethod:'jsSelect', msg:subPath + ' is not a valid selector' }); } } else { setupEscapes(subPath); } result = cache[subPath](root); if (result && result !== doc) { results = results.concat(result); } } if (paths.length > 1) { return nodup(results); } return results; }, isXml: function(el) { var docEl = (el ? el.ownerDocument || el : 0).documentElement; return docEl ? docEl.nodeName !== "HTML" : false; }, select : doc.querySelectorAll ? function(path, root, type, single) { root = root || doc; if (!DQ.isXml(root)) { try { if (root.parentNode && (root.nodeType !== 9) && path.indexOf(',') === -1 && !startIdRe.test(path)) { path = '#' + Ext.escapeId(Ext.id(root)) + ' ' + path; root = root.parentNode; } return single ? [ root.querySelector(path) ] : Ext.Array.toArray(root.querySelectorAll(path)); } catch (e) { } } return DQ.jsSelect.call(this, path, root, type); } : function(path, root, type) { return DQ.jsSelect.call(this, path, root, type); }, selectNode : function(path, root){ return Ext.DomQuery.select(path, root, null, true)[0]; }, selectValue: function(path, root, defaultValue) { path = path.replace(trimRe, ""); if (!valueCache[path]) { valueCache[path] = DQ.compile(path, "select"); } else { setupEscapes(path); } var n = valueCache[path](root), v; n = n[0] ? n[0] : n; if (typeof n.normalize == 'function') { n.normalize(); } v = (n && n.firstChild ? n.firstChild.nodeValue : null); return ((v === null || v === undefined || v === '') ? defaultValue : v); }, selectNumber: function(path, root, defaultValue) { var v = DQ.selectValue(path, root, defaultValue || 0); return parseFloat(v); }, is: function(el, ss) { if (typeof el == "string") { el = doc.getElementById(el); } var isArray = Ext.isArray(el), result = DQ.filter(isArray ? el : [el], ss); return isArray ? (result.length == el.length) : (result.length > 0); }, filter: function(els, ss, nonMatches) { ss = ss.replace(trimRe, ""); if (!simpleCache[ss]) { simpleCache[ss] = DQ.compile(ss, "simple"); } else { setupEscapes(ss); } var result = simpleCache[ss](els); return nonMatches ? quickDiff(result, els) : result; }, matchers: [{ re: /^\.([\w\-\\]+)/, select: useClassList ? 'n = byClassName(n, "{1}");' : 'n = byClassName(n, " {1} ");' }, { re: /^\:([\w\-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/, select: 'n = byPseudo(n, "{1}", "{2}");' }, { re: /^(?:([\[\{])(?:@)?([\w\-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/, select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");' }, { re: /^#([\w\-\\]+)/, select: 'n = byId(n, "{1}");' }, { re: /^@([\w\-\.]+)/, select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};' }], operators: { "=": function(a, v) { return a == v; }, "!=": function(a, v) { return a != v; }, "^=": function(a, v) { return a && a.substr(0, v.length) == v; }, "$=": function(a, v) { return a && a.substr(a.length - v.length) == v; }, "*=": function(a, v) { return a && a.indexOf(v) !== -1; }, "%=": function(a, v) { return (a % v) === 0; }, "|=": function(a, v) { return a && (a == v || a.substr(0, v.length + 1) == v + '-'); }, "~=": function(a, v) { return a && (' ' + a + ' ').indexOf(' ' + v + ' ') != -1; } }, pseudos: { "first-child": function(c) { var r = [], ri = -1, n, i, ci; for (i = 0; (ci = n = c[i]); i++) { while ((n = n.previousSibling) && n.nodeType != 1); if (!n) { r[++ri] = ci; } } return r; }, "last-child": function(c) { var r = [], ri = -1, n, i, ci; for (i = 0; (ci = n = c[i]); i++) { while ((n = n.nextSibling) && n.nodeType != 1); if (!n) { r[++ri] = ci; } } return r; }, "nth-child": function(c, a) { var r = [], ri = -1, m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a), f = (m[1] || 1) - 0, l = m[2] - 0, i, n, j, cn, pn; for (i = 0; n = c[i]; i++) { pn = n.parentNode; if (batch != pn._batch) { j = 0; for (cn = pn.firstChild; cn; cn = cn.nextSibling) { if (cn.nodeType == 1) { cn.nodeIndex = ++j; } } pn._batch = batch; } if (f == 1) { if (l === 0 || n.nodeIndex == l) { r[++ri] = n; } } else if ((n.nodeIndex + l) % f === 0) { r[++ri] = n; } } return r; }, "only-child": function(c) { var r = [], ri = -1, i, ci; for (i = 0; ci = c[i]; i++) { if (!prev(ci) && !next(ci)) { r[++ri] = ci; } } return r; }, "empty": function(c) { var r = [], ri = -1, i, ci, cns, j, cn, empty; for (i = 0; ci = c[i]; i++) { cns = ci.childNodes; j = 0; empty = true; while (cn = cns[j]) { ++j; if (cn.nodeType == 1 || cn.nodeType == 3) { empty = false; break; } } if (empty) { r[++ri] = ci; } } return r; }, "contains": function(c, v) { var r = [], ri = -1, i, ci; for (i = 0; ci = c[i]; i++) { if ((ci.textContent || ci.innerText || ci.text || '').indexOf(v) != -1) { r[++ri] = ci; } } return r; }, "nodeValue": function(c, v) { var r = [], ri = -1, i, ci; for (i = 0; ci = c[i]; i++) { if (ci.firstChild && ci.firstChild.nodeValue == v) { r[++ri] = ci; } } return r; }, "checked": function(c) { var r = [], ri = -1, i, ci; for (i = 0; ci = c[i]; i++) { if (ci.checked === true) { r[++ri] = ci; } } return r; }, "not": function(c, ss) { return DQ.filter(c, ss, true); }, "any": function(c, selectors) { var ss = selectors.split('|'), r = [], ri = -1, s, i, ci, j; for (i = 0; ci = c[i]; i++) { for (j = 0; s = ss[j]; j++) { if (DQ.is(ci, s)) { r[++ri] = ci; break; } } } return r; }, "odd": function(c) { return this["nth-child"](c, "odd"); }, "even": function(c) { return this["nth-child"](c, "even"); }, "nth": function(c, a) { return c[a - 1] || []; }, "first": function(c) { return c[0] || []; }, "last": function(c) { return c[c.length - 1] || []; }, "has": function(c, ss) { var s = DQ.select, r = [], ri = -1, i, ci; for (i = 0; ci = c[i]; i++) { if (s(ss, ci).length > 0) { r[++ri] = ci; } } return r; }, "next": function(c, ss) { var is = DQ.is, r = [], ri = -1, i, ci, n; for (i = 0; ci = c[i]; i++) { n = next(ci); if (n && is(n, ss)) { r[++ri] = ci; } } return r; }, "prev": function(c, ss) { var is = DQ.is, r = [], ri = -1, i, ci, n; for (i = 0; ci = c[i]; i++) { n = prev(ci); if (n && is(n, ss)) { r[++ri] = ci; } } return r; }, focusable: function(candidates) { var len = candidates.length, results = [], i = 0, c; for (; i < len; i++) { c = candidates[i]; if (Ext.fly(c, '_DomQuery').isFocusable()) { results.push(c); } } return results; }, visible: function(candidates, deep) { var len = candidates.length, results = [], i = 0, c; for (; i < len; i++) { c = candidates[i]; if (Ext.fly(c, '_DomQuery').isVisible(deep)) { results.push(c); } } return results; } } }; }()); Ext.query = Ext.DomQuery.select; Ext.define('Ext.dom.Element_anim', { override: 'Ext.dom.Element', animate: function(config) { var me = this, animId = me.dom.id || Ext.id(me.dom), listeners, anim, end; if (!Ext.fx.Manager.hasFxBlock(animId)) { if (config.listeners) { listeners = config.listeners; delete config.listeners; } if (config.internalListeners) { config.listeners = config.internalListeners; delete config.internalListeners; } end = config.autoEnd; delete config.autoEnd; anim = new Ext.fx.Anim(me.anim(config)); if (listeners) { anim.on(listeners); } Ext.fx.Manager.queueFx(anim); if (end) { anim.jumpToEnd(); } } return me; }, anim: function(config) { if (!Ext.isObject(config)) { return (config) ? {} : false; } var me = this, duration = config.duration || Ext.fx.Anim.prototype.duration, easing = config.easing || 'ease', animConfig; if (config.stopAnimation) { me.stopAnimation(); } Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id)); Ext.fx.Manager.setFxDefaults(me.id, { delay: 0 }); animConfig = { target: me.dom, remove: config.remove, alternate: config.alternate || false, duration: duration, easing: easing, callback: config.callback, listeners: config.listeners, iterations: config.iterations || 1, scope: config.scope, block: config.block, concurrent: config.concurrent, delay: config.delay || 0, paused: true, keyframes: config.keyframes, from: config.from || {}, to: Ext.apply({}, config) }; Ext.apply(animConfig.to, config.to); delete animConfig.to.to; delete animConfig.to.from; delete animConfig.to.remove; delete animConfig.to.alternate; delete animConfig.to.keyframes; delete animConfig.to.iterations; delete animConfig.to.listeners; delete animConfig.to.target; delete animConfig.to.paused; delete animConfig.to.callback; delete animConfig.to.scope; delete animConfig.to.duration; delete animConfig.to.easing; delete animConfig.to.concurrent; delete animConfig.to.block; delete animConfig.to.stopAnimation; delete animConfig.to.delay; return animConfig; }, slideIn: function(anchor, obj, slideOut) { var me = this, dom = me.dom, elStyle = dom.style, beforeAnim, wrapAnim, restoreScroll, wrapDomParentNode; anchor = anchor || "t"; obj = obj || {}; beforeAnim = function() { var animScope = this, listeners = obj.listeners, el = Ext.fly(dom, '_anim'), box, originalStyles, anim, wrap; if (!slideOut) { el.fixDisplay(); } box = el.getBox(); if ((anchor == 't' || anchor == 'b') && box.height === 0) { box.height = dom.scrollHeight; } else if ((anchor == 'l' || anchor == 'r') && box.width === 0) { box.width = dom.scrollWidth; } originalStyles = el.getStyles('width', 'height', 'left', 'right', 'top', 'bottom', 'position', 'z-index', true); el.setSize(box.width, box.height); if (obj.preserveScroll) { restoreScroll = el.cacheScrollValues(); } wrap = el.wrap({ role: 'presentation', id: Ext.id() + '-anim-wrap-for-' + el.dom.id, style: { visibility: slideOut ? 'visible' : 'hidden' } }); wrapDomParentNode = wrap.dom.parentNode; wrap.setPositioning(el.getPositioning(true)); if (wrap.isStyle('position', 'static')) { wrap.position('relative'); } el.clearPositioning('auto'); wrap.clip(); if (restoreScroll) { restoreScroll(); } el.setStyle({ visibility: '', position: 'absolute' }); if (slideOut) { wrap.setSize(box.width, box.height); } switch (anchor) { case 't': anim = { from: { width: box.width + 'px', height: '0px' }, to: { width: box.width + 'px', height: box.height + 'px' } }; elStyle.bottom = '0px'; break; case 'l': anim = { from: { width: '0px', height: box.height + 'px' }, to: { width: box.width + 'px', height: box.height + 'px' } }; me.anchorAnimX(anchor); break; case 'r': anim = { from: { x: box.x + box.width, width: '0px', height: box.height + 'px' }, to: { x: box.x, width: box.width + 'px', height: box.height + 'px' } }; me.anchorAnimX(anchor); break; case 'b': anim = { from: { y: box.y + box.height, width: box.width + 'px', height: '0px' }, to: { y: box.y, width: box.width + 'px', height: box.height + 'px' } }; break; case 'tl': anim = { from: { x: box.x, y: box.y, width: '0px', height: '0px' }, to: { width: box.width + 'px', height: box.height + 'px' } }; elStyle.bottom = '0px'; me.anchorAnimX('l'); break; case 'bl': anim = { from: { y: box.y + box.height, width: '0px', height: '0px' }, to: { y: box.y, width: box.width + 'px', height: box.height + 'px' } }; me.anchorAnimX('l'); break; case 'br': anim = { from: { x: box.x + box.width, y: box.y + box.height, width: '0px', height: '0px' }, to: { x: box.x, y: box.y, width: box.width + 'px', height: box.height + 'px' } }; me.anchorAnimX('r'); break; case 'tr': anim = { from: { x: box.x + box.width, width: '0px', height: '0px' }, to: { x: box.x, width: box.width + 'px', height: box.height + 'px' } }; elStyle.bottom = '0px'; me.anchorAnimX('r'); break; } wrap.show(); wrapAnim = Ext.apply({}, obj); delete wrapAnim.listeners; wrapAnim = new Ext.fx.Anim(Ext.applyIf(wrapAnim, { target: wrap, duration: 500, easing: 'ease-out', from: slideOut ? anim.to : anim.from, to: slideOut ? anim.from : anim.to })); wrapAnim.on('afteranimate', function() { var el = Ext.fly(dom, '_anim'); el.setStyle(originalStyles); if (slideOut) { if (obj.useDisplay) { el.setDisplayed(false); } else { el.hide(); } } if (wrap.dom) { if (wrap.dom.parentNode) { wrap.dom.parentNode.insertBefore(el.dom, wrap.dom); } else { wrapDomParentNode.appendChild(el.dom); } wrap.remove(); } if (restoreScroll) { restoreScroll(); } animScope.end(); }); if (listeners) { wrapAnim.on(listeners); } }; me.animate({ duration: obj.duration ? Math.max(obj.duration, 500) * 2 : 1000, listeners: { beforeanimate: beforeAnim } }); return me; }, slideOut: function(anchor, o) { return this.slideIn(anchor, o, true); }, puff: function(obj) { var me = this, dom = me.dom, beforeAnim, box = me.getBox(), originalStyles = me.getStyles('width', 'height', 'left', 'right', 'top', 'bottom', 'position', 'z-index', 'font-size', 'opacity', true); obj = Ext.applyIf(obj || {}, { easing: 'ease-out', duration: 500, useDisplay: false }); beforeAnim = function() { var el = Ext.fly(dom, '_anim'); el.clearOpacity(); el.show(); this.to = { width: box.width * 2, height: box.height * 2, x: box.x - (box.width / 2), y: box.y - (box.height /2), opacity: 0, fontSize: '200%' }; this.on('afteranimate',function() { var el = Ext.fly(dom, '_anim'); if (el) { if (obj.useDisplay) { el.setDisplayed(false); } else { el.hide(); } el.setStyle(originalStyles); Ext.callback(obj.callback, obj.scope); } }); }; me.animate({ duration: obj.duration, easing: obj.easing, listeners: { beforeanimate: { fn: beforeAnim } } }); return me; }, switchOff: function(obj) { var me = this, dom = me.dom, beforeAnim; obj = Ext.applyIf(obj || {}, { easing: 'ease-in', duration: 500, remove: false, useDisplay: false }); beforeAnim = function() { var el = Ext.fly(dom, '_anim'), animScope = this, size = el.getSize(), xy = el.getXY(), keyframe, position; el.clearOpacity(); el.clip(); position = el.getPositioning(); keyframe = new Ext.fx.Animator({ target: dom, duration: obj.duration, easing: obj.easing, keyframes: { 33: { opacity: 0.3 }, 66: { height: 1, y: xy[1] + size.height / 2 }, 100: { width: 1, x: xy[0] + size.width / 2 } } }); keyframe.on('afteranimate', function() { var el = Ext.fly(dom, '_anim'); if (obj.useDisplay) { el.setDisplayed(false); } else { el.hide(); } el.clearOpacity(); el.setPositioning(position); el.setSize(size); animScope.end(); }); }; me.animate({ duration: (Math.max(obj.duration, 500) * 2), listeners: { beforeanimate: { fn: beforeAnim } }, callback: obj.callback, scope: obj.scope }); return me; }, frame : function(color, count, obj){ var me = this, dom = me.dom, beforeAnim; color = color || '#C3DAF9'; count = count || 1; obj = obj || {}; beforeAnim = function() { var el = Ext.fly(dom, '_anim'), animScope = this, box, proxy, proxyAnim; el.show(); box = el.getBox(); proxy = Ext.getBody().createChild({ role: 'presentation', id: el.dom.id + '-anim-proxy', style: { position : 'absolute', 'pointer-events': 'none', 'z-index': 35000, border : '0px solid ' + color } }); proxyAnim = new Ext.fx.Anim({ target: proxy, duration: obj.duration || 1000, iterations: count, from: { top: box.y, left: box.x, borderWidth: 0, opacity: 1, height: box.height, width: box.width }, to: { top: box.y - 20, left: box.x - 20, borderWidth: 10, opacity: 0, height: box.height + 40, width: box.width + 40 } }); proxyAnim.on('afteranimate', function() { proxy.remove(); animScope.end(); }); }; me.animate({ duration: (Math.max(obj.duration, 500) * 2) || 2000, listeners: { beforeanimate: { fn: beforeAnim } }, callback: obj.callback, scope: obj.scope }); return me; }, ghost: function(anchor, obj) { var me = this, dom = me.dom, beforeAnim; anchor = anchor || "b"; beforeAnim = function() { var el = Ext.fly(dom, '_anim'), width = el.getWidth(), height = el.getHeight(), xy = el.getXY(), position = el.getPositioning(), to = { opacity: 0 }; switch (anchor) { case 't': to.y = xy[1] - height; break; case 'l': to.x = xy[0] - width; break; case 'r': to.x = xy[0] + width; break; case 'b': to.y = xy[1] + height; break; case 'tl': to.x = xy[0] - width; to.y = xy[1] - height; break; case 'bl': to.x = xy[0] - width; to.y = xy[1] + height; break; case 'br': to.x = xy[0] + width; to.y = xy[1] + height; break; case 'tr': to.x = xy[0] + width; to.y = xy[1] - height; break; } this.to = to; this.on('afteranimate', function () { var el = Ext.fly(dom, '_anim'); if (el) { el.hide(); el.clearOpacity(); el.setPositioning(position); } }); }; me.animate(Ext.applyIf(obj || {}, { duration: 500, easing: 'ease-out', listeners: { beforeanimate: beforeAnim } })); return me; }, highlight: function(color, o) { var me = this, dom = me.dom, from = {}, restore, to, attr, lns, event, fn; if (dom.tagName.match(me.tableTagRe)) { return me.select('div').highlight(color, o); } o = o || {}; lns = o.listeners || {}; attr = o.attr || 'backgroundColor'; from[attr] = color || 'ffff9c'; if (!o.to) { to = {}; to[attr] = o.endColor || me.getColor(attr, 'ffffff', ''); } else { to = o.to; } o.listeners = Ext.apply(Ext.apply({}, lns), { beforeanimate: function() { restore = dom.style[attr]; var el = Ext.fly(dom, '_anim'); el.clearOpacity(); el.show(); event = lns.beforeanimate; if (event) { fn = event.fn || event; return fn.apply(event.scope || lns.scope || window, arguments); } }, afteranimate: function() { if (dom) { dom.style[attr] = restore; } event = lns.afteranimate; if (event) { fn = event.fn || event; fn.apply(event.scope || lns.scope || window, arguments); } } }); me.animate(Ext.apply({}, o, { duration: 1000, easing: 'ease-in', from: from, to: to })); return me; }, pause: function(ms) { var me = this; Ext.fx.Manager.setFxDefaults(me.id, { delay: ms }); return me; }, fadeIn: function(o) { var me = this, dom = me.dom; me.animate(Ext.apply({}, o, { opacity: 1, internalListeners: { beforeanimate: function(anim){ var el = Ext.fly(dom, '_anim'); if (el.isStyle('display', 'none')) { el.setDisplayed(''); } else { el.show(); } } } })); return this; }, fadeOut: function(o) { var me = this, dom = me.dom; o = Ext.apply({ opacity: 0, internalListeners: { afteranimate: function(anim){ if (dom && anim.to.opacity === 0) { var el = Ext.fly(dom, '_anim'); if (o.useDisplay) { el.setDisplayed(false); } else { el.hide(); } } } } }, o); me.animate(o); return me; }, scale: function(w, h, o) { this.animate(Ext.apply({}, o, { width: w, height: h })); return this; }, shift: function(config) { this.animate(config); return this; }, anchorAnimX: function(anchor) { var xName = (anchor === 'l') ? 'right' : 'left'; this.dom.style[xName] = '0px'; } }); Ext.define('Ext.dom.Element_dd', { override: 'Ext.dom.Element', initDD : function(group, config, overrides){ var dd = new Ext.dd.DD(Ext.id(this.dom), group, config); return Ext.apply(dd, overrides); }, initDDProxy : function(group, config, overrides){ var dd = new Ext.dd.DDProxy(Ext.id(this.dom), group, config); return Ext.apply(dd, overrides); }, initDDTarget : function(group, config, overrides){ var dd = new Ext.dd.DDTarget(Ext.id(this.dom), group, config); return Ext.apply(dd, overrides); } }); Ext.define('Ext.dom.Element_fx', { override: 'Ext.dom.Element' }, function() { var Element = Ext.dom.Element, VISIBILITY = "visibility", DISPLAY = "display", NONE = "none", HIDDEN = 'hidden', VISIBLE = 'visible', OFFSETS = "offsets", ASCLASS = "asclass", NOSIZE = 'nosize', ORIGINALDISPLAY = 'originalDisplay', VISMODE = 'visibilityMode', ISVISIBLE = 'isVisible', OFFSETCLASS = Ext.baseCSSPrefix + 'hide-offsets', getDisplay = function(el) { var data = (el.$cache || el.getCache()).data, display = data[ORIGINALDISPLAY]; if (display === undefined) { data[ORIGINALDISPLAY] = display = ''; } return display; }, getVisMode = function(el){ var data = (el.$cache || el.getCache()).data, visMode = data[VISMODE]; if (visMode === undefined) { data[VISMODE] = visMode = Element.VISIBILITY; } return visMode; }; Element.override({ originalDisplay : "", visibilityMode : 1, setVisible : function(visible, animate) { var me = this, dom = me.dom, visMode = getVisMode(me); if (typeof animate == 'string') { switch (animate) { case DISPLAY: visMode = Element.DISPLAY; break; case VISIBILITY: visMode = Element.VISIBILITY; break; case OFFSETS: visMode = Element.OFFSETS; break; case NOSIZE: case ASCLASS: visMode = Element.ASCLASS; break; } me.setVisibilityMode(visMode); animate = false; } if (!animate || !me.anim) { if (visMode == Element.DISPLAY) { return me.setDisplayed(visible); } else if (visMode == Element.OFFSETS) { me[visible?'removeCls':'addCls'](OFFSETCLASS); } else if (visMode == Element.VISIBILITY) { me.fixDisplay(); dom.style.visibility = visible ? '' : HIDDEN; } else if (visMode == Element.ASCLASS) { me[visible?'removeCls':'addCls'](me.visibilityCls || Element.visibilityCls); } } else { if (visible) { me.setOpacity(0.01); me.setVisible(true); } if (!Ext.isObject(animate)) { animate = { duration: 350, easing: 'ease-in' }; } me.animate(Ext.applyIf({ callback: function() { if (!visible) { Ext.fly(dom, '_internal').setVisible(false).setOpacity(1); } }, to: { opacity: (visible) ? 1 : 0 } }, animate)); } (me.$cache || me.getCache()).data[ISVISIBLE] = visible; return me; }, hasMetrics : function(){ var visMode = getVisMode(this); return this.isVisible() || (visMode == Element.OFFSETS) || (visMode == Element.VISIBILITY); }, toggle : function(animate){ var me = this; me.setVisible(!me.isVisible(), me.anim(animate)); return me; }, setDisplayed : function(value) { if(typeof value == "boolean"){ value = value ? getDisplay(this) : NONE; } this.setStyle(DISPLAY, value); return this; }, fixDisplay : function(){ var me = this; if (me.isStyle(DISPLAY, NONE)) { me.setStyle(VISIBILITY, HIDDEN); me.setStyle(DISPLAY, getDisplay(me)); if (me.isStyle(DISPLAY, NONE)) { me.setStyle(DISPLAY, "block"); } } }, hide : function(animate){ if (typeof animate == 'string'){ this.setVisible(false, animate); return this; } this.setVisible(false, this.anim(animate)); return this; }, show : function(animate){ if (typeof animate == 'string'){ this.setVisible(true, animate); return this; } this.setVisible(true, this.anim(animate)); return this; } }); }); Ext.define('Ext.dom.Element_position', { override: 'Ext.dom.Element' }, function() { var flyInstance, Element = this, LEFT = "left", RIGHT = "right", TOP = "top", BOTTOM = "bottom", POSITION = "position", STATIC = "static", RELATIVE = "relative", ZINDEX = "z-index", BODY = 'BODY', PADDING = 'padding', BORDER = 'border', SLEFT = '-left', SRIGHT = '-right', STOP = '-top', SBOTTOM = '-bottom', SWIDTH = '-width', borders = {l: BORDER + SLEFT + SWIDTH, r: BORDER + SRIGHT + SWIDTH, t: BORDER + STOP + SWIDTH, b: BORDER + SBOTTOM + SWIDTH}, paddings = {l: PADDING + SLEFT, r: PADDING + SRIGHT, t: PADDING + STOP, b: PADDING + SBOTTOM}, paddingsTLRB = [paddings.l, paddings.r, paddings.t, paddings.b], bordersTLRB = [borders.l, borders.r, borders.t, borders.b], round = Math.round, doc = document, fly = function (el) { if (!flyInstance) { flyInstance = new Ext.Element.Fly(); } flyInstance.attach(el); return flyInstance; }; Element.override({ pxRe: /^\d+(?:\.\d*)?px$/i, inheritableStatics: { getX: function(el) { return Element.getXY(el)[0]; }, getXY: function(el) { var bd = doc.body, docEl = doc.documentElement, leftBorder = 0, topBorder = 0, ret = [0,0], box, scroll; el = Ext.getDom(el); if(el != doc && el != bd){ if (Ext.isIE) { try { box = el.getBoundingClientRect(); topBorder = docEl.clientTop || bd.clientTop; leftBorder = docEl.clientLeft || bd.clientLeft; } catch (ex) { box = { left: 0, top: 0 }; } } else { box = el.getBoundingClientRect(); } scroll = fly(doc).getScroll(); ret = [ round(box.left + scroll.left - leftBorder), round(box.top + scroll.top - topBorder) ]; } return ret; }, getY: function(el) { return Element.getXY(el)[1]; }, setX: function(el, x) { Element.setXY(el, [x, false]); }, setXY: function(el, xy) { (el = Ext.fly(el, '_setXY')).position(); var pts = el.translatePoints(xy), style = el.dom.style, pos; style.right = 'auto'; for (pos in pts) { if (!isNaN(pts[pos])) { style[pos] = pts[pos] + "px"; } } }, setY: function(el, y) { Element.setXY(el, [false, y]); } }, center: function(centerIn){ return this.alignTo(centerIn || doc, 'c-c'); }, clearPositioning: function(value) { value = value || ''; return this.setStyle({ left : value, right : value, top : value, bottom : value, 'z-index' : '', position : STATIC }); }, getAnchorToXY: function(el, anchor, local, mySize) { return el.getAnchorXY(anchor, local, mySize); }, getBottom: function(local) { return (local ? this.getLocalY() : this.getY()) + this.getHeight(); }, getBorderPadding: function() { var paddingWidth = this.getStyle(paddingsTLRB), bordersWidth = this.getStyle(bordersTLRB); return { beforeX: (parseFloat(bordersWidth[borders.l]) || 0) + (parseFloat(paddingWidth[paddings.l]) || 0), afterX: (parseFloat(bordersWidth[borders.r]) || 0) + (parseFloat(paddingWidth[paddings.r]) || 0), beforeY: (parseFloat(bordersWidth[borders.t]) || 0) + (parseFloat(paddingWidth[paddings.t]) || 0), afterY: (parseFloat(bordersWidth[borders.b]) || 0) + (parseFloat(paddingWidth[paddings.b]) || 0) }; }, getCenterXY: function(){ return this.getAlignToXY(doc, 'c-c'); }, getLeft: function(local) { return local ? this.getLocalX() : this.getX(); }, getLocalX: function() { var me = this, offsetParent = me.dom.offsetParent, x = me.getStyle('left'); if (!x || x === 'auto') { x = 0; } else if (me.pxRe.test(x)) { x = parseFloat(x); } else { x = me.getX(); if (offsetParent) { x -= Element.getX(offsetParent); } } return x; }, getLocalXY: function() { var me = this, offsetParent = me.dom.offsetParent, style = me.getStyle(['left', 'top']), x = style.left, y = style.top; if (!x || x === 'auto') { x = 0; } else if (me.pxRe.test(x)) { x = parseFloat(x); } else { x = me.getX(); if (offsetParent) { x -= Element.getX(offsetParent); } } if (!y || y === 'auto') { y = 0; } else if (me.pxRe.test(y)) { y = parseFloat(y); } else { y = me.getY(); if (offsetParent) { y -= Element.getY(offsetParent); } } return [x, y]; }, getLocalY: function() { var me = this, offsetParent = me.dom.offsetParent, y = me.getStyle('top'); if (!y || y === 'auto') { y = 0; } else if (me.pxRe.test(y)) { y = parseFloat(y); } else { y = me.getY(); if (offsetParent) { y -= Element.getY(offsetParent); } } return y; }, getPageBox: function(getRegion) { var me = this, dom = me.dom, isDoc = dom.nodeName == BODY, w = isDoc ? Ext.Element.getViewWidth() : dom.offsetWidth, h = isDoc ? Ext.Element.getViewHeight() : dom.offsetHeight, xy = me.getXY(), t = xy[1], r = xy[0] + w, b = xy[1] + h, l = xy[0]; if (getRegion) { return new Ext.util.Region(t, r, b, l); } else { return { left: l, top: t, width: w, height: h, right: r, bottom: b }; } }, getPositioning: function(autoPx){ var styles = this.getStyle(['left', 'top', 'position', 'z-index']), dom = this.dom; if(autoPx) { if(styles.left === 'auto') { styles.left = dom.offsetLeft + 'px'; } if(styles.top === 'auto') { styles.top = dom.offsetTop + 'px'; } } return styles; }, getRight: function(local) { return (local ? this.getLocalX() : this.getX()) + this.getWidth(); }, getTop: function(local) { return local ? this.getLocalY() : this.getY(); }, getX: function() { return Element.getX(this.dom); }, getXY: function() { return Element.getXY(this.dom); }, getY: function() { return Element.getY(this.dom); }, moveTo: function(x, y, animate) { return this.setXY([x, y], animate); }, position: function(pos, zIndex, x, y) { var me = this; if (!pos && me.isStyle(POSITION, STATIC)) { me.setStyle(POSITION, RELATIVE); } else if (pos) { me.setStyle(POSITION, pos); } if (zIndex) { me.setStyle(ZINDEX, zIndex); } if (x || y) { me.setXY([x || false, y || false]); } }, setBottom: function(bottom) { this.dom.style[BOTTOM] = this.addUnits(bottom); return this; }, setBounds: function(x, y, width, height, animate) { return this.setBox({ x: x, y: y, width: width, height: height }, animate); }, setLeft: function(left) { this.dom.style[LEFT] = this.addUnits(left); return this; }, setLeftTop: function(left, top) { var me = this, style = me.dom.style; style.left = me.addUnits(left); style.top = me.addUnits(top); return me; }, setLocalX: function(x) { var style = this.dom.style; style.right = 'auto'; style.left = (x === null) ? 'auto' : x + 'px'; }, setLocalXY: function(x, y) { var style = this.dom.style; style.right = 'auto'; if (x && x.length) { y = x[1]; x = x[0]; } if (x === null) { style.left = 'auto'; } else if (x !== undefined) { style.left = x + 'px'; } if (y === null) { style.top = 'auto'; } else if (y !== undefined) { style.top = y + 'px'; } }, setLocalY: function(y) { this.dom.style.top = (y === null) ? 'auto' : y + 'px'; }, setLocation: function(x, y, animate) { return this.setXY([x, y], animate); }, setPositioning: function(pc) { return this.setStyle(pc); }, setRight: function(right) { this.dom.style[RIGHT] = this.addUnits(right); return this; }, setTop: function(top) { this.dom.style[TOP] = this.addUnits(top); return this; }, setX: function(x, animate) { return this.setXY([x, this.getY()], animate); }, setXY: function(xy, animate) { var me = this; if (!animate || !me.anim) { Element.setXY(me.dom, xy); } else { if (!Ext.isObject(animate)) { animate = {}; } me.animate(Ext.applyIf({ to: { x: xy[0], y: xy[1] } }, animate)); } return this; }, setY: function(y, animate) { return this.setXY([this.getX(), y], animate); } }); Element.getTrueXY = Element.getXY; }); Ext.define('Ext.dom.Element_scroll', { override: 'Ext.dom.Element', isScrollable: function() { var dom = this.dom; return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth; }, getScroll: function() { var me = this, dom = me.dom, doc = document, body = doc.body, docElement = doc.documentElement, left, top; if (dom === doc || dom === body) { left = docElement.scrollLeft || (body ? body.scrollLeft : 0); top = docElement.scrollTop || (body ? body.scrollTop : 0); } else { left = dom.scrollLeft; top = dom.scrollTop; } return { left: left, top: top }; }, getScrollLeft: function() { var dom = this.dom, doc = document; if (dom === doc || dom === doc.body) { return this.getScroll().left; } else { return dom.scrollLeft; } }, getScrollTop: function(){ var dom = this.dom, doc = document; if (dom === doc || dom === doc.body) { return this.getScroll().top; } else { return dom.scrollTop; } }, setScrollLeft: function(left){ this.dom.scrollLeft = left; return this; }, setScrollTop: function(top) { this.dom.scrollTop = top; return this; }, scrollBy: function(deltaX, deltaY, animate) { var me = this, dom = me.dom; if (deltaX.length) { animate = deltaY; deltaY = deltaX[1]; deltaX = deltaX[0]; } else if (typeof deltaX != 'number') { animate = deltaY; deltaY = deltaX.y; deltaX = deltaX.x; } if (deltaX) { me.scrollTo('left', me.constrainScrollLeft(dom.scrollLeft + deltaX), animate); } if (deltaY) { me.scrollTo('top', me.constrainScrollTop(dom.scrollTop + deltaY), animate); } return me; }, scrollTo: function(side, value, animate) { var top = /top/i.test(side), me = this, prop = top ? 'scrollTop' : 'scrollLeft', dom = me.dom, animCfg; if (!animate || !me.anim) { dom[prop] = value; dom[prop] = value; } else { animCfg = { to: {} }; animCfg.to[prop] = value; if (Ext.isObject(animate)) { Ext.applyIf(animCfg, animate); } me.animate(animCfg); } return me; }, scrollIntoView: function(container, hscroll, animate, highlight) { var me = this, dom = me.dom, offsets = me.getOffsetsTo(container = Ext.getDom(container) || Ext.getBody().dom), left = offsets[0] + container.scrollLeft, top = offsets[1] + container.scrollTop, bottom = top + dom.offsetHeight, right = left + dom.offsetWidth, ctClientHeight = container.clientHeight, ctScrollTop = parseInt(container.scrollTop, 10), ctScrollLeft = parseInt(container.scrollLeft, 10), ctBottom = ctScrollTop + ctClientHeight, ctRight = ctScrollLeft + container.clientWidth, newPos; if (highlight) { if (animate) { animate = Ext.apply({ listeners: { afteranimate: function() { me.scrollChildFly.attach(dom).highlight(); } } }, animate); } else { me.scrollChildFly.attach(dom).highlight(); } } if (dom.offsetHeight > ctClientHeight || top < ctScrollTop) { newPos = top; } else if (bottom > ctBottom) { newPos = bottom - ctClientHeight; } if (newPos != null) { me.scrollChildFly.attach(container).scrollTo('top', newPos, animate); } if (hscroll !== false) { newPos = null; if (dom.offsetWidth > container.clientWidth || left < ctScrollLeft) { newPos = left; } else if (right > ctRight) { newPos = right - container.clientWidth; } if (newPos != null) { me.scrollChildFly.attach(container).scrollTo('left', newPos, animate); } } return me; }, scrollChildIntoView: function(child, hscroll) { this.scrollChildFly.attach(Ext.getDom(child)).scrollIntoView(this, hscroll); }, scroll: function(direction, distance, animate) { if (!this.isScrollable()) { return false; } direction = direction.charAt(0); var me = this, dom = me.dom, side = direction === 'r' || direction === 'l' ? 'left' : 'top', scrolled = false, currentScroll, constrainedScroll; if (direction === 'l' || direction === 't' || direction === 'u') { distance = -distance; } if (side === 'left') { currentScroll = dom.scrollLeft; constrainedScroll = me.constrainScrollLeft(currentScroll + distance); } else { currentScroll = dom.scrollTop; constrainedScroll = me.constrainScrollTop(currentScroll + distance); } if (constrainedScroll !== currentScroll) { this.scrollTo(side, constrainedScroll, animate); scrolled = true; } return scrolled; }, constrainScrollLeft: function(left) { var dom = this.dom; return Math.max(Math.min(left, dom.scrollWidth - dom.clientWidth), 0); }, constrainScrollTop: function(top) { var dom = this.dom; return Math.max(Math.min(top, dom.scrollHeight - dom.clientHeight), 0); } }, function() { this.prototype.scrollChildFly = new this.Fly(); this.prototype.scrolltoFly = new this.Fly(); }); Ext.define('Ext.dom.Element_style', { override: 'Ext.dom.Element' }, function() { var Element = this, view = document.defaultView, adjustDirect2DTableRe = /table-row|table-.*-group/, INTERNAL = '_internal', HIDDEN = 'hidden', HEIGHT = 'height', WIDTH = 'width', ISCLIPPED = 'isClipped', OVERFLOW = 'overflow', OVERFLOWX = 'overflow-x', OVERFLOWY = 'overflow-y', ORIGINALCLIP = 'originalClip', DOCORBODYRE = /#document|body/i, styleHooks, verticalStyleHooks90, verticalStyleHooks270, edges, k, edge, borderWidth; if (!view || !view.getComputedStyle) { Element.prototype.getStyle = function (property, inline) { var me = this, dom = me.dom, multiple = typeof property != 'string', hooks = me.styleHooks, prop = property, props = prop, len = 1, isInline = inline, camel, domStyle, values, hook, out, style, i; if (multiple) { values = {}; prop = props[0]; i = 0; if (!(len = props.length)) { return values; } } if (!dom || dom.documentElement) { return values || ''; } domStyle = dom.style; if (inline) { style = domStyle; } else { style = dom.currentStyle; if (!style) { isInline = true; style = domStyle; } } do { hook = hooks[prop]; if (!hook) { hooks[prop] = hook = { name: Element.normalize(prop) }; } if (hook.get) { out = hook.get(dom, me, isInline, style); } else { camel = hook.name; if (hook.canThrow) { try { out = style[camel]; } catch (e) { out = ''; } } else { out = style ? style[camel] : ''; } } if (!multiple) { return out; } values[prop] = out; prop = props[++i]; } while (i < len); return values; }; } Element.override({ getHeight: function(contentHeight, preciseHeight) { var me = this, hidden = me.isStyle('display', 'none'), height, floating; if (hidden) { return 0; } height = me.dom.offsetHeight; if (Ext.supports.Direct2DBug) { floating = me.adjustDirect2DDimension(HEIGHT); if (preciseHeight) { height += floating; } else if (floating > 0 && floating < 0.5) { height++; } } if (contentHeight) { height -= me.getBorderWidth("tb") + me.getPadding("tb"); } return (height < 0) ? 0 : height; }, getWidth: function(contentWidth, preciseWidth) { var me = this, dom = me.dom, hidden = me.isStyle('display', 'none'), rect, width, floating; if (hidden) { return 0; } if (Ext.supports.BoundingClientRect) { rect = dom.getBoundingClientRect(); width = (me.vertical && !Ext.isIE9 && !Ext.supports.RotatedBoundingClientRect) ? (rect.bottom - rect.top) : (rect.right - rect.left); width = preciseWidth ? width : Math.ceil(width); } else { width = dom.offsetWidth; } if (Ext.supports.Direct2DBug && !me.vertical) { floating = me.adjustDirect2DDimension(WIDTH); if (preciseWidth) { width += floating; } else if (floating > 0 && floating < 0.5) { width++; } } if (contentWidth) { width -= me.getBorderWidth("lr") + me.getPadding("lr"); } return (width < 0) ? 0 : width; }, setWidth: function(width, animate) { var me = this; width = me.adjustWidth(width); if (!animate || !me.anim) { me.dom.style.width = me.addUnits(width); } else { if (!Ext.isObject(animate)) { animate = {}; } me.animate(Ext.applyIf({ to: { width: width } }, animate)); } return me; }, setHeight : function(height, animate) { var me = this; height = me.adjustHeight(height); if (!animate || !me.anim) { me.dom.style.height = me.addUnits(height); } else { if (!Ext.isObject(animate)) { animate = {}; } me.animate(Ext.applyIf({ to: { height: height } }, animate)); } return me; }, applyStyles: function(style) { Ext.DomHelper.applyStyles(this.dom, style); return this; }, setSize: function(width, height, animate) { var me = this; if (Ext.isObject(width)) { animate = height; height = width.height; width = width.width; } width = me.adjustWidth(width); height = me.adjustHeight(height); if (!animate || !me.anim) { me.dom.style.width = me.addUnits(width); me.dom.style.height = me.addUnits(height); } else { if (animate === true) { animate = {}; } me.animate(Ext.applyIf({ to: { width: width, height: height } }, animate)); } return me; }, getViewSize : function() { var me = this, dom = me.dom, isDoc = DOCORBODYRE.test(dom.nodeName), ret; if (isDoc) { ret = { width : Element.getViewWidth(), height : Element.getViewHeight() }; } else { ret = { width : dom.clientWidth, height : dom.clientHeight }; } return ret; }, getSize: function(contentSize) { return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)}; }, adjustWidth : function(width) { var me = this, isNum = (typeof width == 'number'); if (isNum && me.autoBoxAdjust && !me.isBorderBox()) { width -= (me.getBorderWidth("lr") + me.getPadding("lr")); } return (isNum && width < 0) ? 0 : width; }, adjustHeight : function(height) { var me = this, isNum = (typeof height == "number"); if (isNum && me.autoBoxAdjust && !me.isBorderBox()) { height -= (me.getBorderWidth("tb") + me.getPadding("tb")); } return (isNum && height < 0) ? 0 : height; }, getColor : function(attr, defaultValue, prefix) { var v = this.getStyle(attr), color = prefix || prefix === '' ? prefix : '#', h, len, i=0; if (!v || (/transparent|inherit/.test(v))) { return defaultValue; } if (/^r/.test(v)) { v = v.slice(4, v.length - 1).split(','); len = v.length; for (; i 5 ? color.toLowerCase() : defaultValue); }, setOpacity: function(opacity, animate) { var me = this; if (!me.dom) { return me; } if (!animate || !me.anim) { me.setStyle('opacity', opacity); } else { if (typeof animate != 'object') { animate = { duration: 350, easing: 'ease-in' }; } me.animate(Ext.applyIf({ to: { opacity: opacity } }, animate)); } return me; }, clearOpacity : function() { return this.setOpacity(''); }, adjustDirect2DDimension: function(dimension) { var me = this, dom = me.dom, display = me.getStyle('display'), inlineDisplay = dom.style.display, inlinePosition = dom.style.position, originIndex = dimension === WIDTH ? 0 : 1, currentStyle = dom.currentStyle, floating; if (display === 'inline') { dom.style.display = 'inline-block'; } dom.style.position = display.match(adjustDirect2DTableRe) ? 'absolute' : 'static'; floating = (parseFloat(currentStyle[dimension]) || parseFloat(currentStyle.msTransformOrigin.split(' ')[originIndex]) * 2) % 1; dom.style.position = inlinePosition; if (display === 'inline') { dom.style.display = inlineDisplay; } return floating; }, clip : function() { var me = this, data = (me.$cache || me.getCache()).data, style; if (!data[ISCLIPPED]) { data[ISCLIPPED] = true; style = me.getStyle([OVERFLOW, OVERFLOWX, OVERFLOWY]); data[ORIGINALCLIP] = { o: style[OVERFLOW], x: style[OVERFLOWX], y: style[OVERFLOWY] }; me.setStyle(OVERFLOW, HIDDEN); me.setStyle(OVERFLOWX, HIDDEN); me.setStyle(OVERFLOWY, HIDDEN); } return me; }, unclip : function() { var me = this, data = (me.$cache || me.getCache()).data, clip; if (data[ISCLIPPED]) { data[ISCLIPPED] = false; clip = data[ORIGINALCLIP]; if (clip.o) { me.setStyle(OVERFLOW, clip.o); } if (clip.x) { me.setStyle(OVERFLOWX, clip.x); } if (clip.y) { me.setStyle(OVERFLOWY, clip.y); } } return me; }, boxWrap : function(cls) { cls = cls || Ext.baseCSSPrefix + 'box'; var el = Ext.get(this.insertHtml("beforeBegin", "")); Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom); return el; }, getComputedHeight : function() { var me = this, h = Math.max(me.dom.offsetHeight, me.dom.clientHeight); if (!h) { h = parseFloat(me.getStyle(HEIGHT)) || 0; if (!me.isBorderBox()) { h += me.getFrameWidth('tb'); } } return h; }, getComputedWidth : function() { var me = this, w = Math.max(me.dom.offsetWidth, me.dom.clientWidth); if (!w) { w = parseFloat(me.getStyle(WIDTH)) || 0; if (!me.isBorderBox()) { w += me.getFrameWidth('lr'); } } return w; }, getFrameWidth : function(sides, onlyContentBox) { return (onlyContentBox && this.isBorderBox()) ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides)); }, addClsOnOver : function(className, testFn, scope) { var me = this, dom = me.dom, hasTest = Ext.isFunction(testFn); me.hover( function() { if (hasTest && testFn.call(scope || me, me) === false) { return; } Ext.fly(dom, INTERNAL).addCls(className); }, function() { Ext.fly(dom, INTERNAL).removeCls(className); } ); return me; }, addClsOnFocus : function(className, testFn, scope) { var me = this, dom = me.dom, hasTest = Ext.isFunction(testFn); me.on("focus", function() { if (hasTest && testFn.call(scope || me, me) === false) { return false; } Ext.fly(dom, INTERNAL).addCls(className); }); me.on("blur", function() { Ext.fly(dom, INTERNAL).removeCls(className); }); return me; }, addClsOnClick : function(className, testFn, scope) { var me = this, dom = me.dom, hasTest = Ext.isFunction(testFn); me.on("mousedown", function() { if (hasTest && testFn.call(scope || me, me) === false) { return false; } Ext.fly(dom, INTERNAL).addCls(className); var d = Ext.getDoc(), fn = function() { Ext.fly(dom, INTERNAL).removeCls(className); d.removeListener("mouseup", fn); }; d.on("mouseup", fn); }); return me; }, getStyleSize : function() { var me = this, d = this.dom, isDoc = DOCORBODYRE.test(d.nodeName), s , w, h; if (isDoc) { return { width : Element.getViewWidth(), height : Element.getViewHeight() }; } s = me.getStyle([HEIGHT, WIDTH], true); if (s.width && s.width != 'auto') { w = parseFloat(s.width); if (me.isBorderBox()) { w -= me.getFrameWidth('lr'); } } if (s.height && s.height != 'auto') { h = parseFloat(s.height); if (me.isBorderBox()) { h -= me.getFrameWidth('tb'); } } return {width: w || me.getWidth(true), height: h || me.getHeight(true)}; }, statics: { selectableCls: Ext.baseCSSPrefix + 'selectable', unselectableCls: Ext.baseCSSPrefix + 'unselectable' }, selectable : function() { var me = this; me.dom.unselectable = ''; me.removeCls(Element.unselectableCls); me.addCls(Element.selectableCls); return me; }, unselectable : function() { var me = this; if (Ext.isOpera) { me.dom.unselectable = 'on'; } me.removeCls(Element.selectableCls); me.addCls(Element.unselectableCls); return me; }, setVertical: function(angle, cls) { var me = this, proto = Element.prototype, hooks; me.vertical = true; if (cls) { me.addCls(me.verticalCls = cls); } me.setWidth = proto.setHeight; me.setHeight = proto.setWidth; if (!Ext.isIE9m) { me.getWidth = proto.getHeight; me.getHeight = proto.getWidth; } me.styleHooks = (angle === 270) ? Element.prototype.verticalStyleHooks270 : Element.prototype.verticalStyleHooks90; }, setHorizontal: function() { var me = this, cls = me.verticalCls; delete me.vertical; if (cls) { delete me.verticalCls; me.removeCls(cls); } delete me.setWidth; delete me.setHeight; if (!Ext.isIE9m) { delete me.getWidth; delete me.getHeight; } delete me.styleHooks; } }); Element.prototype.styleHooks = styleHooks = Ext.dom.AbstractElement.prototype.styleHooks; Element.prototype.verticalStyleHooks90 = verticalStyleHooks90 = Ext.Object.chain(Element.prototype.styleHooks); Element.prototype.verticalStyleHooks270 = verticalStyleHooks270 = Ext.Object.chain(Element.prototype.styleHooks); verticalStyleHooks90.width = { name: 'height' }; verticalStyleHooks90.height = { name: 'width' }; verticalStyleHooks90['margin-top'] = { name: 'marginLeft' }; verticalStyleHooks90['margin-right'] = { name: 'marginTop' }; verticalStyleHooks90['margin-bottom'] = { name: 'marginRight' }; verticalStyleHooks90['margin-left'] = { name: 'marginBottom' }; verticalStyleHooks90['padding-top'] = { name: 'paddingLeft' }; verticalStyleHooks90['padding-right'] = { name: 'paddingTop' }; verticalStyleHooks90['padding-bottom'] = { name: 'paddingRight' }; verticalStyleHooks90['padding-left'] = { name: 'paddingBottom' }; verticalStyleHooks90['border-top'] = { name: 'borderLeft' }; verticalStyleHooks90['border-right'] = { name: 'borderTop' }; verticalStyleHooks90['border-bottom'] = { name: 'borderRight' }; verticalStyleHooks90['border-left'] = { name: 'borderBottom' }; verticalStyleHooks270.width = { name: 'height' }; verticalStyleHooks270.height = { name: 'width' }; verticalStyleHooks270['margin-top'] = { name: 'marginRight' }; verticalStyleHooks270['margin-right'] = { name: 'marginBottom' }; verticalStyleHooks270['margin-bottom'] = { name: 'marginLeft' }; verticalStyleHooks270['margin-left'] = { name: 'marginTop' }; verticalStyleHooks270['padding-top'] = { name: 'paddingRight' }; verticalStyleHooks270['padding-right'] = { name: 'paddingBottom' }; verticalStyleHooks270['padding-bottom'] = { name: 'paddingLeft' }; verticalStyleHooks270['padding-left'] = { name: 'paddingTop' }; verticalStyleHooks270['border-top'] = { name: 'borderRight' }; verticalStyleHooks270['border-right'] = { name: 'borderBottom' }; verticalStyleHooks270['border-bottom'] = { name: 'borderLeft' }; verticalStyleHooks270['border-left'] = { name: 'borderTop' }; if (Ext.isIE7m) { styleHooks.fontSize = styleHooks['font-size'] = { name: 'fontSize', canThrow: true }; styleHooks.fontStyle = styleHooks['font-style'] = { name: 'fontStyle', canThrow: true }; styleHooks.fontFamily = styleHooks['font-family'] = { name: 'fontFamily', canThrow: true }; } if (Ext.isIEQuirks || Ext.isIE && Ext.ieVersion <= 8) { function getBorderWidth (dom, el, inline, style) { if (style[this.styleName] == 'none') { return '0px'; } return style[this.name]; } edges = ['Top','Right','Bottom','Left']; k = edges.length; while (k--) { edge = edges[k]; borderWidth = 'border' + edge + 'Width'; styleHooks['border-'+edge.toLowerCase()+'-width'] = styleHooks[borderWidth] = { name: borderWidth, styleName: 'border' + edge + 'Style', get: getBorderWidth }; } } Ext.getDoc().on('selectstart', function(ev, dom) { var doc = document.documentElement, selectableCls = Element.selectableCls, unselectableCls = Element.unselectableCls, tagName = dom && dom.tagName; tagName = tagName && tagName.toLowerCase(); if (tagName === 'input' || tagName === 'textarea') { return; } while (dom && dom.nodeType === 1 && dom !== doc) { var el = Ext.fly(dom); if (el.hasCls(selectableCls)) { return; } if (el.hasCls(unselectableCls)) { ev.stopEvent(); return; } dom = dom.parentNode; } }); }); Ext.onReady(function () { var opacityRe = /alpha\(opacity=(.*)\)/i, trimRe = /^\s+|\s+$/g, hooks = Ext.dom.Element.prototype.styleHooks; hooks.opacity = { name: 'opacity', afterSet: function(dom, value, el) { if (el.isLayer) { el.onOpacitySet(value); } } }; if (!Ext.supports.Opacity && Ext.isIE) { Ext.apply(hooks.opacity, { get: function (dom) { var filter = dom.style.filter, match, opacity; if (filter.match) { match = filter.match(opacityRe); if (match) { opacity = parseFloat(match[1]); if (!isNaN(opacity)) { return opacity ? opacity / 100 : 0; } } } return 1; }, set: function (dom, value) { var style = dom.style, val = style.filter.replace(opacityRe, '').replace(trimRe, ''); style.zoom = 1; if (typeof(value) == 'number' && value >= 0 && value < 1) { value *= 100; style.filter = val + (val.length ? ' ' : '') + 'alpha(opacity='+value+')'; } else { style.filter = val; } } }); } }); Ext.define('Ext.util.Positionable', { _positionTopLeft: ['position', 'top', 'left'], _alignRe: /^([a-z]+)-([a-z]+)(\?)?$/, afterSetPosition: Ext.emptyFn, adjustForConstraints: function(xy, parent) { var vector = this.getConstrainVector(parent, xy); if (vector) { xy[0] += vector[0]; xy[1] += vector[1]; } return xy; }, alignTo: function(element, position, offsets, animate) { var me = this, el = me.el; return me.setXY(me.getAlignToXY(element, position, offsets), el.anim && !!animate ? el.anim(animate) : false); }, anchorTo: function(anchorToEl, alignment, offsets, animate, monitorScroll, callback) { var me = this, scroll = !Ext.isEmpty(monitorScroll), action = function() { me.alignTo(anchorToEl, alignment, offsets, animate); Ext.callback(callback, me); }, anchor = me.getAnchor(); me.removeAnchor(); Ext.apply(anchor, { fn: action, scroll: scroll }); Ext.EventManager.onWindowResize(action, null); if (scroll) { Ext.EventManager.on(window, 'scroll', action, null, {buffer: !isNaN(monitorScroll) ? monitorScroll : 50}); } action(); return me; }, calculateAnchorXY: function(anchor, extraX, extraY, mySize) { var me = this, el = me.el, doc = document, isViewport = el.dom == doc.body || el.dom == doc, round = Math.round, xy, myWidth, myHeight; anchor = (anchor || "tl").toLowerCase(); mySize = mySize || {}; myWidth = mySize.width || isViewport ? Ext.Element.getViewWidth() : me.getWidth(); myHeight = mySize.height || isViewport ? Ext.Element.getViewHeight() : me.getHeight(); switch (anchor) { case 'tl' : xy = [0, 0]; break; case 'bl' : xy = [0, myHeight]; break; case 'tr' : xy = [myWidth, 0]; break; case 'c' : xy = [round(myWidth * 0.5), round(myHeight * 0.5)]; break; case 't' : xy = [round(myWidth * 0.5), 0]; break; case 'l' : xy = [0, round(myHeight * 0.5)]; break; case 'r' : xy = [myWidth, round(myHeight * 0.5)]; break; case 'b' : xy = [round(myWidth * 0.5), myHeight]; break; case 'tc' : xy = [round(myWidth * 0.5), 0]; break; case 'bc' : xy = [round(myWidth * 0.5), myHeight]; break; case 'br' : xy = [myWidth, myHeight]; } return [xy[0] + extraX, xy[1] + extraY]; }, convertPositionSpec: Ext.identityFn, getAlignToXY: function(alignToEl, posSpec, offset) { var me = this, viewportWidth = Ext.Element.getViewWidth() - 10, viewportHeight = Ext.Element.getViewHeight() - 10, doc = document, docElement = doc.documentElement, docBody = doc.body, scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0), scrollY = (docElement.scrollTop || docBody.scrollTop || 0), alignMatch, myPosition, alignToElPosition, myWidth, myHeight, alignToElRegion, swapY, swapX, constrain, align1, align2, p1y, p1x, p2y, p2x, x, y; alignToEl = Ext.get(alignToEl.el || alignToEl); if (!alignToEl || !alignToEl.dom) { } offset = offset || [0,0]; posSpec = (!posSpec || posSpec == "?" ? "tl-bl?" : (!(/-/).test(posSpec) && posSpec !== "" ? "tl-" + posSpec : posSpec || "tl-bl")).toLowerCase(); posSpec = me.convertPositionSpec(posSpec); alignMatch = posSpec.match(me._alignRe); align1 = alignMatch[1]; align2 = alignMatch[2]; constrain = !!alignMatch[3]; myPosition = me.getAnchorXY(align1, true); alignToElPosition = me.getAnchorToXY(alignToEl, align2, false); x = alignToElPosition[0] - myPosition[0] + offset[0]; y = alignToElPosition[1] - myPosition[1] + offset[1]; if (constrain) { myWidth = me.getWidth(); myHeight = me.getHeight(); alignToElRegion = alignToEl.getRegion(); p1y = align1.charAt(0); p1x = align1.charAt(align1.length - 1); p2y = align2.charAt(0); p2x = align2.charAt(align2.length - 1); swapY = ((p1y == "t" && p2y == "b") || (p1y == "b" && p2y == "t")); swapX = ((p1x == "r" && p2x == "l") || (p1x == "l" && p2x == "r")); if (x + myWidth > viewportWidth + scrollX) { x = swapX ? alignToElRegion.left - myWidth : viewportWidth + scrollX - myWidth; } if (x < scrollX) { x = swapX ? alignToElRegion.right : scrollX; } if (y + myHeight > viewportHeight + scrollY) { y = swapY ? alignToElRegion.top - myHeight : viewportHeight + scrollY - myHeight; } if (y < scrollY) { y = swapY ? alignToElRegion.bottom : scrollY; } } return [x,y]; }, getAnchor: function(){ var el = this.el, data = (el.$cache || el.getCache()).data, anchor; if (!el.dom) { return; } anchor = data._anchor; if(!anchor){ anchor = data._anchor = {}; } return anchor; }, getAnchorXY: function(anchor, local, mySize) { var me = this, myPos = me.getXY(), el = me.el, doc = document, isViewport = el.dom == doc.body || el.dom == doc, scroll = el.getScroll(), extraX = isViewport ? scroll.left : local ? 0 : myPos[0], extraY = isViewport ? scroll.top : local ? 0 : myPos[1]; return me.calculateAnchorXY(anchor, extraX, extraY, mySize); }, getBox: function(contentBox, local) { var me = this, xy = local ? me.getLocalXY() : me.getXY(), x = xy[0], y = xy[1], w = me.getWidth(), h = me.getHeight(), borderPadding, beforeX, beforeY; if (contentBox) { borderPadding = me.getBorderPadding(); beforeX = borderPadding.beforeX; beforeY = borderPadding.beforeY; x += beforeX; y += beforeY; w -= (beforeX + borderPadding.afterX); h -= (beforeY + borderPadding.afterY); } return { x: x, left: x, 0: x, y: y, top: y, 1: y, width: w, height: h, right: x + w, bottom: y + h }; }, calculateConstrainedPosition: function(constrainTo, proposedPosition, local, proposedSize) { var me = this, vector, fp = me.floatParent, parentNode = fp ? fp.getTargetEl() : null, parentOffset, borderPadding, proposedConstrainPosition, xy = false; if (local && fp) { parentOffset = parentNode.getXY(); borderPadding = parentNode.getBorderPadding(); parentOffset[0] += borderPadding.beforeX; parentOffset[1] += borderPadding.beforeY; if (proposedPosition) { proposedConstrainPosition = [proposedPosition[0] + parentOffset[0], proposedPosition[1] + parentOffset[1]]; } } else { proposedConstrainPosition = proposedPosition; } constrainTo = constrainTo || me.constrainTo || parentNode || me.container || me.el.parent(); vector = (me.constrainHeader ? me.header : me).getConstrainVector(constrainTo, proposedConstrainPosition, proposedSize); if (vector) { xy = proposedPosition || me.getPosition(local); xy[0] += vector[0]; xy[1] += vector[1]; } return xy; }, getConstrainVector: function(constrainTo, proposedPosition, proposedSize) { var thisRegion = this.getRegion(), vector = [0, 0], shadowSize = (this.shadow && this.constrainShadow && !this.shadowDisabled) ? this.shadow.getShadowSize() : undefined, overflowed = false, constraintInsets = this.constraintInsets; if (!(constrainTo instanceof Ext.util.Region)) { constrainTo = Ext.get(constrainTo.el || constrainTo).getViewRegion(); } if (constraintInsets) { constraintInsets = Ext.isObject(constraintInsets) ? constraintInsets : Ext.Element.parseBox(constraintInsets); constrainTo.adjust(constraintInsets.top, constraintInsets.right, constraintInsets.bottom, constraintInsets.length); } if (proposedPosition) { thisRegion.translateBy(proposedPosition[0] - thisRegion.x, proposedPosition[1] - thisRegion.y); } if (proposedSize) { thisRegion.right = thisRegion.left + proposedSize[0]; thisRegion.bottom = thisRegion.top + proposedSize[1]; } if (shadowSize) { constrainTo.adjust(shadowSize[0], -shadowSize[1], -shadowSize[2], shadowSize[3]); } if (thisRegion.right > constrainTo.right) { overflowed = true; vector[0] = (constrainTo.right - thisRegion.right); } if (thisRegion.left + vector[0] < constrainTo.left) { overflowed = true; vector[0] = (constrainTo.left - thisRegion.left); } if (thisRegion.bottom > constrainTo.bottom) { overflowed = true; vector[1] = (constrainTo.bottom - thisRegion.bottom); } if (thisRegion.top + vector[1] < constrainTo.top) { overflowed = true; vector[1] = (constrainTo.top - thisRegion.top); } return overflowed ? vector : false; }, getOffsetsTo: function(offsetsTo) { var o = this.getXY(), e = Ext.fly(offsetsTo.el || offsetsTo, '_internal').getXY(); return [o[0] - e[0],o[1] - e[1]]; }, getRegion: function() { var box = this.getBox(); return new Ext.util.Region(box.top, box.right, box.bottom, box.left); }, getViewRegion: function() { var me = this, el = me.el, isBody = el.dom.nodeName === 'BODY', borderPadding, scroll, pos, top, left, width, height; if (isBody) { scroll = el.getScroll(); left = scroll.left; top = scroll.top; width = Ext.dom.AbstractElement.getViewportWidth(); height = Ext.dom.AbstractElement.getViewportHeight(); } else { borderPadding = me.getBorderPadding(); pos = me.getXY(); left = pos[0] + borderPadding.beforeX; top = pos[1] + borderPadding.beforeY; width = me.getWidth(true); height = me.getHeight(true); } return new Ext.util.Region(top, left + width, top + height, left); }, move: function(direction, distance, animate) { var me = this, xy = me.getXY(), x = xy[0], y = xy[1], left = [x - distance, y], right = [x + distance, y], top = [x, y - distance], bottom = [x, y + distance], hash = { l: left, left: left, r: right, right: right, t: top, top: top, up: top, b: bottom, bottom: bottom, down: bottom }; direction = direction.toLowerCase(); me.setXY([hash[direction][0], hash[direction][1]], animate); }, removeAnchor: function() { var anchor = this.getAnchor(); if (anchor && anchor.fn) { Ext.EventManager.removeResizeListener(anchor.fn); if (anchor.scroll) { Ext.EventManager.un(window, 'scroll', anchor.fn); } delete anchor.fn; } return this; }, setBox: function(box, animate) { var me = this, el = me.el, x = box.x, y = box.y, xy = [x, y], w = box.width, h = box.height, doConstrain = (me.constrain || me.constrainHeader), constrainedPos = doConstrain && me.calculateConstrainedPosition(null, [x, y], false, [w, h]); if (constrainedPos) { x = constrainedPos[0]; y = constrainedPos[1]; } if (!animate || !el.anim) { me.setSize(w, h); me.setXY([x, y]); me.afterSetPosition(x, y); } else { me.animate(Ext.applyIf({ to: { x: x, y: y, width: el.adjustWidth(w), height: el.adjustHeight(h) }, listeners: { afteranimate: Ext.Function.bind(me.afterSetPosition, me, [x, y]) } }, animate)); } return me; }, setRegion: function(region, animate) { return this.setBox({ x: region.left, y: region.top, width: region.right - region.left, height: region.bottom - region.top }, animate); }, translatePoints: function(x, y) { var pos = this.translateXY(x, y); return { left: pos.x, top: pos.y }; }, translateXY: function(x, y) { var me = this, el = me.el, styles = el.getStyle(me._positionTopLeft), relative = styles.position == 'relative', left = parseFloat(styles.left), top = parseFloat(styles.top), xy = me.getXY(); if (Ext.isArray(x)) { y = x[1]; x = x[0]; } if (isNaN(left)) { left = relative ? 0 : el.dom.offsetLeft; } if (isNaN(top)) { top = relative ? 0 : el.dom.offsetTop; } left = (typeof x == 'number') ? x - xy[0] + left : undefined; top = (typeof y == 'number') ? y - xy[1] + top : undefined; return { x: left, y: top }; } }); Ext.define('Ext.dom.Element', function(Element) { var HIDDEN = 'hidden', DOC = document, VISIBILITY = "visibility", DISPLAY = "display", NONE = "none", XMASKED = Ext.baseCSSPrefix + "masked", XMASKEDRELATIVE = Ext.baseCSSPrefix + "masked-relative", EXTELMASKMSG = Ext.baseCSSPrefix + "mask-msg", bodyRe = /^body/i, visFly, noBoxAdjust = Ext.isStrict ? { select: 1 }: { input: 1, select: 1, textarea: 1 }, isScrolled = function(c) { var r = [], ri = -1, i, ci; for (i = 0; ci = c[i]; i++) { if (ci.scrollTop > 0 || ci.scrollLeft > 0) { r[++ri] = ci; } } return r; }; return { extend: Ext.dom.AbstractElement , alternateClassName: ['Ext.Element', 'Ext.core.Element'], tableTagRe: /^(?:tr|td|table|tbody)$/i, mixins: [ Ext.util.Positionable ], addUnits: function() { return Element.addUnits.apply(Element, arguments); }, focus: function(defer, dom) { var me = this; dom = dom || me.dom; try { if (Number(defer)) { Ext.defer(me.focus, defer, me, [null, dom]); } else { dom.focus(); } } catch(e) { } return me; }, blur: function() { var me = this, dom = me.dom; if (dom !== document.body) { try { dom.blur(); } catch(e) { } return me; } else { return me.focus(undefined, dom); } }, isBorderBox: function() { var box = Ext.isBorderBox; if (box && Ext.isIE7m) { box = !((this.dom.tagName || "").toLowerCase() in noBoxAdjust); } return box; }, hover: function(overFn, outFn, scope, options) { var me = this; me.on('mouseenter', overFn, scope || me.dom, options); me.on('mouseleave', outFn, scope || me.dom, options); return me; }, getAttributeNS: function(ns, name) { return this.getAttribute(name, ns); }, getAttribute: (Ext.isIE && !(Ext.isIE9p && DOC.documentMode >= 9)) ? function(name, ns) { var d = this.dom, type; if (ns) { type = typeof d[ns + ":" + name]; if (type != 'undefined' && type != 'unknown') { return d[ns + ":" + name] || null; } return null; } if (name === "for") { name = "htmlFor"; } return d[name] || null; } : function(name, ns) { var d = this.dom; if (ns) { return d.getAttributeNS(ns, name) || d.getAttribute(ns + ":" + name); } return d.getAttribute(name) || d[name] || null; }, cacheScrollValues: function() { var me = this, scrolledDescendants, el, i, scrollValues = [], result = function() { for (i = 0; i < scrolledDescendants.length; i++) { el = scrolledDescendants[i]; el.scrollLeft = scrollValues[i][0]; el.scrollTop = scrollValues[i][1]; } }; if (!Ext.DomQuery.pseudos.isScrolled) { Ext.DomQuery.pseudos.isScrolled = isScrolled; } scrolledDescendants = me.query(':isScrolled'); for (i = 0; i < scrolledDescendants.length; i++) { el = scrolledDescendants[i]; scrollValues[i] = [el.scrollLeft, el.scrollTop]; } return result; }, autoBoxAdjust: true, isVisible : function(deep) { var me = this, dom = me.dom, stopNode = dom.ownerDocument.documentElement; if (!visFly) { visFly = new Element.Fly(); } while (dom !== stopNode) { if (!dom || dom.nodeType === 11 || (visFly.attach(dom)).isStyle(VISIBILITY, HIDDEN) || visFly.isStyle(DISPLAY, NONE)) { return false; } if (!deep) { break; } dom = dom.parentNode; } return true; }, isDisplayed : function() { return !this.isStyle(DISPLAY, NONE); }, enableDisplayMode : function(display) { var me = this; me.setVisibilityMode(Element.DISPLAY); if (!Ext.isEmpty(display)) { (me.$cache || me.getCache()).data.originalDisplay = display; } return me; }, mask : function(msg, msgCls , elHeight) { var me = this, dom = me.dom, setExpression = dom.style.setExpression, data = (me.$cache || me.getCache()).data, maskShimEl = data.maskShimEl, maskEl = data.maskEl, maskMsg = data.maskMsg, widthExpression, heightExpression, docElem, ie6DocElHeight; if (!(bodyRe.test(dom.tagName) && me.getStyle('position') == 'static')) { me.addCls(XMASKEDRELATIVE); } if (maskEl) { maskEl.remove(); } if (maskMsg) { maskMsg.remove(); } if (maskShimEl) { maskShimEl.remove(); } if (Ext.isIE6) { maskShimEl = Ext.DomHelper.append(dom, { tag: 'iframe', role: 'presentation', cls : Ext.baseCSSPrefix + 'shim ' + Ext.baseCSSPrefix + 'mask-shim' }, true); data.maskShimEl = maskShimEl; maskShimEl.setDisplayed(true); } Ext.DomHelper.append(dom, [{ role: 'presentation', cls : Ext.baseCSSPrefix + "mask", style: 'top:0;left:0;' }, { role: 'presentation', cls : msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG, cn : { tag: 'div', role: 'presentation', cls: Ext.baseCSSPrefix + 'mask-msg-inner', cn: { tag: 'div', role: 'presentation', cls: Ext.baseCSSPrefix + 'mask-msg-text', html: msg || '' } } }]); maskMsg = Ext.get(dom.lastChild); maskEl = Ext.get(maskMsg.dom.previousSibling); data.maskMsg = maskMsg; data.maskEl = maskEl; me.addCls(XMASKED); maskEl.setDisplayed(true); if (typeof msg == 'string') { maskMsg.setDisplayed(true); maskMsg.center(me); } else { maskMsg.setDisplayed(false); } if (Ext.isStrict && !Ext.isIE6) { if (dom === DOC.body) { maskEl.addCls(Ext.baseCSSPrefix + 'mask-fixed'); } } if (dom !== DOC.body || Ext.isIE6 || Ext.isIEQuirks) { if (!Ext.supports.IncludePaddingInWidthCalculation && setExpression) { try { maskEl.dom.style.setExpression('width', 'this.parentNode.clientWidth + "px"'); widthExpression = 'this.parentNode.clientWidth + "px"'; if (maskShimEl) { maskShimEl.dom.style.setExpression('width', widthExpression); } maskEl.dom.style.setExpression('width', widthExpression); } catch (e) {} } if (!Ext.supports.IncludePaddingInHeightCalculation && setExpression) { try { heightExpression = 'this.parentNode.' + (dom == DOC.body ? 'scrollHeight' : 'offsetHeight') + ' + "px"'; if (maskShimEl) { maskShimEl.dom.style.setExpression('height', heightExpression); } maskEl.dom.style.setExpression('height', heightExpression); } catch (e) {} } else if (Ext.isIE9m && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') { if (Ext.isIE6 && Ext.isStrict) { docElem = dom.parentNode; ie6DocElHeight = Math.max(docElem.clientHeight, docElem.scrollHeight); } if (maskShimEl) { maskShimEl.setSize(undefined, elHeight || ie6DocElHeight || me.getHeight()); } maskEl.setSize(undefined, elHeight || ie6DocElHeight || me.getHeight()); } } return maskEl; }, unmask : function() { var me = this, data = (me.$cache || me.getCache()).data, maskEl = data.maskEl, maskShimEl = data.maskShimEl, maskMsg = data.maskMsg, style; if (maskEl) { style = maskEl.dom.style; if (style.clearExpression) { style.clearExpression('width'); style.clearExpression('height'); } if (maskEl) { maskEl.remove(); delete data.maskEl; } if (maskMsg) { maskMsg.remove(); delete data.maskMsg; } me.removeCls([XMASKED, XMASKEDRELATIVE]); if (maskShimEl) { style = maskShimEl.dom.style; if (style.clearExpression) { style.clearExpression('width'); style.clearExpression('height'); } maskShimEl.remove(); delete data.maskShimEl; } } }, isMasked : function() { var me = this, data = (me.$cache || me.getCache()).data, maskEl = data.maskEl, maskMsg = data.maskMsg, hasMask = false; if (maskEl && maskEl.isVisible()) { if (maskMsg) { maskMsg.center(me); } hasMask = true; } return hasMask; }, createShim : function() { var el = DOC.createElement('iframe'), shim; el.frameBorder = '0'; el.className = Ext.baseCSSPrefix + 'shim'; el.src = Ext.SSL_SECURE_URL; el.setAttribute('role', 'presentation'); shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom)); shim.autoBoxAdjust = false; return shim; }, addKeyListener : function(key, fn, scope){ var config; if(typeof key != 'object' || Ext.isArray(key)){ config = { target: this, key: key, fn: fn, scope: scope }; }else{ config = { target: this, key : key.key, shift : key.shift, ctrl : key.ctrl, alt : key.alt, fn: fn, scope: scope }; } return new Ext.util.KeyMap(config); }, addKeyMap : function(config) { return new Ext.util.KeyMap(Ext.apply({ target: this }, config)); }, on: function(eventName, fn, scope, options) { Ext.EventManager.on(this, eventName, fn, scope || this, options); return this; }, un: function(eventName, fn, scope) { Ext.EventManager.un(this, eventName, fn, scope || this); return this; }, removeAllListeners: function() { Ext.EventManager.removeAll(this); return this; }, purgeAllListeners: function() { Ext.EventManager.purgeElement(this); return this; }, select: function(selector) { return Element.select(selector, false, this.dom); } }; }, function() { var DOC = document, EC = Ext.cache, Element = this, AbstractElement = Ext.dom.AbstractElement, focusRe = /^a|button|embed|iframe|input|object|select|textarea$/i, nonSpaceRe = /\S/, scriptTagRe = /(?:]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig, replaceScriptTagRe = /(?:)((\n|\r|.)*?)(?:<\/script>)/ig, srcRe = /\ssrc=([\'\"])(.*?)\1/i, typeRe = /\stype=([\'\"])(.*?)\1/i, useDocForId = !Ext.isIE8m, internalFly; Element.boxMarkup = [ '', '', '' ].join(''); function garbageCollect() { if (!Ext.enableGarbageCollector) { clearInterval(Element.collectorThreadId); } else { var eid, d, o, t; for (eid in EC) { if (!EC.hasOwnProperty(eid)) { continue; } o = EC[eid]; if (o.skipGarbageCollection) { continue; } d = o.dom; if (d && (!d.parentNode || (!d.offsetParent && !Ext.getElementById(eid)))) { if (Ext.enableListenerCollection) { Ext.EventManager.removeAll(d); } delete EC[eid]; } } if (Ext.isIE) { t = {}; for (eid in EC) { if (!EC.hasOwnProperty(eid)) { continue; } t[eid] = EC[eid]; } EC = Ext.cache = t; } } } Element.collectorThreadId = setInterval(garbageCollect, 30000); Element.addMethods({ monitorMouseLeave: function(delay, handler, scope) { var me = this, timer, listeners = { mouseleave: function(e) { timer = setTimeout(Ext.Function.bind(handler, scope||me, [e]), delay); }, mouseenter: function() { clearTimeout(timer); }, freezeEvent: true }; me.on(listeners); return listeners; }, swallowEvent : function(eventName, preventDefault) { var me = this, e, eLen, fn = function(e) { e.stopPropagation(); if (preventDefault) { e.preventDefault(); } }; if (Ext.isArray(eventName)) { eLen = eventName.length; for (e = 0; e < eLen; e++) { me.on(eventName[e], fn); } return me; } me.on(eventName, fn); return me; }, relayEvent : function(eventName, observable) { this.on(eventName, function(e) { observable.fireEvent(eventName, e); }); }, clean : function(forceReclean) { var me = this, dom = me.dom, data = (me.$cache || me.getCache()).data, n = dom.firstChild, ni = -1, nx; if (data.isCleaned && forceReclean !== true) { return me; } while (n) { nx = n.nextSibling; if (n.nodeType == 3) { if (!(nonSpaceRe.test(n.nodeValue))) { dom.removeChild(n); } else if (nx && nx.nodeType == 3) { n.appendData(Ext.String.trim(nx.data)); dom.removeChild(nx); nx = n.nextSibling; n.nodeIndex = ++ni; } } else { internalFly.attach(n).clean(); n.nodeIndex = ++ni; } n = nx; } data.isCleaned = true; return me; }, load : function(options) { this.getLoader().load(options); return this; }, getLoader : function() { var me = this, data = (me.$cache || me.getCache()).data, loader = data.loader; if (!loader) { data.loader = loader = new Ext.ElementLoader({ target: me }); } return loader; }, syncContent: function(source) { source = Ext.getDom(source); var sourceNodes = source.childNodes, sourceLen = sourceNodes.length, dest = this.dom, destNodes = dest.childNodes, destLen = destNodes.length, i, destNode, sourceNode, nodeType, newAttrs, attLen, attName; if (Ext.isIE9m && dest.mergeAttributes) { dest.mergeAttributes(source, true); dest.src = source.src; } else { newAttrs = source.attributes; attLen = newAttrs.length; for (i = 0; i < attLen; i++) { attName = newAttrs[i].name; if (attName !== 'id') { dest.setAttribute(attName, newAttrs[i].value); } } } if (sourceLen !== destLen) { dest.innerHTML = source.innerHTML; return; } for (i = 0; i < sourceLen; i++) { sourceNode = sourceNodes[i]; destNode = destNodes[i]; nodeType = sourceNode.nodeType; if (nodeType !== destNode.nodeType || (nodeType === 1 && sourceNode.tagName !== destNode.tagName)) { dest.innerHTML = source.innerHTML; return; } if (nodeType === 3) { destNode.data = sourceNode.data; } else { if (sourceNode.id && destNode.id !== sourceNode.id) { destNode.id = sourceNode.id; } destNode.style.cssText = sourceNode.style.cssText; destNode.className = sourceNode.className; internalFly.attach(destNode).syncContent(sourceNode); } } }, update : function(html, loadScripts, callback) { var me = this, id, dom, interval; if (!me.dom) { return me; } html = html || ''; dom = me.dom; if (loadScripts !== true) { dom.innerHTML = html; Ext.callback(callback, me); return me; } id = Ext.id(); html += ''; interval = setInterval(function() { var hd, match, attrs, srcMatch, typeMatch, el, s; if (!(el = DOC.getElementById(id))) { return false; } clearInterval(interval); Ext.removeNode(el); hd = Ext.getHead().dom; while ((match = scriptTagRe.exec(html))) { attrs = match[1]; srcMatch = attrs ? attrs.match(srcRe) : false; if (srcMatch && srcMatch[2]) { s = DOC.createElement("script"); s.src = srcMatch[2]; typeMatch = attrs.match(typeRe); if (typeMatch && typeMatch[2]) { s.type = typeMatch[2]; } hd.appendChild(s); } else if (match[2] && match[2].length > 0) { if (window.execScript) { window.execScript(match[2]); } else { window.eval(match[2]); } } } Ext.callback(callback, me); }, 20); dom.innerHTML = html.replace(replaceScriptTagRe, ''); return me; }, removeAllListeners : function() { this.removeAnchor(); Ext.EventManager.removeAll(this.dom); return this; }, createProxy : function(config, renderTo, matchBox) { config = (typeof config == 'object') ? config : { tag: "div", role: 'presentation', cls: config }; var me = this, proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) : Ext.DomHelper.insertBefore(me.dom, config, true); proxy.setVisibilityMode(Element.DISPLAY); proxy.hide(); if (matchBox && me.setBox && me.getBox) { proxy.setBox(me.getBox()); } return proxy; }, needsTabIndex: function() { if (this.dom) { if ((this.dom.nodeName === 'a') && (!this.dom.href)) { return true; } return !focusRe.test(this.dom.nodeName); } }, isFocusable: function ( asFocusEl) { var dom = this.dom, tabIndexAttr = dom.getAttributeNode('tabIndex'), tabIndex, nodeName = dom.nodeName, canFocus = false; if (tabIndexAttr && tabIndexAttr.specified) { tabIndex = tabIndexAttr.value; } if (dom && !dom.disabled) { if (tabIndex == -1) { canFocus = Ext.FocusManager && Ext.FocusManager.enabled && asFocusEl; } else { if (focusRe.test(nodeName)) { if ((nodeName !== 'a') || dom.href) { canFocus = true; } } else { canFocus = tabIndex != null && tabIndex >= 0; } } canFocus = canFocus && this.isVisible(true); } return canFocus; } }); if (Ext.isIE9m) { Element.prototype.getById = function (id, asDom) { var dom = this.dom, cacheItem, el, ret; if (dom) { el = (useDocForId && DOC.getElementById(id)) || dom.all[id]; if (el) { if (asDom) { ret = el; } else { cacheItem = EC[id]; if (cacheItem && cacheItem.el) { ret = Ext.updateCacheEntry(cacheItem, el).el; } else { ret = new Element(el); } } return ret; } } return asDom ? Ext.getDom(id) : Element.get(id); }; } Element.createAlias({ addListener: 'on', removeListener: 'un', clearListeners: 'removeAllListeners', focusable: 'isFocusable' }); Element.Fly = AbstractElement.Fly = new Ext.Class({ extend: Element, isFly: true, constructor: function(dom) { this.dom = dom; this.el = this; }, attach: AbstractElement.Fly.prototype.attach }); internalFly = new Element.Fly(); if (Ext.isIE9m) { Ext.getElementById = function (id) { var el = DOC.getElementById(id), detachedBodyEl; if (!el && (detachedBodyEl = AbstractElement.detachedBodyEl)) { el = detachedBodyEl.dom.all[id]; } return el; }; } else if (!DOC.querySelector) { Ext.getDetachedBody = Ext.getBody; Ext.getElementById = function (id) { return DOC.getElementById(id); }; } }); Ext.define('Ext.dom.CompositeElementLite', { alternateClassName: 'Ext.CompositeElementLite', statics: { importElementMethods: function() { var name, elementPrototype = Ext.dom.Element.prototype, prototype = this.prototype; for (name in elementPrototype) { if (typeof elementPrototype[name] == 'function'){ (function(key) { prototype[key] = prototype[key] || function() { return this.invoke(key, arguments); }; }).call(prototype, name); } } } }, constructor: function(elements, root) { this.elements = []; this.add(elements, root); this.el = new Ext.dom.AbstractElement.Fly(); }, isComposite: true, getElement: function(el) { return this.el.attach(el); }, transformElement: function(el) { return Ext.getDom(el); }, getCount: function() { return this.elements.length; }, add: function(els, root) { var elements = this.elements, i, ln; if (!els) { return this; } if (typeof els == "string") { els = Ext.dom.Element.selectorFunction(els, root); } else if (els.isComposite) { els = els.elements; } else if (!Ext.isIterable(els)) { els = [els]; } for (i = 0, ln = els.length; i < ln; ++i) { elements.push(this.transformElement(els[i])); } return this; }, invoke: function(fn, args) { var elements = this.elements, ln = elements.length, element, i; fn = Ext.dom.Element.prototype[fn]; for (i = 0; i < ln; i++) { element = elements[i]; if (element) { fn.apply(this.getElement(element), args); } } return this; }, item: function(index) { var el = this.elements[index], out = null; if (el) { out = this.getElement(el); } return out; }, slice: function() { return this.elements.slice.apply(this.elements, arguments); }, addListener: function(eventName, handler, scope, opt) { var els = this.elements, len = els.length, i, e; for (i = 0; i < len; i++) { e = els[i]; if (e) { Ext.EventManager.on(e, eventName, handler, scope || e, opt); } } return this; }, each: function(fn, scope) { var me = this, els = me.elements, len = els.length, i, e; for (i = 0; i < len; i++) { e = els[i]; if (e) { e = this.getElement(e); if (fn.call(scope || e, e, me, i) === false) { break; } } } return me; }, fill: function(els) { var me = this; me.elements = []; me.add(els); return me; }, insert: function(index, nodes) { Ext.Array.insert(this.elements, index, nodes); }, filter: function(selector) { var me = this, els = me.elements, len = els.length, out = [], i = 0, isFunc = typeof selector == 'function', add, el; for (; i < len; i++) { el = els[i]; add = false; if (el) { el = me.getElement(el); if (isFunc) { add = selector.call(el, el, me, i) !== false; } else { add = el.is(selector); } if (add) { out.push(me.transformElement(el)); } } } me.elements = out; return me; }, indexOf: function(el) { return Ext.Array.indexOf(this.elements, this.transformElement(el)); }, replaceElement: function(el, replacement, domReplace) { var index = !isNaN(el) ? el : this.indexOf(el), d; if (index > -1) { replacement = Ext.getDom(replacement); if (domReplace) { d = this.elements[index]; d.parentNode.insertBefore(replacement, d); Ext.removeNode(d); } Ext.Array.splice(this.elements, index, 1, replacement); } return this; }, clear: function(removeDom) { var me = this, els = me.elements, i = els.length - 1; if (removeDom) { for (; i >= 0; i--) { Ext.removeNode(els[i]); } } this.elements = []; }, addElements: function(els, root) { if (!els) { return this; } if (typeof els == "string") { els = Ext.dom.Element.selectorFunction(els, root); } var yels = this.elements, eLen = els.length, e; for (e = 0; e < eLen; e++) { yels.push(Ext.get(els[e])); } return this; }, first: function() { return this.item(0); }, last: function() { return this.item(this.getCount() - 1); }, contains: function(el) { return this.indexOf(el) != -1; }, removeElement: function(keys, removeDom) { keys = [].concat(keys); var me = this, elements = me.elements, kLen = keys.length, val, el, k; for (k = 0; k < kLen; k++) { val = keys[k]; if ((el = (elements[val] || elements[val = me.indexOf(val)]))) { if (removeDom) { if (el.dom) { el.remove(); } else { Ext.removeNode(el); } } Ext.Array.erase(elements, val, 1); } } return me; } }, function() { this.importElementMethods(); this.prototype.on = this.prototype.addListener; if (Ext.DomQuery){ Ext.dom.Element.selectorFunction = Ext.DomQuery.select; } Ext.dom.Element.select = function(selector, root) { var elements; if (typeof selector == "string") { elements = Ext.dom.Element.selectorFunction(selector, root); } else if (selector.length !== undefined) { elements = selector; } else { } return new Ext.CompositeElementLite(elements); }; Ext.select = function() { return Ext.dom.Element.select.apply(Ext.dom.Element, arguments); }; }); Ext.define('Ext.dom.CompositeElement', { alternateClassName: 'Ext.CompositeElement', extend: Ext.dom.CompositeElementLite , getElement: function(el) { return el; }, transformElement: function(el) { return Ext.get(el); } }, function() { Ext.dom.Element.select = function(selector, unique, root) { var elements; if (typeof selector == "string") { elements = Ext.dom.Element.selectorFunction(selector, root); } else if (selector.length !== undefined) { elements = selector; } else { } return (unique === true) ? new Ext.CompositeElement(elements) : new Ext.CompositeElementLite(elements); }; }); Ext.select = Ext.Element.select; Ext.define('Ext.util.HashMap', { mixins: { observable: Ext.util.Observable }, generation: 0, constructor: function(config) { config = config || {}; var me = this, keyFn = config.keyFn; me.initialConfig = config; me.addEvents( 'add', 'clear', 'remove', 'replace' ); me.mixins.observable.constructor.call(me, config); me.clear(true); if (keyFn) { me.getKey = keyFn; } }, getCount: function() { return this.length; }, getData: function(key, value) { if (value === undefined) { value = key; key = this.getKey(value); } return [key, value]; }, getKey: function(o) { return o.id; }, add: function(key, value) { var me = this; if (arguments.length === 1) { value = key; key = me.getKey(value); } if (me.containsKey(key)) { return me.replace(key, value); } me.map[key] = value; ++me.length; me.generation++; if (me.hasListeners.add) { me.fireEvent('add', me, key, value); } return value; }, replace: function(key, value) { var me = this, map = me.map, old; if (arguments.length === 1) { value = key; key = me.getKey(value); } if (!me.containsKey(key)) { me.add(key, value); } old = map[key]; map[key] = value; me.generation++; if (me.hasListeners.replace) { me.fireEvent('replace', me, key, value, old); } return value; }, remove: function(o) { var key = this.findKey(o); if (key !== undefined) { return this.removeAtKey(key); } return false; }, removeAtKey: function(key) { var me = this, value; if (me.containsKey(key)) { value = me.map[key]; delete me.map[key]; --me.length; me.generation++; if (me.hasListeners.remove) { me.fireEvent('remove', me, key, value); } return true; } return false; }, get: function(key) { var map = this.map; return map.hasOwnProperty(key) ? map[key] : undefined; }, clear: function( initial) { var me = this; if (initial || me.generation) { me.map = {}; me.length = 0; me.generation = initial ? 0 : me.generation + 1; } if (initial !== true && me.hasListeners.clear) { me.fireEvent('clear', me); } return me; }, containsKey: function(key) { var map = this.map; return map.hasOwnProperty(key) && map[key] !== undefined; }, contains: function(value) { return this.containsKey(this.findKey(value)); }, getKeys: function() { return this.getArray(true); }, getValues: function() { return this.getArray(false); }, getArray: function(isKey) { var arr = [], key, map = this.map; for (key in map) { if (map.hasOwnProperty(key)) { arr.push(isKey ? key: map[key]); } } return arr; }, each: function(fn, scope) { var items = Ext.apply({}, this.map), key, length = this.length; scope = scope || this; for (key in items) { if (items.hasOwnProperty(key)) { if (fn.call(scope, key, items[key], length) === false) { break; } } } return this; }, clone: function() { var hash = new this.self(this.initialConfig), map = this.map, key; hash.suspendEvents(); for (key in map) { if (map.hasOwnProperty(key)) { hash.add(key, map[key]); } } hash.resumeEvents(); return hash; }, findKey: function(value) { var key, map = this.map; for (key in map) { if (map.hasOwnProperty(key) && map[key] === value) { return key; } } return undefined; } }); Ext.define('Ext.AbstractManager', { typeName: 'type', constructor: function(config) { Ext.apply(this, config || {}); this.all = new Ext.util.HashMap(); this.types = {}; }, get : function(id) { return this.all.get(id); }, register: function(item) { this.all.add(item); }, unregister: function(item) { this.all.remove(item); }, registerType : function(type, cls) { this.types[type] = cls; cls[this.typeName] = type; }, isRegistered : function(type){ return this.types[type] !== undefined; }, create: function(config, defaultType) { var type = config[this.typeName] || config.type || defaultType, Constructor = this.types[type]; return new Constructor(config); }, onAvailable : function(id, fn, scope){ var all = this.all, item, callback; if (all.containsKey(id)) { item = all.get(id); fn.call(scope || item, item); } else { callback = function(map, key, item){ if (key == id) { fn.call(scope || item, item); all.un('add', callback); } }; all.on('add', callback); } }, each: function(fn, scope){ this.all.each(fn, scope || this); }, getCount: function(){ return this.all.getCount(); } }); Ext.define('Ext.ComponentManager', { extend: Ext.AbstractManager , alternateClassName: 'Ext.ComponentMgr', singleton: true, typeName: 'xtype', create: function(component, defaultType){ if (typeof component == 'string') { return Ext.widget(component); } if (component.isComponent) { return component; } return Ext.widget(component.xtype || defaultType, component); }, registerType: function(type, cls) { this.types[type] = cls; cls[this.typeName] = type; cls.prototype[this.typeName] = type; } }, function () { Ext.getCmp = function(id) { return Ext.ComponentManager.get(id); }; }); Ext.define('Ext.ComponentQuery', { singleton: true }, function() { var cq = this, domQueryOperators = Ext.dom.Query.operators, nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/, filterFnPattern = [ 'var r = [],', 'i = 0,', 'it = items,', 'l = it.length,', 'c;', 'for (; i < l; i++) {', 'c = it[i];', 'if (c.{0}) {', 'r.push(c);', '}', '}', 'return r;' ].join(''), filterItems = function(items, operation) { return operation.method.apply(this, [ items ].concat(operation.args)); }, getItems = function(items, mode) { var result = [], i = 0, length = items.length, candidate, deep = mode !== '>'; for (; i < length; i++) { candidate = items[i]; if (candidate.getRefItems) { result = result.concat(candidate.getRefItems(deep)); } } return result; }, getAncestors = function(items) { var result = [], i = 0, length = items.length, candidate; for (; i < length; i++) { candidate = items[i]; while (!!(candidate = candidate.getRefOwner())) { result.push(candidate); } } return result; }, filterByXType = function(items, xtype, shallow) { if (xtype === '*') { return items.slice(); } else { var result = [], i = 0, length = items.length, candidate; for (; i < length; i++) { candidate = items[i]; if (candidate.isXType(xtype, shallow)) { result.push(candidate); } } return result; } }, filterByClassName = function(items, className) { var result = [], i = 0, length = items.length, candidate; for (; i < length; i++) { candidate = items[i]; if (candidate.hasCls(className)) { result.push(candidate); } } return result; }, filterByAttribute = function(items, property, operator, compareTo) { var result = [], i = 0, length = items.length, mustBeOwnProperty, presenceOnly, candidate, propValue, j, propLen; if (property.charAt(0) === '@') { mustBeOwnProperty = true; property = property.substr(1); } if (property.charAt(0) === '?') { mustBeOwnProperty = true; presenceOnly = true; property = property.substr(1); } for (; i < length; i++) { candidate = items[i]; if (!mustBeOwnProperty || candidate.hasOwnProperty(property)) { propValue = candidate[property]; if (presenceOnly) { result.push(candidate); } else if (operator === '~=') { if (propValue) { if (!Ext.isArray(propValue)) { propValue = propValue.split(' '); } for (j = 0, propLen = propValue.length; j < propLen; j++) { if (domQueryOperators[operator](Ext.coerce(propValue[j], compareTo), compareTo)) { result.push(candidate); break; } } } } else if (!compareTo ? !!candidate[property] : domQueryOperators[operator](Ext.coerce(propValue, compareTo), compareTo)) { result.push(candidate); } } } return result; }, filterById = function(items, id) { var result = [], i = 0, length = items.length, candidate; for (; i < length; i++) { candidate = items[i]; if (candidate.getItemId() === id) { result.push(candidate); } } return result; }, filterByPseudo = function(items, name, value) { return cq.pseudos[name](items, value); }, modeRe = /^(\s?([>\^])\s?|\s|$)/, tokenRe = /^(#)?([\w\-]+|\*)(?:\((true|false)\))?/, matchers = [{ re: /^\.([\w\-]+)(?:\((true|false)\))?/, method: filterByXType }, { re: /^(?:\[((?:[@?$])?[\w\-]*)\s*(?:([\^$*~%!]?=)\s*['"]?(.*?)["']?)?\])/, method: filterByAttribute }, { re: /^#([\w\-]+)/, method: filterById }, { re: /^\:([\w\-]+)(?:\(((?:\{[^\}]+\})|(?:(?!\{)[^\s>\/]*?(?!\})))\))?/, method: filterByPseudo }, { re: /^(?:\{([^\}]+)\})/, method: filterFnPattern }]; cq.Query = Ext.extend(Object, { constructor: function(cfg) { cfg = cfg || {}; Ext.apply(this, cfg); }, execute : function(root) { var operations = this.operations, i = 0, length = operations.length, operation, workingItems; if (!root) { workingItems = Ext.ComponentManager.all.getArray(); } else if (Ext.isIterable(root)) { workingItems = root; } else if (root.isMixedCollection) { workingItems = root.items; } for (; i < length; i++) { operation = operations[i]; if (operation.mode === '^') { workingItems = getAncestors(workingItems || [root]); } else if (operation.mode) { workingItems = getItems(workingItems || [root], operation.mode); } else { workingItems = filterItems(workingItems || getItems([root]), operation); } if (i === length -1) { return workingItems; } } return []; }, is: function(component) { var operations = this.operations, len = operations.length, active = [component], operation, i, j, mode, matches, items, item; for (i = len - 1; i >= 0; --i) { operation = operations[i]; mode = operation.mode; if (mode) { if (mode === '^') { active = getItems(active, ' '); } else if (mode === '>') { items = []; for (j = 0, len = active.length; j < len; ++j) { item = active[j].getRefOwner(); if (item) { items.push(item); } } active = items; } else { active = getAncestors(active); } if (active.length === 0) { return false; } } else { active = filterItems(active, operation); if (active.length === 0) { return false; } } } return true; }, getMatches: function(components, operations) { var len = operations.length, i; for (i = 0; i < len; ++i) { components = filterItems(components, operations[i]); if (components.length === 0) { break; } } return components; } }); Ext.apply(this, { cache: {}, pseudos: { not: function(components, selector){ var CQ = Ext.ComponentQuery, i = 0, length = components.length, results = [], index = -1, component; for(; i < length; ++i) { component = components[i]; if (!CQ.is(component, selector)) { results[++index] = component; } } return results; }, first: function(components) { var ret = []; if (components.length > 0) { ret.push(components[0]); } return ret; }, last: function(components) { var len = components.length, ret = []; if (len > 0) { ret.push(components[len - 1]); } return ret; }, focusable: function(cmps) { var len = cmps.length, results = [], i = 0, c; for (; i < len; i++) { c = cmps[i]; if (c.isFocusable()) { results.push(c); } } return results; }, "nth-child" : function(c, a) { var result = [], m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a), f = (m[1] || 1) - 0, l = m[2] - 0, i, n, nodeIndex; for (i = 0; n = c[i]; i++) { nodeIndex = i + 1; if (f == 1) { if (l == 0 || nodeIndex == l) { result.push(n); } } else if ((nodeIndex + l) % f == 0){ result.push(n); } } return result; } }, query: function(selector, root) { var selectors = selector.split(','), length = selectors.length, i = 0, results = [], noDupResults = [], dupMatcher = {}, query, resultsLn, cmp; for (; i < length; i++) { selector = Ext.String.trim(selectors[i]); query = this.cache[selector] || (this.cache[selector] = this.parse(selector)); results = results.concat(query.execute(root)); } if (length > 1) { resultsLn = results.length; for (i = 0; i < resultsLn; i++) { cmp = results[i]; if (!dupMatcher[cmp.id]) { noDupResults.push(cmp); dupMatcher[cmp.id] = true; } } results = noDupResults; } return results; }, is: function(component, selector) { if (!selector) { return true; } var selectors = selector.split(','), length = selectors.length, i = 0, query; for (; i < length; i++) { selector = Ext.String.trim(selectors[i]); query = this.cache[selector] || (this.cache[selector] = this.parse(selector)); if (query.is(component)) { return true; } } return false; }, parse: function(selector) { var operations = [], length = matchers.length, lastSelector, tokenMatch, matchedChar, modeMatch, selectorMatch, i, matcher, method; while (selector && lastSelector !== selector) { lastSelector = selector; tokenMatch = selector.match(tokenRe); if (tokenMatch) { matchedChar = tokenMatch[1]; if (matchedChar === '#') { operations.push({ method: filterById, args: [Ext.String.trim(tokenMatch[2])] }); } else if (matchedChar === '.') { operations.push({ method: filterByClassName, args: [Ext.String.trim(tokenMatch[2])] }); } else { operations.push({ method: filterByXType, args: [Ext.String.trim(tokenMatch[2]), Boolean(tokenMatch[3])] }); } selector = selector.replace(tokenMatch[0], ''); } while (!(modeMatch = selector.match(modeRe))) { for (i = 0; selector && i < length; i++) { matcher = matchers[i]; selectorMatch = selector.match(matcher.re); method = matcher.method; if (selectorMatch) { operations.push({ method: Ext.isString(matcher.method) ? Ext.functionFactory('items', Ext.String.format.apply(Ext.String, [method].concat(selectorMatch.slice(1)))) : matcher.method, args: selectorMatch.slice(1) }); selector = selector.replace(selectorMatch[0], ''); break; } if (i === (length - 1)) { Ext.Error.raise('Invalid ComponentQuery selector: "' + arguments[0] + '"'); } } } if (modeMatch[1]) { operations.push({ mode: modeMatch[2]||modeMatch[1] }); selector = selector.replace(modeMatch[0], ''); } } return new cq.Query({ operations: operations }); } }); }); Ext.define('Ext.util.ProtoElement', (function () { var splitWords = Ext.String.splitWords, toMap = Ext.Array.toMap; return { isProtoEl: true, clsProp: 'cls', styleProp: 'style', removedProp: 'removed', styleIsText: false, constructor: function (config) { var me = this; Ext.apply(me, config); me.classList = splitWords(me.cls); me.classMap = toMap(me.classList); delete me.cls; if (Ext.isFunction(me.style)) { me.styleFn = me.style; delete me.style; } else if (typeof me.style == 'string') { me.style = Ext.Element.parseStyles(me.style); } else if (me.style) { me.style = Ext.apply({}, me.style); } }, flush: function(){ this.flushClassList = []; this.removedClasses = {}; delete this.style; delete this.unselectableAttr; }, addCls: function (cls) { var me = this, add = (typeof cls === 'string') ? splitWords(cls) : cls, length = add.length, list = me.classList, map = me.classMap, flushList = me.flushClassList, i = 0, c; for (; i < length; ++i) { c = add[i]; if (!map[c]) { map[c] = true; list.push(c); if (flushList) { flushList.push(c); delete me.removedClasses[c]; } } } return me; }, hasCls: function (cls) { return cls in this.classMap; }, removeCls: function (cls) { var me = this, list = me.classList, newList = (me.classList = []), remove = toMap(splitWords(cls)), length = list.length, map = me.classMap, removedClasses = me.removedClasses, i, c; for (i = 0; i < length; ++i) { c = list[i]; if (remove[c]) { if (removedClasses) { if (map[c]) { removedClasses[c] = true; Ext.Array.remove(me.flushClassList, c); } } delete map[c]; } else { newList.push(c); } } return me; }, setStyle: function (prop, value) { var me = this, style = me.style || (me.style = {}); if (typeof prop == 'string') { if (arguments.length === 1) { me.setStyle(Ext.Element.parseStyles(prop)); } else { style[prop] = value; } } else { Ext.apply(style, prop); } return me; }, unselectable: function() { this.addCls(Ext.dom.Element.unselectableCls); if (Ext.isOpera) { this.unselectableAttr = true; } }, writeTo: function (to) { var me = this, classList = me.flushClassList || me.classList, removedClasses = me.removedClasses, style; if (me.styleFn) { style = Ext.apply({}, me.styleFn()); Ext.apply(style, me.style); } else { style = me.style; } to[me.clsProp] = classList.join(' '); if (style) { to[me.styleProp] = me.styleIsText ? Ext.DomHelper.generateStyles(style, null, true) : style; } if (removedClasses) { removedClasses = Ext.Object.getKeys(removedClasses); if (removedClasses.length) { to[me.removedProp] = removedClasses.join(' '); } } if (me.unselectableAttr) { to.unselectable = 'on'; } return to; } }; }())); Ext.define('Ext.PluginManager', { extend: Ext.AbstractManager , alternateClassName: 'Ext.PluginMgr', singleton: true, typeName: 'ptype', create : function(config, defaultType, host) { var result; if (config.init) { result = config; } else { if (host) { config = Ext.apply({}, config); config.cmp = host; } else { host = config.cmp; } if (config.xclass) { result = Ext.create(config); } else { result = Ext.ClassManager.getByAlias(('plugin.' + (config.ptype || defaultType))); if (typeof result === 'function') { result = new result(config); } } } if (result && host && result.setCmp && !result.setCmpCalled) { result.setCmp(host); result.setCmpCalled = true; } return result; }, findByType: function(type, defaultsOnly) { var matches = [], types = this.types, name, item; for (name in types) { if (!types.hasOwnProperty(name)) { continue; } item = types[name]; if (item.type == type && (!defaultsOnly || (defaultsOnly === true && item.isDefault))) { matches.push(item); } } return matches; } }, function() { Ext.preg = function() { return Ext.PluginManager.registerType.apply(Ext.PluginManager, arguments); }; }); Ext.define('Ext.util.Filter', { id: null, anyMatch: false, exactMatch: false, caseSensitive: false, disabled: false, operator: null, statics: { createFilterFn: function(filters) { return filters && filters.length ? function(candidate) { var isMatch = true, length = filters.length, i, filter; for (i = 0; isMatch && i < length; i++) { filter = filters[i]; if (!filter.disabled) { isMatch = isMatch && filter.filterFn.call(filter.scope || filter, candidate); } } return isMatch; } : function() { return true; }; } }, operatorFns: { "<": function(candidate) { return Ext.coerce(this.getRoot(candidate)[this.property], this.value) < this.value; }, "<=": function(candidate) { return Ext.coerce(this.getRoot(candidate)[this.property], this.value) <= this.value; }, "=": function(candidate) { return Ext.coerce(this.getRoot(candidate)[this.property], this.value) == this.value; }, ">=": function(candidate) { return Ext.coerce(this.getRoot(candidate)[this.property], this.value) >= this.value; }, ">": function(candidate) { return Ext.coerce(this.getRoot(candidate)[this.property], this.value) > this.value; }, "!=": function(candidate) { return Ext.coerce(this.getRoot(candidate)[this.property], this.value) != this.value; } }, constructor: function(config) { var me = this; me.initialConfig = config; Ext.apply(me, config); me.filter = me.filter || me.filterFn; if (me.filter === undefined) { me.setValue(config.value); } }, setValue: function(value) { var me = this; me.value = value; if (me.property === undefined || me.value === undefined) { } else { me.filter = me.createFilterFn(); } me.filterFn = me.filter; }, setFilterFn: function(filterFn) { this.filterFn = this.filter = filterFn; }, createFilterFn: function() { var me = this, matcher = me.createValueMatcher(), property = me.property; if (me.operator) { return me.operatorFns[me.operator]; } else { return function(item) { var value = me.getRoot(item)[property]; return matcher === null ? value === null : matcher.test(value); }; } }, getRoot: function(item) { var root = this.root; return root === undefined ? item : item[root]; }, createValueMatcher : function() { var me = this, value = me.value, anyMatch = me.anyMatch, exactMatch = me.exactMatch, caseSensitive = me.caseSensitive, escapeRe = Ext.String.escapeRegex; if (value === null) { return value; } if (!value.exec) { value = String(value); if (anyMatch === true) { value = escapeRe(value); } else { value = '^' + escapeRe(value); if (exactMatch === true) { value += '$'; } } value = new RegExp(value, caseSensitive ? '' : 'i'); } return value; }, serialize: function() { var me = this, result = Ext.apply({}, me.initialConfig); result.value = me.value; return result; } }, function() { this.prototype.operatorFns['=='] = this.prototype.operatorFns['=']; }); Ext.define('Ext.util.AbstractMixedCollection', { mixins: { observable: Ext.util.Observable }, isMixedCollection: true, generation: 0, indexGeneration: 0, constructor: function(allowFunctions, keyFn) { var me = this; if (arguments.length === 1 && Ext.isObject(allowFunctions)) { me.initialConfig = allowFunctions; Ext.apply(me, allowFunctions); } else { me.allowFunctions = allowFunctions === true; if (keyFn) { me.getKey = keyFn; } me.initialConfig = { allowFunctions: me.allowFunctions, getKey: me.getKey }; } me.items = []; me.map = {}; me.keys = []; me.indexMap = {}; me.length = 0; me.mixins.observable.constructor.call(me); }, allowFunctions : false, add : function(key, obj) { var len = this.length, out; if (arguments.length === 1) { out = this.insert(len, key); } else { out = this.insert(len, key, obj); } return out; }, getKey : function(o) { return o.id; }, replace : function(key, o) { var me = this, old, index; if (arguments.length == 1) { o = arguments[0]; key = me.getKey(o); } old = me.map[key]; if (typeof key == 'undefined' || key === null || typeof old == 'undefined') { return me.add(key, o); } me.generation++; index = me.indexOfKey(key); me.items[index] = o; me.map[key] = o; if (me.hasListeners.replace) { me.fireEvent('replace', key, old, o); } return o; }, updateKey: function(oldKey, newKey) { var me = this, map = me.map, indexMap = me.indexMap, index = me.indexOfKey(oldKey), item; if (index > -1) { item = map[oldKey]; delete map[oldKey]; delete indexMap[oldKey]; map[newKey] = item; indexMap[newKey] = index; me.keys[index] = newKey; me.indexGeneration = ++me.generation; } }, addAll : function(objs) { var me = this, key; if (arguments.length > 1 || Ext.isArray(objs)) { me.insert(me.length, arguments.length > 1 ? arguments : objs); } else { for (key in objs) { if (objs.hasOwnProperty(key)) { if (me.allowFunctions || typeof objs[key] != 'function') { me.add(key, objs[key]); } } } } }, each : function(fn, scope){ var items = Ext.Array.push([], this.items), i = 0, len = items.length, item; for (; i < len; i++) { item = items[i]; if (fn.call(scope || item, item, i, len) === false) { break; } } }, eachKey : function(fn, scope){ var keys = this.keys, items = this.items, i = 0, len = keys.length; for (; i < len; i++) { fn.call(scope || window, keys[i], items[i], i, len); } }, findBy : function(fn, scope) { var keys = this.keys, items = this.items, i = 0, len = items.length; for (; i < len; i++) { if (fn.call(scope || window, items[i], keys[i])) { return items[i]; } } return null; }, find : function() { if (Ext.isDefined(Ext.global.console)) { Ext.global.console.warn('Ext.util.MixedCollection: find has been deprecated. Use findBy instead.'); } return this.findBy.apply(this, arguments); }, insert : function(index, key, obj) { var out; if (Ext.isIterable(key)) { out = this.doInsert(index, key, obj); } else { if (arguments.length > 2) { out = this.doInsert(index, [key], [obj]); } else { out = this.doInsert(index, [key]); } out = out[0]; } return out; }, doInsert : function(index, keys, objects) { var me = this, itemKey, removeIndex, i, len = keys.length, deDupedLen = len, fireAdd = me.hasListeners.add, syncIndices, newKeys = {}, passedDuplicates, oldKeys, oldObjects; if (objects != null) { me.useLinearSearch = true; } else { objects = keys; keys = new Array(len); for (i = 0; i < len; i++) { keys[i] = this.getKey(objects[i]); } } me.suspendEvents(); for (i = 0; i < len; i++) { itemKey = keys[i]; removeIndex = me.indexOfKey(itemKey); if (removeIndex !== -1) { if (removeIndex < index) { index--; } me.removeAt(removeIndex); } if (itemKey != null) { if (newKeys[itemKey] != null) { passedDuplicates = true; deDupedLen--; } newKeys[itemKey] = i; } } me.resumeEvents(); if (passedDuplicates) { oldKeys = keys; oldObjects = objects; keys = new Array(deDupedLen); objects = new Array(deDupedLen); i = 0; for (itemKey in newKeys) { keys[i] = oldKeys[newKeys[itemKey]]; objects[i] = oldObjects[newKeys[itemKey]]; i++; } len = deDupedLen; } syncIndices = index === me.length && me.indexGeneration === me.generation; Ext.Array.insert(me.items, index, objects); Ext.Array.insert(me.keys, index, keys); me.length += len; me.generation++; if (syncIndices) { me.indexGeneration = me.generation; } for (i = 0; i < len; i++, index++) { itemKey = keys[i]; if (itemKey != null) { me.map[itemKey] = objects[i]; if (syncIndices) { me.indexMap[itemKey] = index; } } if (fireAdd) { me.fireEvent('add', index, objects[i], itemKey); } } return objects; }, remove : function(o) { var me = this, removeKey, index; if (!me.useLinearSearch && (removeKey = me.getKey(o))) { index = me.indexOfKey(removeKey); } else { index = Ext.Array.indexOf(me.items, o); } return (index === -1) ? false : me.removeAt(index); }, removeAll : function(items) { var me = this, i; if (items || me.hasListeners.remove) { if (items) { for (i = items.length - 1; i >= 0; --i) { me.remove(items[i]); } } else { while (me.length) { me.removeAt(0); } } } else { me.length = me.items.length = me.keys.length = 0; me.map = {}; me.indexMap = {}; me.generation++; me.indexGeneration = me.generation; } }, removeAt : function(index) { var me = this, o, key; if (index < me.length && index >= 0) { me.length--; o = me.items[index]; Ext.Array.erase(me.items, index, 1); key = me.keys[index]; if (typeof key != 'undefined') { delete me.map[key]; } Ext.Array.erase(me.keys, index, 1); if (me.hasListeners.remove) { me.fireEvent('remove', o, key); } me.generation++; return o; } return false; }, removeRange : function(index, removeCount) { var me = this, o, key, i, limit, syncIndices, trimming; if (index < me.length && index >= 0) { if (!removeCount) { removeCount = 1; } limit = Math.min(index + removeCount, me.length); removeCount = limit - index; trimming = limit === me.length; syncIndices = trimming && me.indexGeneration === me.generation; for (i = index; i < limit; i++) { key = me.keys[i]; if (key != null) { delete me.map[key]; if (syncIndices) { delete me.indexMap[key]; } } } o = me.items[i - 1]; me.length -= removeCount; me.generation++; if (syncIndices) { me.indexGeneration = me.generation; } if (trimming) { me.items.length = me.keys.length = me.length; } else { me.items.splice(index, removeCount); me.keys.splice(index, removeCount); } return o; } return false; }, removeAtKey : function(key) { var me = this, keys = me.keys, i; if (key == null) { for (i = keys.length - 1; i >=0; i--) { if (keys[i] == null) { me.removeAt(i); } } } else { return me.removeAt(me.indexOfKey(key)); } }, getCount : function() { return this.length; }, indexOf : function(o) { var me = this, key; if (o != null) { if (!me.useLinearSearch && (key = me.getKey(o))) { return this.indexOfKey(key); } return Ext.Array.indexOf(me.items, o); } return -1; }, indexOfKey : function(key) { if (!this.map.hasOwnProperty(key)) { return -1; } if (this.indexGeneration !== this.generation) { this.rebuildIndexMap(); } return this.indexMap[key]; }, rebuildIndexMap: function() { var me = this, indexMap = me.indexMap = {}, keys = me.keys, len = keys.length, i; for (i = 0; i < len; i++) { indexMap[keys[i]] = i; } me.indexGeneration = me.generation; }, get : function(key) { var me = this, mk = me.map[key], item = mk !== undefined ? mk : (typeof key == 'number') ? me.items[key] : undefined; return typeof item != 'function' || me.allowFunctions ? item : null; }, getAt : function(index) { return this.items[index]; }, getByKey : function(key) { return this.map[key]; }, contains : function(o) { var me = this, key; if (o != null) { if (!me.useLinearSearch && (key = me.getKey(o))) { return this.map[key] != null; } return Ext.Array.indexOf(this.items, o) !== -1; } return false; }, containsKey : function(key) { return this.map.hasOwnProperty(key); }, clear : function() { var me = this; if (me.generation) { me.length = 0; me.items = []; me.keys = []; me.map = {}; me.indexMap = {}; me.generation++; me.indexGeneration = me.generation; } if (me.hasListeners.clear) { me.fireEvent('clear'); } }, first : function() { return this.items[0]; }, last : function() { return this.items[this.length - 1]; }, sum: function(property, root, start, end) { var values = this.extractValues(property, root), length = values.length, sum = 0, i; start = start || 0; end = (end || end === 0) ? end : length - 1; for (i = start; i <= end; i++) { sum += values[i]; } return sum; }, collect: function(property, root, allowNull) { var values = this.extractValues(property, root), length = values.length, hits = {}, unique = [], value, strValue, i; for (i = 0; i < length; i++) { value = values[i]; strValue = String(value); if ((allowNull || !Ext.isEmpty(value)) && !hits[strValue]) { hits[strValue] = true; unique.push(value); } } return unique; }, extractValues: function(property, root) { var values = this.items; if (root) { values = Ext.Array.pluck(values, root); } return Ext.Array.pluck(values, property); }, hasRange: function(start, end) { return (end < this.length); }, getRange : function(start, end){ var me = this, items = me.items, range = [], len = items.length, tmp, reverse; if (len < 1) { return range; } if (start > end) { reverse = true; tmp = start; start = end; end = tmp; } if (start < 0) { start = 0; } if (end == null || end >= len) { end = len - 1; } range = items.slice(start, end + 1); if (reverse && range.length) { range.reverse(); } return range; }, filter : function(property, value, anyMatch, caseSensitive) { var filters = []; if (Ext.isString(property)) { filters.push(new Ext.util.Filter({ property : property, value : value, anyMatch : anyMatch, caseSensitive: caseSensitive })); } else if (Ext.isArray(property) || property instanceof Ext.util.Filter) { filters = filters.concat(property); } return this.filterBy(Ext.util.Filter.createFilterFn(filters)); }, filterBy : function(fn, scope) { var me = this, newMC = new me.self(me.initialConfig), keys = me.keys, items = me.items, length = items.length, i; newMC.getKey = me.getKey; for (i = 0; i < length; i++) { if (fn.call(scope || me, items[i], keys[i])) { newMC.add(keys[i], items[i]); } } newMC.useLinearSearch = me.useLinearSearch; return newMC; }, findIndex : function(property, value, start, anyMatch, caseSensitive){ if(Ext.isEmpty(value, false)){ return -1; } value = this.createValueMatcher(value, anyMatch, caseSensitive); return this.findIndexBy(function(o){ return o && value.test(o[property]); }, null, start); }, findIndexBy : function(fn, scope, start){ var me = this, keys = me.keys, items = me.items, i = start || 0, len = items.length; for (; i < len; i++) { if (fn.call(scope || me, items[i], keys[i])) { return i; } } return -1; }, createValueMatcher : function(value, anyMatch, caseSensitive, exactMatch) { if (!value.exec) { var er = Ext.String.escapeRegex; value = String(value); if (anyMatch === true) { value = er(value); } else { value = '^' + er(value); if (exactMatch === true) { value += '$'; } } value = new RegExp(value, caseSensitive ? '' : 'i'); } return value; }, clone : function() { var me = this, copy = new me.self(me.initialConfig); copy.add(me.keys, me.items); copy.useLinearSearch = me.useLinearSearch; return copy; } }); Ext.define('Ext.util.Sorter', { direction: "ASC", constructor: function(config) { var me = this; Ext.apply(me, config); me.updateSortFunction(); }, createSortFunction: function(sorterFn) { var me = this, direction = me.direction || "ASC", modifier = direction.toUpperCase() == "DESC" ? -1 : 1; return function(o1, o2) { return modifier * sorterFn.call(me, o1, o2); }; }, defaultSorterFn: function(o1, o2) { var me = this, transform = me.transform, v1 = me.getRoot(o1)[me.property], v2 = me.getRoot(o2)[me.property]; if (transform) { v1 = transform(v1); v2 = transform(v2); } return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0); }, getRoot: function(item) { return this.root === undefined ? item : item[this.root]; }, setDirection: function(direction) { var me = this; me.direction = direction ? direction.toUpperCase() : direction; me.updateSortFunction(); }, toggle: function() { var me = this; me.direction = Ext.String.toggle(me.direction, "ASC", "DESC"); me.updateSortFunction(); }, updateSortFunction: function(fn) { var me = this; fn = fn || me.sorterFn || me.defaultSorterFn; me.sort = me.createSortFunction(fn); }, serialize: function() { return { root: this.root, property: this.property, direction: this.direction }; } }); Ext.define("Ext.util.Sortable", { isSortable: true, defaultSortDirection: "ASC", statics: { createComparator: function(sorters) { return sorters && sorters.length ? function(r1, r2) { var result = sorters[0].sort(r1, r2), length = sorters.length, i = 1; for (; i < length; i++) { result = result || sorters[i].sort.call(this, r1, r2); } return result; }: function() { return 0; }; } }, initSortable: function() { var me = this, sorters = me.sorters; me.sorters = new Ext.util.AbstractMixedCollection(false, function(item) { return item.id || item.property; }); if (sorters) { me.sorters.addAll(me.decodeSorters(sorters)); } }, sort: function(sorters, direction, where, doSort) { var me = this, sorter, newSorters; if (Ext.isArray(sorters)) { doSort = where; where = direction; newSorters = sorters; } else if (Ext.isObject(sorters)) { doSort = where; where = direction; newSorters = [sorters]; } else if (Ext.isString(sorters)) { sorter = me.sorters.get(sorters); if (!sorter) { sorter = { property : sorters, direction: direction }; newSorters = [sorter]; } else if (direction === undefined) { sorter.toggle(); } else { sorter.setDirection(direction); } } if (newSorters && newSorters.length) { newSorters = me.decodeSorters(newSorters); if (Ext.isString(where)) { if (where === 'prepend') { me.sorters.insert(0, newSorters); } else { me.sorters.addAll(newSorters); } } else { me.sorters.clear(); me.sorters.addAll(newSorters); } } if (doSort !== false) { me.fireEvent('beforesort', me, newSorters); me.onBeforeSort(newSorters); sorters = me.sorters.items; if (sorters.length) { me.doSort(me.generateComparator()); } } return sorters; }, generateComparator: function() { var sorters = this.sorters.getRange(); return sorters.length ? this.createComparator(sorters) : this.emptyComparator; }, emptyComparator: function(){ return 0; }, onBeforeSort: Ext.emptyFn, decodeSorters: function(sorters) { if (!Ext.isArray(sorters)) { if (sorters === undefined) { sorters = []; } else { sorters = [sorters]; } } var length = sorters.length, Sorter = Ext.util.Sorter, fields = this.model ? this.model.prototype.fields : null, field, config, i; for (i = 0; i < length; i++) { config = sorters[i]; if (!(config instanceof Sorter)) { if (Ext.isString(config)) { config = { property: config }; } Ext.applyIf(config, { root : this.sortRoot, direction: "ASC" }); if (config.fn) { config.sorterFn = config.fn; } if (typeof config == 'function') { config = { sorterFn: config }; } if (fields && !config.transform) { field = fields.get(config.property); config.transform = field && field.sortType !== Ext.identityFn ? field.sortType : undefined; } sorters[i] = new Ext.util.Sorter(config); } } return sorters; }, getSorters: function() { return this.sorters.items; }, getFirstSorter: function(){ var sorters = this.sorters.items, len = sorters.length, i = 0, sorter; for (; i < len; ++i) { sorter = sorters[i]; if (!sorter.isGrouper) { return sorter; } } return null; } }, function() { this.prototype.createComparator = this.createComparator; }); Ext.define('Ext.util.MixedCollection', { extend: Ext.util.AbstractMixedCollection , mixins: { sortable: Ext.util.Sortable }, constructor: function() { var me = this; me.callParent(arguments); me.addEvents('sort'); me.mixins.sortable.initSortable.call(me); }, doSort: function(sorterFn) { this.sortBy(sorterFn); }, _sort : function(property, dir, fn) { var me = this, i, len, dsc = String(dir).toUpperCase() == 'DESC' ? -1 : 1, c = [], keys = me.keys, items = me.items, o; fn = fn || function(a, b) { return a - b; }; for (i = 0, len = items.length; i < len; i++) { c[c.length] = { key : keys[i], value: items[i], index: i }; } Ext.Array.sort(c, function(a, b) { return fn(a[property], b[property]) * dsc || (a.index < b.index ? -1 : 1); }); for (i = 0, len = c.length; i < len; i++) { o = c[i]; items[i] = o.value; keys[i] = o.key; me.indexMap[o.key] = i; } me.generation++; me.indexGeneration = me.generation; me.fireEvent('sort', me); }, sortBy: function(sorterFn) { var me = this, items = me.items, item, keys = me.keys, key, length = items.length, i; for (i = 0; i < length; i++) { items[i].$extCollectionIndex = i; } Ext.Array.sort(items, function(a, b) { return sorterFn(a, b) || (a.$extCollectionIndex < b.$extCollectionIndex ? -1 : 1); }); for (i = 0; i < length; i++) { item = items[i]; key = me.getKey(item); keys[i] = key; me.indexMap[key] = i; delete items.$extCollectionIndex; } me.generation++; me.indexGeneration = me.generation; me.fireEvent('sort', me, items, keys); }, findInsertionIndex: function(newItem, sorterFn) { var me = this, items = me.items, start = 0, end = items.length - 1, middle, comparison; if (!sorterFn) { sorterFn = me.generateComparator(); } while (start <= end) { middle = (start + end) >> 1; comparison = sorterFn(newItem, items[middle]); if (comparison >= 0) { start = middle + 1; } else if (comparison < 0) { end = middle - 1; } } return start; }, reorder: function(mapping) { var me = this, items = me.items, index = 0, length = items.length, order = [], remaining = [], oldIndex; me.suspendEvents(); for (oldIndex in mapping) { order[mapping[oldIndex]] = items[oldIndex]; } for (index = 0; index < length; index++) { if (mapping[index] == undefined) { remaining.push(items[index]); } } for (index = 0; index < length; index++) { if (order[index] == undefined) { order[index] = remaining.shift(); } } me.clear(); me.addAll(order); me.resumeEvents(); me.fireEvent('sort', me); }, sortByKey : function(dir, fn){ this._sort('key', dir, fn || function(a, b){ var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase(); return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0); }); } }); Ext.define('Ext.fx.target.Target', { isAnimTarget: true, constructor: function(target) { this.target = target; this.id = this.getId(); }, getId: function() { return this.target.id; }, remove: function() { Ext.destroy(this.target); } }); Ext.define('Ext.fx.target.Element', { extend: Ext.fx.target.Target , type: 'element', getElVal: function(el, attr, val) { if (val == undefined) { if (attr === 'x') { val = el.getX(); } else if (attr === 'y') { val = el.getY(); } else if (attr === 'scrollTop') { val = el.getScroll().top; } else if (attr === 'scrollLeft') { val = el.getScroll().left; } else if (attr === 'height') { val = el.getHeight(); } else if (attr === 'width') { val = el.getWidth(); } else { val = el.getStyle(attr); } } return val; }, getAttr: function(attr, val) { var el = this.target; return [[ el, this.getElVal(el, attr, val)]]; }, setAttr: function(targetData) { var target = this.target, ln = targetData.length, attrs, attr, o, i, j, ln2; for (i = 0; i < ln; i++) { attrs = targetData[i].attrs; for (attr in attrs) { if (attrs.hasOwnProperty(attr)) { ln2 = attrs[attr].length; for (j = 0; j < ln2; j++) { o = attrs[attr][j]; this.setElVal(o[0], attr, o[1]); } } } } }, setElVal: function(element, attr, value){ if (attr === 'x') { element.setX(value); } else if (attr === 'y') { element.setY(value); } else if (attr === 'scrollTop') { element.scrollTo('top', value); } else if (attr === 'scrollLeft') { element.scrollTo('left',value); } else if (attr === 'width') { element.setWidth(value); } else if (attr === 'height') { element.setHeight(value); } else { element.setStyle(attr, value); } } }); Ext.define('Ext.fx.target.ElementCSS', { extend: Ext.fx.target.Element , setAttr: function(targetData, isFirstFrame) { var cssArr = { attrs: [], duration: [], easing: [] }, ln = targetData.length, attributes, attrs, attr, easing, duration, o, i, j, ln2; for (i = 0; i < ln; i++) { attrs = targetData[i]; duration = attrs.duration; easing = attrs.easing; attrs = attrs.attrs; for (attr in attrs) { if (Ext.Array.indexOf(cssArr.attrs, attr) == -1) { cssArr.attrs.push(attr.replace(/[A-Z]/g, function(v) { return '-' + v.toLowerCase(); })); cssArr.duration.push(duration + 'ms'); cssArr.easing.push(easing); } } } attributes = cssArr.attrs.join(','); duration = cssArr.duration.join(','); easing = cssArr.easing.join(', '); for (i = 0; i < ln; i++) { attrs = targetData[i].attrs; for (attr in attrs) { ln2 = attrs[attr].length; for (j = 0; j < ln2; j++) { o = attrs[attr][j]; o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', isFirstFrame ? '' : attributes); o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', isFirstFrame ? '' : duration); o[0].setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', isFirstFrame ? '' : easing); o[0].setStyle(attr, o[1]); if (isFirstFrame) { o = o[0].dom.offsetWidth; } else { o[0].on(Ext.supports.CSS3TransitionEnd, function() { this.setStyle(Ext.supports.CSS3Prefix + 'TransitionProperty', null); this.setStyle(Ext.supports.CSS3Prefix + 'TransitionDuration', null); this.setStyle(Ext.supports.CSS3Prefix + 'TransitionTimingFunction', null); }, o[0], { single: true }); } } } } } }); Ext.define('Ext.fx.target.CompositeElement', { extend: Ext.fx.target.Element , isComposite: true, constructor: function(target) { target.id = target.id || Ext.id(null, 'ext-composite-'); this.callParent([target]); }, getAttr: function(attr, val) { var out = [], target = this.target, elements = target.elements, length = elements.length, i, el; for (i = 0; i < length; i++) { el = elements[i]; if (el) { el = target.getElement(el); out.push([el, this.getElVal(el, attr, val)]); } } return out; }, setAttr: function(targetData){ var target = this.target, ln = targetData.length, elements = target.elements, ln3 = elements.length, value, k, attrs, attr, o, i, j, ln2; for (i = 0; i < ln; i++) { attrs = targetData[i].attrs; for (attr in attrs) { if (attrs.hasOwnProperty(attr)) { ln2 = attrs[attr].length; for (j = 0; j < ln2; j++) { value = attrs[attr][j][1]; for (k = 0; k < ln3; ++k) { el = elements[k]; if (el) { el = target.getElement(el); this.setElVal(el, attr, value); } } } } } } }, remove: function() { this.target.remove(); } }); Ext.define('Ext.fx.target.CompositeElementCSS', { extend: Ext.fx.target.CompositeElement , setAttr: function() { return Ext.fx.target.ElementCSS.prototype.setAttr.apply(this, arguments); } }); Ext.define('Ext.fx.target.Sprite', { extend: Ext.fx.target.Target , type: 'draw', getFromPrim: function (sprite, attr) { var obj; switch (attr) { case 'rotate': case 'rotation': obj = sprite.attr.rotation; return { x: obj.x || 0, y: obj.y || 0, degrees: obj.degrees || 0 }; case 'scale': case 'scaling': obj = sprite.attr.scaling; return { x: obj.x || 1, y: obj.y || 1, cx: obj.cx || 0, cy: obj.cy || 0 }; case 'translate': case 'translation': obj = sprite.attr.translation; return { x: obj.x || 0, y: obj.y || 0 }; default: return sprite.attr[attr]; } }, getAttr: function (attr, val) { return [ [this.target, val != undefined ? val : this.getFromPrim(this.target, attr)] ]; }, setAttr: function (targetData) { var ln = targetData.length, spriteArr = [], attrsConf, attr, attrArr, attrs, sprite, idx, value, i, j, x, y, ln2; for (i = 0; i < ln; i++) { attrsConf = targetData[i].attrs; for (attr in attrsConf) { attrArr = attrsConf[attr]; ln2 = attrArr.length; for (j = 0; j < ln2; j++) { sprite = attrArr[j][0]; attrs = attrArr[j][1]; if (attr === 'translate' || attr === 'translation') { value = { x: attrs.x, y: attrs.y }; } else if (attr === 'rotate' || attr === 'rotation') { x = attrs.x; if (isNaN(x)) { x = null; } y = attrs.y; if (isNaN(y)) { y = null; } value = { degrees: attrs.degrees, x: x, y: y }; } else if (attr === 'scale' || attr === 'scaling') { x = attrs.x; if (isNaN(x)) { x = null; } y = attrs.y; if (isNaN(y)) { y = null; } value = { x: x, y: y, cx: attrs.cx, cy: attrs.cy }; } else if (attr === 'width' || attr === 'height' || attr === 'x' || attr === 'y') { value = parseFloat(attrs); } else { value = attrs; } idx = Ext.Array.indexOf(spriteArr, sprite); if (idx == -1) { spriteArr.push([sprite, {}]); idx = spriteArr.length - 1; } spriteArr[idx][1][attr] = value; } } } ln = spriteArr.length; for (i = 0; i < ln; i++) { spriteArr[i][0].setAttributes(spriteArr[i][1]); } this.target.redraw(); } }); Ext.define('Ext.fx.target.CompositeSprite', { extend: Ext.fx.target.Sprite , getAttr: function(attr, val) { var out = [], sprites = [].concat(this.target.items), length = sprites.length, i, sprite; for (i = 0; i < length; i++) { sprite = sprites[i]; out.push([sprite, val != undefined ? val : this.getFromPrim(sprite, attr)]); } return out; } }); Ext.define('Ext.fx.target.Component', { extend: Ext.fx.target.Target , type: 'component', getPropMethod: { top: function() { return this.getPosition(true)[1]; }, left: function() { return this.getPosition(true)[0]; }, x: function() { return this.getPosition()[0]; }, y: function() { return this.getPosition()[1]; }, height: function() { return this.getHeight(); }, width: function() { return this.getWidth(); }, opacity: function() { return this.el.getStyle('opacity'); } }, setMethods: { top: 'setPosition', left: 'setPosition', x: 'setPagePosition', y: 'setPagePosition', height: 'setSize', width: 'setSize', opacity: 'setOpacity' }, getAttr: function(attr, val) { return [[this.target, val !== undefined ? val : this.getPropMethod[attr].call(this.target)]]; }, setAttr: function(targetData, isFirstFrame, isLastFrame) { var me = this, ln = targetData.length, attrs, attr, o, i, j, targets, left, top, w, h, methodsToCall = {}, methodProps; for (i = 0; i < ln; i++) { attrs = targetData[i].attrs; for (attr in attrs) { targets = attrs[attr].length; for (j = 0; j < targets; j++) { o = attrs[attr][j]; methodProps = methodsToCall[me.setMethods[attr]] || (methodsToCall[me.setMethods[attr]] = {}); methodProps.target = o[0]; methodProps[attr] = o[1]; } } if (methodsToCall.setPosition) { o = methodsToCall.setPosition; left = (o.left === undefined) ? undefined : parseFloat(o.left); top = (o.top === undefined) ? undefined : parseFloat(o.top); o.target.setPosition(left, top); } if (methodsToCall.setPagePosition) { o = methodsToCall.setPagePosition; o.target.setPagePosition(o.x, o.y); } if (methodsToCall.setSize) { o = methodsToCall.setSize; w = (o.width === undefined) ? o.target.getWidth() : parseFloat(o.width); h = (o.height === undefined) ? o.target.getHeight() : parseFloat(o.height); o.target.el.setSize(w, h); if (isLastFrame || me.dynamic) { Ext.globalEvents.on({ idle: Ext.Function.bind(o.target.setSize, o.target, [w, h]), single: true }); } } if (methodsToCall.setOpacity) { o = methodsToCall.setOpacity; o.target.el.setStyle('opacity', o.opacity); } } } }); Ext.define('Ext.fx.Queue', { constructor: function() { this.targets = new Ext.util.HashMap(); this.fxQueue = {}; }, getFxDefaults: function(targetId) { var target = this.targets.get(targetId); if (target) { return target.fxDefaults; } return {}; }, setFxDefaults: function(targetId, obj) { var target = this.targets.get(targetId); if (target) { target.fxDefaults = Ext.apply(target.fxDefaults || {}, obj); } }, stopAnimation: function(targetId) { var me = this, queue = me.getFxQueue(targetId), ln = queue.length; while (ln) { queue[ln - 1].end(); ln--; } }, getActiveAnimation: function(targetId) { var queue = this.getFxQueue(targetId); return (queue && !!queue.length) ? queue[0] : false; }, hasFxBlock: function(targetId) { var queue = this.getFxQueue(targetId); return queue && queue[0] && queue[0].block; }, getFxQueue: function(targetId) { if (!targetId) { return false; } var me = this, queue = me.fxQueue[targetId], target = me.targets.get(targetId); if (!target) { return false; } if (!queue) { me.fxQueue[targetId] = []; if (target.type != 'element') { target.target.on('destroy', function() { me.fxQueue[targetId] = []; }); } } return me.fxQueue[targetId]; }, queueFx: function(anim) { var me = this, target = anim.target, queue, ln; if (!target) { return; } queue = me.getFxQueue(target.getId()); ln = queue.length; if (ln) { if (anim.concurrent) { anim.paused = false; } else { queue[ln - 1].on('afteranimate', function() { anim.paused = false; }); } } else { anim.paused = false; } anim.on('afteranimate', function() { Ext.Array.remove(queue, anim); if (queue.length === 0) { me.targets.remove(anim.target); } if (anim.remove) { if (target.type == 'element') { var el = Ext.get(target.id); if (el) { el.remove(); } } } }, me, { single: true }); queue.push(anim); } }); Ext.define('Ext.fx.Manager', { singleton: true, mixins: { queue: Ext.fx.Queue }, constructor: function() { var me = this; me.items = new Ext.util.MixedCollection(); me.targetArr = {}; me.mixins.queue.constructor.call(me); me.taskRunner = new Ext.util.TaskRunner(); }, interval: 16, forceJS: true, createTarget: function(target) { var me = this, useCSS3 = !me.forceJS && Ext.supports.Transitions, targetObj; me.useCSS3 = useCSS3; if (target) { if (target.tagName || Ext.isString(target) || target.isFly) { target = Ext.get(target); targetObj = new Ext.fx.target['Element' + (useCSS3 ? 'CSS' : '')](target); } else if (target.dom) { targetObj = new Ext.fx.target['Element' + (useCSS3 ? 'CSS' : '')](target); } else if (target.isComposite) { targetObj = new Ext.fx.target['CompositeElement' + (useCSS3 ? 'CSS' : '')](target); } else if (target.isSprite) { targetObj = new Ext.fx.target.Sprite(target); } else if (target.isCompositeSprite) { targetObj = new Ext.fx.target.CompositeSprite(target); } else if (target.isComponent) { targetObj = new Ext.fx.target.Component(target); } else if (target.isAnimTarget) { return target; } else { return null; } me.targets.add(targetObj); return targetObj; } else { return null; } }, addAnim: function(anim) { var me = this, items = me.items, task = me.task; items.add(anim.id, anim); if (!task && items.length) { task = me.task = { run: me.runner, interval: me.interval, scope: me }; me.taskRunner.start(task); } }, removeAnim: function(anim) { var me = this, items = me.items, task = me.task; items.removeAtKey(anim.id); if (task && !items.length) { me.taskRunner.stop(task); delete me.task; } }, runner: function() { var me = this, items = me.items.getRange(), i = 0, len = items.length, anim; me.targetArr = {}; me.timestamp = new Date(); for (; i < len; i++) { anim = items[i]; if (anim.isReady()) { me.startAnim(anim); } } for (i = 0; i < len; i++) { anim = items[i]; if (anim.isRunning()) { me.runAnim(anim); } } me.applyPendingAttrs(); }, startAnim: function(anim) { anim.start(this.timestamp); }, runAnim: function(anim, forceEnd) { if (!anim) { return; } var me = this, useCSS3 = me.useCSS3 && anim.target.type == 'element', elapsedTime = me.timestamp - anim.startTime, lastFrame = (elapsedTime >= anim.duration), target, o; if (forceEnd) { elapsedTime = anim.duration; lastFrame = true; } target = this.collectTargetData(anim, elapsedTime, useCSS3, lastFrame); if (useCSS3) { anim.target.setAttr(target.anims[anim.id].attributes, true); me.collectTargetData(anim, anim.duration, useCSS3, lastFrame); anim.paused = true; target = anim.target.target; if (anim.target.isComposite) { target = anim.target.target.last(); } o = {}; o[Ext.supports.CSS3TransitionEnd] = anim.lastFrame; o.scope = anim; o.single = true; target.on(o); } return target; }, jumpToEnd: function(anim) { var target = this.runAnim(anim, true); this.applyAnimAttrs(target, target.anims[anim.id]); }, collectTargetData: function(anim, elapsedTime, useCSS3, isLastFrame) { var targetId = anim.target.getId(), target = this.targetArr[targetId]; if (!target) { target = this.targetArr[targetId] = { id: targetId, el: anim.target, anims: {} }; } target.anims[anim.id] = { id: anim.id, anim: anim, elapsed: elapsedTime, isLastFrame: isLastFrame, attributes: [{ duration: anim.duration, easing: (useCSS3 && anim.reverse) ? anim.easingFn.reverse().toCSS3() : anim.easing, attrs: anim.runAnim(elapsedTime) }] }; return target; }, applyAnimAttrs: function(target, animWrap) { var anim = animWrap.anim; if (animWrap.attributes && anim.isRunning()) { target.el.setAttr(animWrap.attributes, false, animWrap.isLastFrame); if (animWrap.isLastFrame) { anim.lastFrame(); } } }, applyPendingAttrs: function() { var targetArr = this.targetArr, target, targetId, animWrap, anim, animId; for (targetId in targetArr) { if (targetArr.hasOwnProperty(targetId)) { target = targetArr[targetId]; for (animId in target.anims) { if (target.anims.hasOwnProperty(animId)) { animWrap = target.anims[animId]; anim = animWrap.anim; if (animWrap.attributes && anim.isRunning()) { target.el.setAttr(animWrap.attributes, false, animWrap.isLastFrame); if (animWrap.isLastFrame) { anim.lastFrame(); } } } } } } } }); Ext.define('Ext.fx.Animator', { mixins: { observable: Ext.util.Observable }, isAnimator: true, duration: 250, delay: 0, delayStart: 0, dynamic: false, easing: 'ease', running: false, paused: false, damper: 1, iterations: 1, currentIteration: 0, keyframeStep: 0, animKeyFramesRE: /^(from|to|\d+%?)$/, constructor: function(config) { var me = this; config = Ext.apply(me, config || {}); me.config = config; me.id = Ext.id(null, 'ext-animator-'); me.addEvents( 'beforeanimate', 'keyframe', 'afteranimate' ); me.mixins.observable.constructor.call(me, config); me.timeline = []; me.createTimeline(me.keyframes); if (me.target) { me.applyAnimator(me.target); Ext.fx.Manager.addAnim(me); } }, sorter: function (a, b) { return a.pct - b.pct; }, createTimeline: function(keyframes) { var me = this, attrs = [], to = me.to || {}, duration = me.duration, prevMs, ms, i, ln, pct, attr; for (pct in keyframes) { if (keyframes.hasOwnProperty(pct) && me.animKeyFramesRE.test(pct)) { attr = {attrs: Ext.apply(keyframes[pct], to)}; if (pct == "from") { pct = 0; } else if (pct == "to") { pct = 100; } attr.pct = parseInt(pct, 10); attrs.push(attr); } } Ext.Array.sort(attrs, me.sorter); ln = attrs.length; for (i = 0; i < ln; i++) { prevMs = (attrs[i - 1]) ? duration * (attrs[i - 1].pct / 100) : 0; ms = duration * (attrs[i].pct / 100); me.timeline.push({ duration: ms - prevMs, attrs: attrs[i].attrs }); } }, applyAnimator: function(target) { var me = this, anims = [], timeline = me.timeline, ln = timeline.length, anim, easing, damper, attrs, i; if (me.fireEvent('beforeanimate', me) !== false) { for (i = 0; i < ln; i++) { anim = timeline[i]; attrs = anim.attrs; easing = attrs.easing || me.easing; damper = attrs.damper || me.damper; delete attrs.easing; delete attrs.damper; anim = new Ext.fx.Anim({ target: target, easing: easing, damper: damper, duration: anim.duration, paused: true, to: attrs }); anims.push(anim); } me.animations = anims; me.target = anim.target; for (i = 0; i < ln - 1; i++) { anim = anims[i]; anim.nextAnim = anims[i + 1]; anim.on('afteranimate', function() { this.nextAnim.paused = false; }); anim.on('afteranimate', function() { this.fireEvent('keyframe', this, ++this.keyframeStep); }, me); } anims[ln - 1].on('afteranimate', function() { this.lastFrame(); }, me); } }, start: function(startTime) { var me = this, delay = me.delay, delayStart = me.delayStart, delayDelta; if (delay) { if (!delayStart) { me.delayStart = startTime; return; } else { delayDelta = startTime - delayStart; if (delayDelta < delay) { return; } else { startTime = new Date(delayStart.getTime() + delay); } } } if (me.fireEvent('beforeanimate', me) !== false) { me.startTime = startTime; me.running = true; me.animations[me.keyframeStep].paused = false; } }, lastFrame: function() { var me = this, iter = me.iterations, iterCount = me.currentIteration; iterCount++; if (iterCount < iter) { me.startTime = new Date(); me.currentIteration = iterCount; me.keyframeStep = 0; me.applyAnimator(me.target); me.animations[me.keyframeStep].paused = false; } else { me.currentIteration = 0; me.end(); } }, end: function() { var me = this; me.fireEvent('afteranimate', me, me.startTime, new Date() - me.startTime); }, isReady: function() { return this.paused === false && this.running === false && this.iterations > 0; }, isRunning: function() { return false; } }); Ext.define('Ext.fx.CubicBezier', { singleton: true, cubicBezierAtTime: function(t, p1x, p1y, p2x, p2y, duration) { var cx = 3 * p1x, bx = 3 * (p2x - p1x) - cx, ax = 1 - cx - bx, cy = 3 * p1y, by = 3 * (p2y - p1y) - cy, ay = 1 - cy - by; function sampleCurveX(t) { return ((ax * t + bx) * t + cx) * t; } function solve(x, epsilon) { var t = solveCurveX(x, epsilon); return ((ay * t + by) * t + cy) * t; } function solveCurveX(x, epsilon) { var t0, t1, t2, x2, d2, i; for (t2 = x, i = 0; i < 8; i++) { x2 = sampleCurveX(t2) - x; if (Math.abs(x2) < epsilon) { return t2; } d2 = (3 * ax * t2 + 2 * bx) * t2 + cx; if (Math.abs(d2) < 1e-6) { break; } t2 = t2 - x2 / d2; } t0 = 0; t1 = 1; t2 = x; if (t2 < t0) { return t0; } if (t2 > t1) { return t1; } while (t0 < t1) { x2 = sampleCurveX(t2); if (Math.abs(x2 - x) < epsilon) { return t2; } if (x > x2) { t0 = t2; } else { t1 = t2; } t2 = (t1 - t0) / 2 + t0; } return t2; } return solve(t, 1 / (200 * duration)); }, cubicBezier: function(x1, y1, x2, y2) { var fn = function(pos) { return Ext.fx.CubicBezier.cubicBezierAtTime(pos, x1, y1, x2, y2, 1); }; fn.toCSS3 = function() { return 'cubic-bezier(' + [x1, y1, x2, y2].join(',') + ')'; }; fn.reverse = function() { return Ext.fx.CubicBezier.cubicBezier(1 - x2, 1 - y2, 1 - x1, 1 - y1); }; return fn; } }); Ext.require('Ext.fx.CubicBezier', function() { var math = Math, pi = math.PI, pow = math.pow, sin = math.sin, sqrt = math.sqrt, abs = math.abs, backInSeed = 1.70158; Ext.define('Ext.fx.Easing', { singleton: true, linear: Ext.identityFn, ease: function(n) { var q = 0.07813 - n / 2, alpha = -0.25, Q = sqrt(0.0066 + q * q), x = Q - q, X = pow(abs(x), 1/3) * (x < 0 ? -1 : 1), y = -Q - q, Y = pow(abs(y), 1/3) * (y < 0 ? -1 : 1), t = X + Y + 0.25; return pow(1 - t, 2) * 3 * t * 0.1 + (1 - t) * 3 * t * t + t * t * t; }, easeIn: function (n) { return pow(n, 1.7); }, easeOut: function (n) { return pow(n, 0.48); }, easeInOut: function(n) { var q = 0.48 - n / 1.04, Q = sqrt(0.1734 + q * q), x = Q - q, X = pow(abs(x), 1/3) * (x < 0 ? -1 : 1), y = -Q - q, Y = pow(abs(y), 1/3) * (y < 0 ? -1 : 1), t = X + Y + 0.5; return (1 - t) * 3 * t * t + t * t * t; }, backIn: function (n) { return n * n * ((backInSeed + 1) * n - backInSeed); }, backOut: function (n) { n = n - 1; return n * n * ((backInSeed + 1) * n + backInSeed) + 1; }, elasticIn: function (n) { if (n === 0 || n === 1) { return n; } var p = 0.3, s = p / 4; return pow(2, -10 * n) * sin((n - s) * (2 * pi) / p) + 1; }, elasticOut: function (n) { return 1 - Ext.fx.Easing.elasticIn(1 - n); }, bounceIn: function (n) { return 1 - Ext.fx.Easing.bounceOut(1 - n); }, bounceOut: function (n) { var s = 7.5625, p = 2.75, l; if (n < (1 / p)) { l = s * n * n; } else { if (n < (2 / p)) { n -= (1.5 / p); l = s * n * n + 0.75; } else { if (n < (2.5 / p)) { n -= (2.25 / p); l = s * n * n + 0.9375; } else { n -= (2.625 / p); l = s * n * n + 0.984375; } } } return l; } }, function(){ var easing = Ext.fx.Easing.self, proto = easing.prototype; easing.implement({ 'back-in': proto.backIn, 'back-out': proto.backOut, 'ease-in': proto.easeIn, 'ease-out': proto.easeOut, 'elastic-in': proto.elasticIn, 'elastic-out': proto.elasticOut, 'bounce-in': proto.bounceIn, 'bounce-out': proto.bounceOut, 'ease-in-out': proto.easeInOut }); }); }); Ext.define('Ext.draw.Color', { colorToHexRe: /(.*?)rgb\((\d+),\s*(\d+),\s*(\d+)\)/, rgbRe: /\s*rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)\s*/, hexRe: /\s*#([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)([0-9a-fA-F][0-9a-fA-F]?)\s*/, lightnessFactor: 0.2, constructor : function(red, green, blue) { var me = this, clamp = Ext.Number.constrain; me.r = clamp(red, 0, 255); me.g = clamp(green, 0, 255); me.b = clamp(blue, 0, 255); }, getRed: function() { return this.r; }, getGreen: function() { return this.g; }, getBlue: function() { return this.b; }, getRGB: function() { var me = this; return [me.r, me.g, me.b]; }, getHSL: function() { var me = this, r = me.r / 255, g = me.g / 255, b = me.b / 255, max = Math.max(r, g, b), min = Math.min(r, g, b), delta = max - min, h, s = 0, l = 0.5 * (max + min); if (min != max) { s = (l < 0.5) ? delta / (max + min) : delta / (2 - max - min); if (r == max) { h = 60 * (g - b) / delta; } else if (g == max) { h = 120 + 60 * (b - r) / delta; } else { h = 240 + 60 * (r - g) / delta; } if (h < 0) { h += 360; } if (h >= 360) { h -= 360; } } return [h, s, l]; }, getLighter: function(factor) { var hsl = this.getHSL(); factor = factor || this.lightnessFactor; hsl[2] = Ext.Number.constrain(hsl[2] + factor, 0, 1); return this.fromHSL(hsl[0], hsl[1], hsl[2]); }, getDarker: function(factor) { factor = factor || this.lightnessFactor; return this.getLighter(-factor); }, toString: function() { var me = this, round = Math.round, r = round(me.r).toString(16), g = round(me.g).toString(16), b = round(me.b).toString(16); r = (r.length == 1) ? '0' + r : r; g = (g.length == 1) ? '0' + g : g; b = (b.length == 1) ? '0' + b : b; return ['#', r, g, b].join(''); }, toHex: function(color) { if (Ext.isArray(color)) { color = color[0]; } if (!Ext.isString(color)) { return ''; } if (color.substr(0, 1) === '#') { return color; } var digits = this.colorToHexRe.exec(color), red, green, blue, rgb; if (Ext.isArray(digits)) { red = parseInt(digits[2], 10); green = parseInt(digits[3], 10); blue = parseInt(digits[4], 10); rgb = blue | (green << 8) | (red << 16); return digits[1] + '#' + ("000000" + rgb.toString(16)).slice(-6); } else { return color; } }, fromString: function(str) { var values, r, g, b, parse = parseInt, firstChar = str.substr(0, 1), colorValue; if (firstChar != '#') { colorValue = Ext.draw.Color.cssColors[str]; if (colorValue) { str = colorValue; firstChar = str.substr(0, 1); } } if ((str.length == 4 || str.length == 7) && firstChar === '#') { values = str.match(this.hexRe); if (values) { r = parse(values[1], 16) >> 0; g = parse(values[2], 16) >> 0; b = parse(values[3], 16) >> 0; if (str.length == 4) { r += (r * 16); g += (g * 16); b += (b * 16); } } } else { values = str.match(this.rgbRe); if (values) { r = values[1]; g = values[2]; b = values[3]; } } return (typeof r == 'undefined') ? undefined : new Ext.draw.Color(r, g, b); }, getGrayscale: function() { return this.r * 0.3 + this.g * 0.59 + this.b * 0.11; }, fromHSL: function(h, s, l) { var C, X, m, i, rgb = [], abs = Math.abs, floor = Math.floor; if (s == 0 || h == null) { rgb = [l, l, l]; } else { h /= 60; C = s * (1 - abs(2 * l - 1)); X = C * (1 - abs(h - 2 * floor(h / 2) - 1)); m = l - C / 2; switch (floor(h)) { case 0: rgb = [C, X, 0]; break; case 1: rgb = [X, C, 0]; break; case 2: rgb = [0, C, X]; break; case 3: rgb = [0, X, C]; break; case 4: rgb = [X, 0, C]; break; case 5: rgb = [C, 0, X]; break; } rgb = [rgb[0] + m, rgb[1] + m, rgb[2] + m]; } return new Ext.draw.Color(rgb[0] * 255, rgb[1] * 255, rgb[2] * 255); } }, function() { var prototype = this.prototype; this.addStatics({ fromHSL: function() { return prototype.fromHSL.apply(prototype, arguments); }, fromString: function() { return prototype.fromString.apply(prototype, arguments); }, toHex: function() { return prototype.toHex.apply(prototype, arguments); }, cssColors: { aliceblue: '#F0F8FF', antiquewhite: '#FAEBD7', aqua: '#00FFFF', aquamarine: '#7FFFD4', azure: '#F0FFFF', beige: '#F5F5DC', bisque: '#FFE4C4', black: '#000000', blanchedalmond: '#FFEBCD', blue: '#0000FF', blueviolet: '#8A2BE2', brown: '#A52A2A', burlywood: '#DEB887', cadetblue: '#5F9EA0', chartreuse: '#7FFF00', chocolate: '#D2691E', coral: '#FF7F50', cornflowerblue: '#6495ED', cornsilk: '#FFF8DC', crimson: '#DC143C', cyan: '#00FFFF', darkblue: '#00008B', darkcyan: '#008B8B', darkgoldenrod: '#B8860B', darkgray: '#A9A9A9', darkgreen: '#006400', darkgrey: '#A9A9A9', darkkhaki: '#BDB76B', darkmagenta: '#8B008B', darkolivegreen: '#556B2F', darkorange: '#FF8C00', darkorchid: '#9932CC', darkred: '#8B0000', darksalmon: '#E9967A', darkseagreen: '#8FBC8F', darkslateblue: '#483D8B', darkslategray: '#2F4F4F', darkslategrey: '#2F4F4F', darkturquoise: '#00CED1', darkviolet: '#9400D3', deeppink: '#FF1493', deepskyblue: '#00BFFF', dimgray: '#696969', dimgrey: '#696969', dodgerblue: '#1E90FF', firebrick: '#B22222', floralwhite: '#FFFAF0', forestgreen: '#228B22', fuchsia: '#FF00FF', gainsboro: '#DCDCDC', ghostwhite: '#F8F8FF', gold: '#FFD700', goldenrod: '#DAA520', gray: '#808080', grey: '#808080', green: '#008000', greenyellow: '#ADFF2F', honeydew: '#F0FFF0', hotpink: '#FF69B4', indianred: '#CD5C5C', indigo: '#4B0082', ivory: '#FFFFF0', khaki: '#F0E68C', lavender: '#E6E6FA', lavenderblush: '#FFF0F5', lawngreen: '#7CFC00', lemonchiffon: '#FFFACD', lightblue: '#ADD8E6', lightcoral: '#F08080', lightcyan: '#E0FFFF', lightgoldenrodyellow: '#FAFAD2', lightgray: '#D3D3D3', lightgreen: '#90EE90', lightgrey: '#D3D3D3', lightpink: '#FFB6C1', lightsalmon: '#FFA07A', lightseagreen: '#20B2AA', lightskyblue: '#87CEFA', lightslategray: '#778899', lightslategrey: '#778899', lightsteelblue: '#B0C4DE', lightyellow: '#FFFFE0', lime: '#00FF00', limegreen: '#32CD32', linen: '#FAF0E6', magenta: '#FF00FF', maroon: '#800000', mediumaquamarine: '#66CDAA', mediumblue: '#0000CD', mediumorchid: '#BA55D3', mediumpurple: '#9370DB', mediumseagreen: '#3CB371', mediumslateblue: '#7B68EE', mediumspringgreen: '#00FA9A', mediumturquoise: '#48D1CC', mediumvioletred: '#C71585', midnightblue: '#191970', mintcream: '#F5FFFA', mistyrose: '#FFE4E1', moccasin: '#FFE4B5', navajowhite: '#FFDEAD', navy: '#000080', oldlace: '#FDF5E6', olive: '#808000', olivedrab: '#6B8E23', orange: '#FFA500', orangered: '#FF4500', orchid: '#DA70D6', palegoldenrod: '#EEE8AA', palegreen: '#98FB98', paleturquoise: '#AFEEEE', palevioletred: '#DB7093', papayawhip: '#FFEFD5', peachpuff: '#FFDAB9', peru: '#CD853F', pink: '#FFC0CB', plum: '#DDA0DD', powderblue: '#B0E0E6', purple: '#800080', red: '#FF0000', rosybrown: '#BC8F8F', royalblue: '#4169E1', saddlebrown: '#8B4513', salmon: '#FA8072', sandybrown: '#F4A460', seagreen: '#2E8B57', seashell: '#FFF5EE', sienna: '#A0522D', silver: '#C0C0C0', skyblue: '#87CEEB', slateblue: '#6A5ACD', slategray: '#708090', slategrey: '#708090', snow: '#FFFAFA', springgreen: '#00FF7F', steelblue: '#4682B4', tan: '#D2B48C', teal: '#008080', thistle: '#D8BFD8', tomato: '#FF6347', turquoise: '#40E0D0', violet: '#EE82EE', wheat: '#F5DEB3', white: '#FFFFFF', whitesmoke: '#F5F5F5', yellow: '#FFFF00', yellowgreen: '#9ACD32' } }); }); Ext.define('Ext.draw.Draw', { singleton: true, pathToStringRE: /,?([achlmqrstvxz]),?/gi, pathCommandRE: /([achlmqstvz])[\s,]*((-?\d*\.?\d*(?:e[-+]?\d+)?\s*,?\s*)+)/ig, pathValuesRE: /(-?\d*\.?\d*(?:e[-+]?\d+)?)\s*,?\s*/ig, stopsRE: /^(\d+%?)$/, radian: Math.PI / 180, availableAnimAttrs: { along: "along", blur: null, "clip-rect": "csv", cx: null, cy: null, fill: "color", "fill-opacity": null, "font-size": null, height: null, opacity: null, path: "path", r: null, rotation: "csv", rx: null, ry: null, scale: "csv", stroke: "color", "stroke-opacity": null, "stroke-width": null, translation: "csv", width: null, x: null, y: null }, is: function(o, type) { type = String(type).toLowerCase(); return (type == "object" && o === Object(o)) || (type == "undefined" && typeof o == type) || (type == "null" && o === null) || (type == "array" && Array.isArray && Array.isArray(o)) || (Object.prototype.toString.call(o).toLowerCase().slice(8, -1)) == type; }, ellipsePath: function(sprite) { var attr = sprite.attr; return Ext.String.format("M{0},{1}A{2},{3},0,1,1,{0},{4}A{2},{3},0,1,1,{0},{1}z", attr.x, attr.y - attr.ry, attr.rx, attr.ry, attr.y + attr.ry); }, rectPath: function(sprite) { var attr = sprite.attr; if (attr.radius) { return Ext.String.format("M{0},{1}l{2},0a{3},{3},0,0,1,{3},{3}l0,{5}a{3},{3},0,0,1,{4},{3}l{6},0a{3},{3},0,0,1,{4},{4}l0,{7}a{3},{3},0,0,1,{3},{4}z", attr.x + attr.radius, attr.y, attr.width - attr.radius * 2, attr.radius, -attr.radius, attr.height - attr.radius * 2, attr.radius * 2 - attr.width, attr.radius * 2 - attr.height); } else { return Ext.String.format("M{0},{1}L{2},{1},{2},{3},{0},{3}z", attr.x, attr.y, attr.width + attr.x, attr.height + attr.y); } }, path2string: function () { return this.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1"); }, pathToString: function(arrayPath) { return arrayPath.join(",").replace(Ext.draw.Draw.pathToStringRE, "$1"); }, parsePathString: function (pathString) { if (!pathString) { return null; } var paramCounts = {a: 7, c: 6, h: 1, l: 2, m: 2, q: 4, s: 4, t: 2, v: 1, z: 0}, data = [], me = this; if (me.is(pathString, "array") && me.is(pathString[0], "array")) { data = me.pathClone(pathString); } if (!data.length) { String(pathString).replace(me.pathCommandRE, function (a, b, c) { var params = [], name = b.toLowerCase(); c.replace(me.pathValuesRE, function (a, b) { b && params.push(+b); }); if (name == "m" && params.length > 2) { data.push([b].concat(Ext.Array.splice(params, 0, 2))); name = "l"; b = (b == "m") ? "l" : "L"; } while (params.length >= paramCounts[name]) { data.push([b].concat(Ext.Array.splice(params, 0, paramCounts[name]))); if (!paramCounts[name]) { break; } } }); } data.toString = me.path2string; return data; }, mapPath: function (path, matrix) { if (!matrix) { return path; } var x, y, i, ii, j, jj, pathi; path = this.path2curve(path); for (i = 0, ii = path.length; i < ii; i++) { pathi = path[i]; for (j = 1, jj = pathi.length; j < jj-1; j += 2) { x = matrix.x(pathi[j], pathi[j + 1]); y = matrix.y(pathi[j], pathi[j + 1]); pathi[j] = x; pathi[j + 1] = y; } } return path; }, pathClone: function(pathArray) { var res = [], j, jj, i, ii; if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { pathArray = this.parsePathString(pathArray); } for (i = 0, ii = pathArray.length; i < ii; i++) { res[i] = []; for (j = 0, jj = pathArray[i].length; j < jj; j++) { res[i][j] = pathArray[i][j]; } } res.toString = this.path2string; return res; }, pathToAbsolute: function (pathArray) { if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { pathArray = this.parsePathString(pathArray); } var res = [], x = 0, y = 0, mx = 0, my = 0, i = 0, ln = pathArray.length, r, pathSegment, j, ln2; if (ln && pathArray[0][0] == "M") { x = +pathArray[0][1]; y = +pathArray[0][2]; mx = x; my = y; i++; res[0] = ["M", x, y]; } for (; i < ln; i++) { r = res[i] = []; pathSegment = pathArray[i]; if (pathSegment[0] != pathSegment[0].toUpperCase()) { r[0] = pathSegment[0].toUpperCase(); switch (r[0]) { case "A": r[1] = pathSegment[1]; r[2] = pathSegment[2]; r[3] = pathSegment[3]; r[4] = pathSegment[4]; r[5] = pathSegment[5]; r[6] = +(pathSegment[6] + x); r[7] = +(pathSegment[7] + y); break; case "V": r[1] = +pathSegment[1] + y; break; case "H": r[1] = +pathSegment[1] + x; break; case "M": mx = +pathSegment[1] + x; my = +pathSegment[2] + y; default: j = 1; ln2 = pathSegment.length; for (; j < ln2; j++) { r[j] = +pathSegment[j] + ((j % 2) ? x : y); } } } else { j = 0; ln2 = pathSegment.length; for (; j < ln2; j++) { res[i][j] = pathSegment[j]; } } switch (r[0]) { case "Z": x = mx; y = my; break; case "H": x = r[1]; break; case "V": y = r[1]; break; case "M": pathSegment = res[i]; ln2 = pathSegment.length; mx = pathSegment[ln2 - 2]; my = pathSegment[ln2 - 1]; default: pathSegment = res[i]; ln2 = pathSegment.length; x = pathSegment[ln2 - 2]; y = pathSegment[ln2 - 1]; } } res.toString = this.path2string; return res; }, pathToRelative: function (pathArray) { if (!this.is(pathArray, "array") || !this.is(pathArray && pathArray[0], "array")) { pathArray = this.parsePathString(pathArray); } var res = [], x = 0, y = 0, mx = 0, my = 0, start = 0, r, pa, i, j, k, len, ii, jj, kk; if (pathArray[0][0] == "M") { x = pathArray[0][1]; y = pathArray[0][2]; mx = x; my = y; start++; res.push(["M", x, y]); } for (i = start, ii = pathArray.length; i < ii; i++) { r = res[i] = []; pa = pathArray[i]; if (pa[0] != pa[0].toLowerCase()) { r[0] = pa[0].toLowerCase(); switch (r[0]) { case "a": r[1] = pa[1]; r[2] = pa[2]; r[3] = pa[3]; r[4] = pa[4]; r[5] = pa[5]; r[6] = +(pa[6] - x).toFixed(3); r[7] = +(pa[7] - y).toFixed(3); break; case "v": r[1] = +(pa[1] - y).toFixed(3); break; case "m": mx = pa[1]; my = pa[2]; default: for (j = 1, jj = pa.length; j < jj; j++) { r[j] = +(pa[j] - ((j % 2) ? x : y)).toFixed(3); } } } else { r = res[i] = []; if (pa[0] == "m") { mx = pa[1] + x; my = pa[2] + y; } for (k = 0, kk = pa.length; k < kk; k++) { res[i][k] = pa[k]; } } len = res[i].length; switch (res[i][0]) { case "z": x = mx; y = my; break; case "h": x += +res[i][len - 1]; break; case "v": y += +res[i][len - 1]; break; default: x += +res[i][len - 2]; y += +res[i][len - 1]; } } res.toString = this.path2string; return res; }, path2curve: function (path) { var me = this, points = me.pathToAbsolute(path), ln = points.length, attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, i, seg, segLn, point; for (i = 0; i < ln; i++) { points[i] = me.command2curve(points[i], attrs); if (points[i].length > 7) { points[i].shift(); point = points[i]; while (point.length) { Ext.Array.splice(points, i++, 0, ["C"].concat(Ext.Array.splice(point, 0, 6))); } Ext.Array.erase(points, i, 1); ln = points.length; i--; } seg = points[i]; segLn = seg.length; attrs.x = seg[segLn - 2]; attrs.y = seg[segLn - 1]; attrs.bx = parseFloat(seg[segLn - 4]) || attrs.x; attrs.by = parseFloat(seg[segLn - 3]) || attrs.y; } return points; }, interpolatePaths: function (path, path2) { var me = this, p = me.pathToAbsolute(path), p2 = me.pathToAbsolute(path2), attrs = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, attrs2 = {x: 0, y: 0, bx: 0, by: 0, X: 0, Y: 0, qx: null, qy: null}, fixArc = function (pp, i) { if (pp[i].length > 7) { pp[i].shift(); var pi = pp[i]; while (pi.length) { Ext.Array.splice(pp, i++, 0, ["C"].concat(Ext.Array.splice(pi, 0, 6))); } Ext.Array.erase(pp, i, 1); ii = Math.max(p.length, p2.length || 0); } }, fixM = function (path1, path2, a1, a2, i) { if (path1 && path2 && path1[i][0] == "M" && path2[i][0] != "M") { Ext.Array.splice(path2, i, 0, ["M", a2.x, a2.y]); a1.bx = 0; a1.by = 0; a1.x = path1[i][1]; a1.y = path1[i][2]; ii = Math.max(p.length, p2.length || 0); } }, i, ii, seg, seg2, seglen, seg2len; for (i = 0, ii = Math.max(p.length, p2.length || 0); i < ii; i++) { p[i] = me.command2curve(p[i], attrs); fixArc(p, i); (p2[i] = me.command2curve(p2[i], attrs2)); fixArc(p2, i); fixM(p, p2, attrs, attrs2, i); fixM(p2, p, attrs2, attrs, i); seg = p[i]; seg2 = p2[i]; seglen = seg.length; seg2len = seg2.length; attrs.x = seg[seglen - 2]; attrs.y = seg[seglen - 1]; attrs.bx = parseFloat(seg[seglen - 4]) || attrs.x; attrs.by = parseFloat(seg[seglen - 3]) || attrs.y; attrs2.bx = (parseFloat(seg2[seg2len - 4]) || attrs2.x); attrs2.by = (parseFloat(seg2[seg2len - 3]) || attrs2.y); attrs2.x = seg2[seg2len - 2]; attrs2.y = seg2[seg2len - 1]; } return [p, p2]; }, command2curve: function (pathCommand, d) { var me = this; if (!pathCommand) { return ["C", d.x, d.y, d.x, d.y, d.x, d.y]; } if (pathCommand[0] != "T" && pathCommand[0] != "Q") { d.qx = d.qy = null; } switch (pathCommand[0]) { case "M": d.X = pathCommand[1]; d.Y = pathCommand[2]; break; case "A": pathCommand = ["C"].concat(me.arc2curve.apply(me, [d.x, d.y].concat(pathCommand.slice(1)))); break; case "S": pathCommand = ["C", d.x + (d.x - (d.bx || d.x)), d.y + (d.y - (d.by || d.y))].concat(pathCommand.slice(1)); break; case "T": d.qx = d.x + (d.x - (d.qx || d.x)); d.qy = d.y + (d.y - (d.qy || d.y)); pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, d.qx, d.qy, pathCommand[1], pathCommand[2])); break; case "Q": d.qx = pathCommand[1]; d.qy = pathCommand[2]; pathCommand = ["C"].concat(me.quadratic2curve(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[3], pathCommand[4])); break; case "L": pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], pathCommand[2], pathCommand[1], pathCommand[2]); break; case "H": pathCommand = ["C"].concat(d.x, d.y, pathCommand[1], d.y, pathCommand[1], d.y); break; case "V": pathCommand = ["C"].concat(d.x, d.y, d.x, pathCommand[1], d.x, pathCommand[1]); break; case "Z": pathCommand = ["C"].concat(d.x, d.y, d.X, d.Y, d.X, d.Y); break; } return pathCommand; }, quadratic2curve: function (x1, y1, ax, ay, x2, y2) { var _13 = 1 / 3, _23 = 2 / 3; return [ _13 * x1 + _23 * ax, _13 * y1 + _23 * ay, _13 * x2 + _23 * ax, _13 * y2 + _23 * ay, x2, y2 ]; }, rotate: function (x, y, rad) { var cos = Math.cos(rad), sin = Math.sin(rad), X = x * cos - y * sin, Y = x * sin + y * cos; return {x: X, y: Y}; }, arc2curve: function (x1, y1, rx, ry, angle, large_arc_flag, sweep_flag, x2, y2, recursive) { var me = this, PI = Math.PI, radian = me.radian, _120 = PI * 120 / 180, rad = radian * (+angle || 0), res = [], math = Math, mcos = math.cos, msin = math.sin, msqrt = math.sqrt, mabs = math.abs, masin = math.asin, xy, x, y, h, rx2, ry2, k, cx, cy, f1, f2, df, c1, s1, c2, s2, t, hx, hy, m1, m2, m3, m4, newres, i, ln, f2old, x2old, y2old; if (!recursive) { xy = me.rotate(x1, y1, -rad); x1 = xy.x; y1 = xy.y; xy = me.rotate(x2, y2, -rad); x2 = xy.x; y2 = xy.y; x = (x1 - x2) / 2; y = (y1 - y2) / 2; h = (x * x) / (rx * rx) + (y * y) / (ry * ry); if (h > 1) { h = msqrt(h); rx = h * rx; ry = h * ry; } rx2 = rx * rx; ry2 = ry * ry; k = (large_arc_flag == sweep_flag ? -1 : 1) * msqrt(mabs((rx2 * ry2 - rx2 * y * y - ry2 * x * x) / (rx2 * y * y + ry2 * x * x))); cx = k * rx * y / ry + (x1 + x2) / 2; cy = k * -ry * x / rx + (y1 + y2) / 2; f1 = masin(((y1 - cy) / ry).toFixed(7)); f2 = masin(((y2 - cy) / ry).toFixed(7)); f1 = x1 < cx ? PI - f1 : f1; f2 = x2 < cx ? PI - f2 : f2; if (f1 < 0) { f1 = PI * 2 + f1; } if (f2 < 0) { f2 = PI * 2 + f2; } if (sweep_flag && f1 > f2) { f1 = f1 - PI * 2; } if (!sweep_flag && f2 > f1) { f2 = f2 - PI * 2; } } else { f1 = recursive[0]; f2 = recursive[1]; cx = recursive[2]; cy = recursive[3]; } df = f2 - f1; if (mabs(df) > _120) { f2old = f2; x2old = x2; y2old = y2; f2 = f1 + _120 * (sweep_flag && f2 > f1 ? 1 : -1); x2 = cx + rx * mcos(f2); y2 = cy + ry * msin(f2); res = me.arc2curve(x2, y2, rx, ry, angle, 0, sweep_flag, x2old, y2old, [f2, f2old, cx, cy]); } df = f2 - f1; c1 = mcos(f1); s1 = msin(f1); c2 = mcos(f2); s2 = msin(f2); t = math.tan(df / 4); hx = 4 / 3 * rx * t; hy = 4 / 3 * ry * t; m1 = [x1, y1]; m2 = [x1 + hx * s1, y1 - hy * c1]; m3 = [x2 + hx * s2, y2 - hy * c2]; m4 = [x2, y2]; m2[0] = 2 * m1[0] - m2[0]; m2[1] = 2 * m1[1] - m2[1]; if (recursive) { return [m2, m3, m4].concat(res); } else { res = [m2, m3, m4].concat(res).join().split(","); newres = []; ln = res.length; for (i = 0; i < ln; i++) { newres[i] = i % 2 ? me.rotate(res[i - 1], res[i], rad).y : me.rotate(res[i], res[i + 1], rad).x; } return newres; } }, rotateAndTranslatePath: function (sprite) { var alpha = sprite.rotation.degrees, cx = sprite.rotation.x, cy = sprite.rotation.y, dx = sprite.translation.x, dy = sprite.translation.y, path, i, p, xy, j, res = []; if (!alpha && !dx && !dy) { return this.pathToAbsolute(sprite.attr.path); } dx = dx || 0; dy = dy || 0; path = this.pathToAbsolute(sprite.attr.path); for (i = path.length; i--;) { p = res[i] = path[i].slice(); if (p[0] == "A") { xy = this.rotatePoint(p[6], p[7], alpha, cx, cy); p[6] = xy.x + dx; p[7] = xy.y + dy; } else { j = 1; while (p[j + 1] != null) { xy = this.rotatePoint(p[j], p[j + 1], alpha, cx, cy); p[j] = xy.x + dx; p[j + 1] = xy.y + dy; j += 2; } } } return res; }, rotatePoint: function (x, y, alpha, cx, cy) { if (!alpha) { return { x: x, y: y }; } cx = cx || 0; cy = cy || 0; x = x - cx; y = y - cy; alpha = alpha * this.radian; var cos = Math.cos(alpha), sin = Math.sin(alpha); return { x: x * cos - y * sin + cx, y: x * sin + y * cos + cy }; }, pathDimensions: function (path) { if (!path || !(path + "")) { return {x: 0, y: 0, width: 0, height: 0}; } path = this.path2curve(path); var x = 0, y = 0, X = [], Y = [], i = 0, ln = path.length, p, xmin, ymin, xmax, ymax, dim; for (; i < ln; i++) { p = path[i]; if (p[0] == "M") { x = p[1]; y = p[2]; X.push(x); Y.push(y); } else { dim = this.curveDim(x, y, p[1], p[2], p[3], p[4], p[5], p[6]); X = X.concat(dim.min.x, dim.max.x); Y = Y.concat(dim.min.y, dim.max.y); x = p[5]; y = p[6]; } } xmin = Math.min.apply(0, X); ymin = Math.min.apply(0, Y); xmax = Math.max.apply(0, X); ymax = Math.max.apply(0, Y); return { x: Math.round(xmin), y: Math.round(ymin), path: path, width: Math.round(xmax - xmin), height: Math.round(ymax - ymin) }; }, intersectInside: function(path, cp1, cp2) { return (cp2[0] - cp1[0]) * (path[1] - cp1[1]) > (cp2[1] - cp1[1]) * (path[0] - cp1[0]); }, intersectIntersection: function(s, e, cp1, cp2) { var p = [], dcx = cp1[0] - cp2[0], dcy = cp1[1] - cp2[1], dpx = s[0] - e[0], dpy = s[1] - e[1], n1 = cp1[0] * cp2[1] - cp1[1] * cp2[0], n2 = s[0] * e[1] - s[1] * e[0], n3 = 1 / (dcx * dpy - dcy * dpx); p[0] = (n1 * dpx - n2 * dcx) * n3; p[1] = (n1 * dpy - n2 * dcy) * n3; return p; }, intersect: function(subjectPolygon, clipPolygon) { var me = this, i = 0, ln = clipPolygon.length, cp1 = clipPolygon[ln - 1], outputList = subjectPolygon, cp2, s, e, ln2, inputList, j; for (; i < ln; ++i) { cp2 = clipPolygon[i]; inputList = outputList; outputList = []; s = inputList[inputList.length - 1]; j = 0; ln2 = inputList.length; for (; j < ln2; j++) { e = inputList[j]; if (me.intersectInside(e, cp1, cp2)) { if (!me.intersectInside(s, cp1, cp2)) { outputList.push(me.intersectIntersection(s, e, cp1, cp2)); } outputList.push(e); } else if (me.intersectInside(s, cp1, cp2)) { outputList.push(me.intersectIntersection(s, e, cp1, cp2)); } s = e; } cp1 = cp2; } return outputList; }, bezier : function (a, b, c, d, x) { if (x === 0) { return a; } else if (x === 1) { return d; } var du = 1 - x, d3 = du * du * du, r = x / du; return d3 * (a + r * (3 * b + r * (3 * c + d * r))); }, bezierDim : function (a, b, c, d) { var points = [], r, A, top, C, delta, bottom, s, min, max, i; if (a + 3 * c == d + 3 * b) { r = a - b; r /= 2 * (a - b - b + c); if ( r < 1 && r > 0) { points.push(r); } } else { A = a - 3 * b + 3 * c - d; top = 2 * (a - b - b + c); C = a - b; delta = top * top - 4 * A * C; bottom = A + A; if (delta === 0) { r = top / bottom; if (r < 1 && r > 0) { points.push(r); } } else if (delta > 0) { s = Math.sqrt(delta); r = (s + top) / bottom; if (r < 1 && r > 0) { points.push(r); } r = (top - s) / bottom; if (r < 1 && r > 0) { points.push(r); } } } min = Math.min(a, d); max = Math.max(a, d); for (i = 0; i < points.length; i++) { min = Math.min(min, this.bezier(a, b, c, d, points[i])); max = Math.max(max, this.bezier(a, b, c, d, points[i])); } return [min, max]; }, curveDim: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) { var x = this.bezierDim(p1x, c1x, c2x, p2x), y = this.bezierDim(p1y, c1y, c2y, p2y); return { min: { x: x[0], y: y[0] }, max: { x: x[1], y: y[1] } }; }, getAnchors: function (prevX, prevY, curX, curY, nextX, nextY, value) { value = value || 4; var M = Math, PI = M.PI, halfPI = PI / 2, abs = M.abs, sin = M.sin, cos = M.cos, atan = M.atan, control1Length, control2Length, control1Angle, control2Angle, control1X, control1Y, control2X, control2Y, alpha; control1Length = (curX - prevX) / value; control2Length = (nextX - curX) / value; if ((curY >= prevY && curY >= nextY) || (curY <= prevY && curY <= nextY)) { control1Angle = control2Angle = halfPI; } else { control1Angle = atan((curX - prevX) / abs(curY - prevY)); if (prevY < curY) { control1Angle = PI - control1Angle; } control2Angle = atan((nextX - curX) / abs(curY - nextY)); if (nextY < curY) { control2Angle = PI - control2Angle; } } alpha = halfPI - ((control1Angle + control2Angle) % (PI * 2)) / 2; if (alpha > halfPI) { alpha -= PI; } control1Angle += alpha; control2Angle += alpha; control1X = curX - control1Length * sin(control1Angle); control1Y = curY + control1Length * cos(control1Angle); control2X = curX + control2Length * sin(control2Angle); control2Y = curY + control2Length * cos(control2Angle); if ((curY > prevY && control1Y < prevY) || (curY < prevY && control1Y > prevY)) { control1X += abs(prevY - control1Y) * (control1X - curX) / (control1Y - curY); control1Y = prevY; } if ((curY > nextY && control2Y < nextY) || (curY < nextY && control2Y > nextY)) { control2X -= abs(nextY - control2Y) * (control2X - curX) / (control2Y - curY); control2Y = nextY; } return { x1: control1X, y1: control1Y, x2: control2X, y2: control2Y }; }, smooth: function (originalPath, value) { var path = this.path2curve(originalPath), newp = [path[0]], x = path[0][1], y = path[0][2], j, points, i = 1, ii = path.length, beg = 1, mx = x, my = y, pathi, pathil, pathim, pathiml, pathip, pathipl, begl; for (; i < ii; i++) { pathi = path[i]; pathil = pathi.length; pathim = path[i - 1]; pathiml = pathim.length; pathip = path[i + 1]; pathipl = pathip && pathip.length; if (pathi[0] == "M") { mx = pathi[1]; my = pathi[2]; j = i + 1; while (path[j][0] != "C") { j++; } newp.push(["M", mx, my]); beg = newp.length; x = mx; y = my; continue; } if (pathi[pathil - 2] == mx && pathi[pathil - 1] == my && (!pathip || pathip[0] == "M")) { begl = newp[beg].length; points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], mx, my, newp[beg][begl - 2], newp[beg][begl - 1], value); newp[beg][1] = points.x2; newp[beg][2] = points.y2; } else if (!pathip || pathip[0] == "M") { points = { x1: pathi[pathil - 2], y1: pathi[pathil - 1] }; } else { points = this.getAnchors(pathim[pathiml - 2], pathim[pathiml - 1], pathi[pathil - 2], pathi[pathil - 1], pathip[pathipl - 2], pathip[pathipl - 1], value); } newp.push(["C", x, y, points.x1, points.y1, pathi[pathil - 2], pathi[pathil - 1]]); x = points.x2; y = points.y2; } return newp; }, findDotAtSegment: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t) { var t1 = 1 - t; return { x: Math.pow(t1, 3) * p1x + Math.pow(t1, 2) * 3 * t * c1x + t1 * 3 * t * t * c2x + Math.pow(t, 3) * p2x, y: Math.pow(t1, 3) * p1y + Math.pow(t1, 2) * 3 * t * c1y + t1 * 3 * t * t * c2y + Math.pow(t, 3) * p2y }; }, snapEnds: function (from, to, stepsMax, prettyNumbers) { if (Ext.isDate(from)) { return this.snapEndsByDate(from, to, stepsMax); } var step = (to - from) / stepsMax, level = Math.floor(Math.log(step) / Math.LN10) + 1, m = Math.pow(10, level), cur, floor, modulo = Math.round((step % m) * Math.pow(10, 2 - level)), interval = [[0, 15], [10, 1], [20, 4], [25, 2], [50, 9], [100, 15]], stepCount = 0, value, weight, i, topValue, topWeight = 1e9, ln = interval.length; floor = Math.floor(from / m) * m; if (from == floor && floor > 0) { floor = Math.floor((from - (m/10)) / m) * m; } if (prettyNumbers) { for (i = 0; i < ln; i++) { value = interval[i][0]; weight = (value - modulo) < 0 ? 1e6 : (value - modulo) / interval[i][1]; if (weight < topWeight) { topValue = value; topWeight = weight; } } step = Math.floor(step * Math.pow(10, -level)) * Math.pow(10, level) + topValue * Math.pow(10, level - 2); if (from < 0 && to >= 0) { cur = 0; while (cur > from) { cur -= step; stepCount++; } from = +cur.toFixed(10); cur = 0; while (cur < to) { cur += step; stepCount++; } to = +cur.toFixed(10); } else { cur = from = floor; while (cur < to) { cur += step; stepCount++; } } to = +cur.toFixed(10); } else { from = floor; stepCount = stepsMax; } return { from: from, to: to, power: level, step: step, steps: stepCount }; }, snapEndsByDate: function (from, to, stepsMax, lockEnds) { var selectedStep = false, scales = [ [Ext.Date.MILLI, [1, 2, 5, 10, 20, 50, 100, 200, 250, 500]], [Ext.Date.SECOND, [1, 2, 5, 10, 15, 30]], [Ext.Date.MINUTE, [1, 2, 5, 10, 15, 30]], [Ext.Date.HOUR, [1, 2, 3, 4, 6, 12]], [Ext.Date.DAY, [1, 2, 7, 14]], [Ext.Date.MONTH, [1, 2, 3, 6]] ], sLen = scales.length, stop = false, scale, j, yearDiff, s; for (s = 0; s < sLen; s++) { scale = scales[s]; if (!stop) { for (j = 0; j < scale[1].length; j++) { if (to < Ext.Date.add(from, scale[0], scale[1][j] * stepsMax)) { selectedStep = [scale[0], scale[1][j]]; stop = true; break; } } } } if (!selectedStep) { yearDiff = this.snapEnds(from.getFullYear(), to.getFullYear() + 1, stepsMax, lockEnds); selectedStep = [Date.YEAR, Math.round(yearDiff.step)]; } return this.snapEndsByDateAndStep(from, to, selectedStep, lockEnds); }, snapEndsByDateAndStep: function(from, to, step, lockEnds) { var fromStat = [from.getFullYear(), from.getMonth(), from.getDate(), from.getHours(), from.getMinutes(), from.getSeconds(), from.getMilliseconds()], testFrom, testTo, date, year, month, day, fractionalMonth, stepsArray, stepUnit = step[0], stepValue = step[1], steps = 0; if (lockEnds) { testFrom = from; } else { switch (stepUnit) { case Ext.Date.MILLI: testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3], fromStat[4], fromStat[5], Math.floor(fromStat[6] / stepValue) * stepValue); break; case Ext.Date.SECOND: testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3], fromStat[4], Math.floor(fromStat[5] / stepValue) * stepValue, 0); break; case Ext.Date.MINUTE: testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3], Math.floor(fromStat[4] / stepValue) * stepValue, 0, 0); break; case Ext.Date.HOUR: testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], Math.floor(fromStat[3] / stepValue) * stepValue, 0, 0, 0); break; case Ext.Date.DAY: testFrom = new Date(fromStat[0], fromStat[1], Math.floor((fromStat[2] - 1) / stepValue) * stepValue + 1, 0, 0, 0, 0); break; case Ext.Date.MONTH: testFrom = new Date(fromStat[0], Math.floor(fromStat[1] / stepValue) * stepValue, 1, 0, 0, 0, 0); steps = []; stepsArray = true; break; default: testFrom = new Date(Math.floor(fromStat[0] / stepValue) * stepValue, 0, 1, 0, 0, 0, 0); steps = []; stepsArray = true; break; } } fractionalMonth = ((stepUnit === Ext.Date.MONTH) && (stepValue == 1/2 || stepValue == 1/3 || stepValue == 1/4)); testTo = new Date(testFrom); while (testTo < to) { if (fractionalMonth) { date = new Date(testTo); year = date.getFullYear(); month = date.getMonth(); day = date.getDate(); switch(stepValue) { case 1/2: if (day >= 15) { day = 1; if (++month > 11) { year++; } } else { day = 15; } break; case 1/3: if (day >= 20) { day = 1; if (++month > 11) { year++; } } else { if (day >= 10) { day = 20 } else { day = 10; } } break; case 1/4: if (day >= 22) { day = 1; if (++month > 11) { year++; } } else { if (day >= 15) { day = 22 } else { if (day >= 8) { day = 15 } else { day = 8; } } } break; } testTo.setYear(year); testTo.setMonth(month); testTo.setDate(day); steps.push(new Date(testTo)); } else if (stepsArray) { testTo = Ext.Date.add(testTo, stepUnit, stepValue); steps.push(new Date(testTo)); } else { testTo = Ext.Date.add(testTo, stepUnit, stepValue); steps++; } } if (lockEnds) { testTo = to; } if (stepsArray) { return { from : +testFrom, to : +testTo, steps : steps }; } else { return { from : +testFrom, to : +testTo, step : (testTo - testFrom) / steps, steps : steps }; } }, sorter: function (a, b) { return a.offset - b.offset; }, rad: function(degrees) { return degrees % 360 * Math.PI / 180; }, normalizeRadians: function(radian) { var twoPi = 2 * Math.PI; if (radian >= 0) { return radian % twoPi; } return ((radian % twoPi) + twoPi) % twoPi; }, degrees: function(radian) { return radian * 180 / Math.PI % 360; }, normalizeDegrees: function(degrees) { if (degrees >= 0) { return degrees % 360; } return ((degrees % 360) + 360) % 360; }, withinBox: function(x, y, bbox) { bbox = bbox || {}; return (x >= bbox.x && x <= (bbox.x + bbox.width) && y >= bbox.y && y <= (bbox.y + bbox.height)); }, parseGradient: function(gradient) { var me = this, type = gradient.type || 'linear', angle = gradient.angle || 0, radian = me.radian, stops = gradient.stops, stopsArr = [], stop, vector, max, stopObj; if (type == 'linear') { vector = [0, 0, Math.cos(angle * radian), Math.sin(angle * radian)]; max = 1 / (Math.max(Math.abs(vector[2]), Math.abs(vector[3])) || 1); vector[2] *= max; vector[3] *= max; if (vector[2] < 0) { vector[0] = -vector[2]; vector[2] = 0; } if (vector[3] < 0) { vector[1] = -vector[3]; vector[3] = 0; } } for (stop in stops) { if (stops.hasOwnProperty(stop) && me.stopsRE.test(stop)) { stopObj = { offset: parseInt(stop, 10), color: Ext.draw.Color.toHex(stops[stop].color) || '#ffffff', opacity: stops[stop].opacity || 1 }; stopsArr.push(stopObj); } } Ext.Array.sort(stopsArr, me.sorter); if (type == 'linear') { return { id: gradient.id, type: type, vector: vector, stops: stopsArr }; } else { return { id: gradient.id, type: type, centerX: gradient.centerX, centerY: gradient.centerY, focalX: gradient.focalX, focalY: gradient.focalY, radius: gradient.radius, vector: vector, stops: stopsArr }; } } }); Ext.define('Ext.fx.PropertyHandler', { statics: { defaultHandler: { pixelDefaultsRE: /width|height|top$|bottom$|left$|right$/i, unitRE: /^(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)*$/, scrollRE: /^scroll/i, computeDelta: function(from, end, damper, initial, attr) { damper = (typeof damper == 'number') ? damper : 1; var unitRE = this.unitRE, match = unitRE.exec(from), start, units; if (match) { from = match[1]; units = match[2]; if (!this.scrollRE.test(attr) && !units && this.pixelDefaultsRE.test(attr)) { units = 'px'; } } from = +from || 0; match = unitRE.exec(end); if (match) { end = match[1]; units = match[2] || units; } end = +end || 0; start = (initial != null) ? initial : from; return { from: from, delta: (end - start) * damper, units: units }; }, get: function(from, end, damper, initialFrom, attr) { var ln = from.length, out = [], i, initial, res, j, len; for (i = 0; i < ln; i++) { if (initialFrom) { initial = initialFrom[i][1].from; } if (Ext.isArray(from[i][1]) && Ext.isArray(end)) { res = []; j = 0; len = from[i][1].length; for (; j < len; j++) { res.push(this.computeDelta(from[i][1][j], end[j], damper, initial, attr)); } out.push([from[i][0], res]); } else { out.push([from[i][0], this.computeDelta(from[i][1], end, damper, initial, attr)]); } } return out; }, set: function(values, easing) { var ln = values.length, out = [], i, val, res, len, j; for (i = 0; i < ln; i++) { val = values[i][1]; if (Ext.isArray(val)) { res = []; j = 0; len = val.length; for (; j < len; j++) { res.push(val[j].from + val[j].delta * easing + (val[j].units || 0)); } out.push([values[i][0], res]); } else { out.push([values[i][0], val.from + val.delta * easing + (val.units || 0)]); } } return out; } }, stringHandler: { computeDelta: function(from, end, damper, initial, attr) { return { from: from, delta: end }; }, get: function(from, end, damper, initialFrom, attr) { var ln = from.length, out = [], i, initial, res, j, len; for (i = 0; i < ln; i++) { out.push([from[i][0], this.computeDelta(from[i][1], end, damper, initial, attr)]); } return out; }, set: function(values, easing) { var ln = values.length, out = [], i, val, res, len, j; for (i = 0; i < ln; i++) { val = values[i][1]; out.push([values[i][0], val.delta]); } return out; } }, color: { rgbRE: /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i, hexRE: /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i, hex3RE: /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i, parseColor : function(color, damper) { damper = (typeof damper == 'number') ? damper : 1; var out = false, reList = [this.hexRE, this.rgbRE, this.hex3RE], length = reList.length, match, base, re, i; for (i = 0; i < length; i++) { re = reList[i]; base = (i % 2 === 0) ? 16 : 10; match = re.exec(color); if (match && match.length === 4) { if (i === 2) { match[1] += match[1]; match[2] += match[2]; match[3] += match[3]; } out = { red: parseInt(match[1], base), green: parseInt(match[2], base), blue: parseInt(match[3], base) }; break; } } return out || color; }, computeDelta: function(from, end, damper, initial) { from = this.parseColor(from); end = this.parseColor(end, damper); var start = initial ? initial : from, tfrom = typeof start, tend = typeof end; if (tfrom == 'string' || tfrom == 'undefined' || tend == 'string' || tend == 'undefined') { return end || start; } return { from: from, delta: { red: Math.round((end.red - start.red) * damper), green: Math.round((end.green - start.green) * damper), blue: Math.round((end.blue - start.blue) * damper) } }; }, get: function(start, end, damper, initialFrom) { var ln = start.length, out = [], i, initial; for (i = 0; i < ln; i++) { if (initialFrom) { initial = initialFrom[i][1].from; } out.push([start[i][0], this.computeDelta(start[i][1], end, damper, initial)]); } return out; }, set: function(values, easing) { var ln = values.length, out = [], i, val, parsedString, from, delta; for (i = 0; i < ln; i++) { val = values[i][1]; if (val) { from = val.from; delta = val.delta; val = (typeof val == 'object' && 'red' in val)? 'rgb(' + val.red + ', ' + val.green + ', ' + val.blue + ')' : val; val = (typeof val == 'object' && val.length)? val[0] : val; if (typeof val == 'undefined') { return []; } parsedString = typeof val == 'string'? val : 'rgb(' + [ (from.red + Math.round(delta.red * easing)) % 256, (from.green + Math.round(delta.green * easing)) % 256, (from.blue + Math.round(delta.blue * easing)) % 256 ].join(',') + ')'; out.push([ values[i][0], parsedString ]); } } return out; } }, object: { interpolate: function(prop, damper) { damper = (typeof damper == 'number') ? damper : 1; var out = {}, p; for(p in prop) { out[p] = parseFloat(prop[p]) * damper; } return out; }, computeDelta: function(from, end, damper, initial) { from = this.interpolate(from); end = this.interpolate(end, damper); var start = initial ? initial : from, delta = {}, p; for(p in end) { delta[p] = end[p] - start[p]; } return { from: from, delta: delta }; }, get: function(start, end, damper, initialFrom) { var ln = start.length, out = [], i, initial; for (i = 0; i < ln; i++) { if (initialFrom) { initial = initialFrom[i][1].from; } out.push([start[i][0], this.computeDelta(start[i][1], end, damper, initial)]); } return out; }, set: function(values, easing) { var ln = values.length, out = [], outObject = {}, i, from, delta, val, p; for (i = 0; i < ln; i++) { val = values[i][1]; from = val.from; delta = val.delta; for (p in from) { outObject[p] = from[p] + delta[p] * easing; } out.push([ values[i][0], outObject ]); } return out; } }, path: { computeDelta: function(from, end, damper, initial) { damper = (typeof damper == 'number') ? damper : 1; var start; from = +from || 0; end = +end || 0; start = (initial != null) ? initial : from; return { from: from, delta: (end - start) * damper }; }, forcePath: function(path) { if (!Ext.isArray(path) && !Ext.isArray(path[0])) { path = Ext.draw.Draw.parsePathString(path); } return path; }, get: function(start, end, damper, initialFrom) { var endPath = this.forcePath(end), out = [], startLn = start.length, startPathLn, pointsLn, i, deltaPath, initial, j, k, path, startPath; for (i = 0; i < startLn; i++) { startPath = this.forcePath(start[i][1]); deltaPath = Ext.draw.Draw.interpolatePaths(startPath, endPath); startPath = deltaPath[0]; endPath = deltaPath[1]; startPathLn = startPath.length; path = []; for (j = 0; j < startPathLn; j++) { deltaPath = [startPath[j][0]]; pointsLn = startPath[j].length; for (k = 1; k < pointsLn; k++) { initial = initialFrom && initialFrom[0][1][j][k].from; deltaPath.push(this.computeDelta(startPath[j][k], endPath[j][k], damper, initial)); } path.push(deltaPath); } out.push([start[i][0], path]); } return out; }, set: function(values, easing) { var ln = values.length, out = [], i, j, k, newPath, calcPath, deltaPath, deltaPathLn, pointsLn; for (i = 0; i < ln; i++) { deltaPath = values[i][1]; newPath = []; deltaPathLn = deltaPath.length; for (j = 0; j < deltaPathLn; j++) { calcPath = [deltaPath[j][0]]; pointsLn = deltaPath[j].length; for (k = 1; k < pointsLn; k++) { calcPath.push(deltaPath[j][k].from + deltaPath[j][k].delta * easing); } newPath.push(calcPath.join(',')); } out.push([values[i][0], newPath.join(',')]); } return out; } } } }, function() { var props = [ 'outlineColor', 'backgroundColor', 'borderColor', 'borderTopColor', 'borderRightColor', 'borderBottomColor', 'borderLeftColor', 'fill', 'stroke' ], length = props.length, i = 0, prop; for (; i= duration) { elapsedTime = duration; lastFrame = true; } if (me.reverse) { elapsedTime = duration - elapsedTime; } for (attr in attrs) { if (attrs.hasOwnProperty(attr)) { values = attrs[attr]; easing = lastFrame ? 1 : easingFn(elapsedTime / duration); ret[attr] = propHandlers[attr].set(values, easing); } } me.frameCount++; return ret; }, lastFrame: function() { var me = this, iter = me.iterations, iterCount = me.currentIteration; iterCount++; if (iterCount < iter) { if (me.alternate) { me.reverse = !me.reverse; } me.startTime = new Date(); me.currentIteration = iterCount; me.paused = false; } else { me.currentIteration = 0; me.end(); me.fireEvent('lastframe', me, me.startTime); } }, endWasCalled: 0, end: function() { var me = this; if (me.endWasCalled++) { return; } me.startTime = 0; me.paused = false; me.running = false; Ext.fx.Manager.removeAnim(me); me.fireEvent('afteranimate', me, me.startTime); Ext.callback(me.callback, me.scope, [me, me.startTime]); if (me.remove) { me.target.remove(); } }, isReady: function() { return this.paused === false && this.running === false && this.iterations > 0; }, isRunning: function() { return this.paused === false && this.running === true && this.isAnimator !== true; } }); Ext.enableFx = true; Ext.define('Ext.util.Animate', { isAnimate: true, animate: function(animObj) { var me = this; if (Ext.fx.Manager.hasFxBlock(me.id)) { return me; } Ext.fx.Manager.queueFx(new Ext.fx.Anim(me.anim(animObj))); return this; }, anim: function(config) { if (!Ext.isObject(config)) { return (config) ? {} : false; } var me = this; if (config.stopAnimation) { me.stopAnimation(); } Ext.applyIf(config, Ext.fx.Manager.getFxDefaults(me.id)); return Ext.apply({ target: me, paused: true }, config); }, stopFx: Ext.Function.alias(Ext.util.Animate, 'stopAnimation'), stopAnimation: function() { Ext.fx.Manager.stopAnimation(this.id); return this; }, syncFx: function() { Ext.fx.Manager.setFxDefaults(this.id, { concurrent: true }); return this; }, sequenceFx: function() { Ext.fx.Manager.setFxDefaults(this.id, { concurrent: false }); return this; }, hasActiveFx: Ext.Function.alias(Ext.util.Animate, 'getActiveAnimation'), getActiveAnimation: function() { return Ext.fx.Manager.getActiveAnimation(this.id); } }, function(){ Ext.applyIf(Ext.Element.prototype, this.prototype); Ext.CompositeElementLite.importElementMethods(); }); Ext.define('Ext.util.ElementContainer', { childEls: [ ], constructor: function () { var me = this, childEls; if (me.hasOwnProperty('childEls')) { childEls = me.childEls; delete me.childEls; me.addChildEls.apply(me, childEls); } }, destroy: function () { var me = this, childEls = me.getChildEls(), child, childName, i, k; for (i = childEls.length; i--; ) { childName = childEls[i]; if (typeof childName != 'string') { childName = childName.name; } child = me[childName]; if (child) { me[childName] = null; child.remove(); } } }, addChildEls: function () { var me = this, args = arguments; if (me.hasOwnProperty('childEls')) { me.childEls.push.apply(me.childEls, args); } else { me.childEls = me.getChildEls().concat(Array.prototype.slice.call(args)); } me.prune(me.childEls, false); }, applyChildEls: function(el, id) { var me = this, childEls = me.getChildEls(), baseId, childName, i, selector, value; baseId = (id || me.id) + '-'; for (i = childEls.length; i--; ) { childName = childEls[i]; if (typeof childName == 'string') { value = el.getById(baseId + childName); } else { if ((selector = childName.select)) { value = Ext.select(selector, true, el.dom); } else if ((selector = childName.selectNode)) { value = Ext.get(Ext.DomQuery.selectNode(selector, el.dom)); } else { value = el.getById(childName.id || (baseId + childName.itemId)); } childName = childName.name; } me[childName] = value; } }, getChildEls: function () { var me = this, self; if (me.hasOwnProperty('childEls')) { return me.childEls; } self = me.self; return self.$childEls || me.getClassChildEls(self); }, getClassChildEls: function (cls) { var me = this, result = cls.$childEls, childEls, i, length, forked, mixin, mixins, name, parts, proto, supr, superMixins; if (!result) { supr = cls.superclass; if (supr) { supr = supr.self; parts = [supr.$childEls || me.getClassChildEls(supr)]; superMixins = supr.prototype.mixins || {}; } else { parts = []; superMixins = {}; } proto = cls.prototype; mixins = proto.mixins; for (name in mixins) { if (mixins.hasOwnProperty(name) && !superMixins.hasOwnProperty(name)) { mixin = mixins[name].self; parts.push(mixin.$childEls || me.getClassChildEls(mixin)); } } parts.push(proto.hasOwnProperty('childEls') && proto.childEls); for (i = 0, length = parts.length; i < length; ++i) { childEls = parts[i]; if (childEls && childEls.length) { if (!result) { result = childEls; } else { if (!forked) { forked = true; result = result.slice(0); } result.push.apply(result, childEls); } } } cls.$childEls = result = (result ? me.prune(result, !forked) : []); } return result; }, prune: function (childEls, shared) { var index = childEls.length, map = {}, name; while (index--) { name = childEls[index]; if (typeof name != 'string') { name = name.name; } if (!map[name]) { map[name] = 1; } else { if (shared) { shared = false; childEls = childEls.slice(0); } Ext.Array.erase(childEls, index, 1); } } return childEls; }, removeChildEls: function (testFn) { var me = this, old = me.getChildEls(), keepers = (me.childEls = []), n, i, cel; for (i = 0, n = old.length; i < n; ++i) { cel = old[i]; if (!testFn(cel)) { keepers.push(cel); } } } }); Ext.define('Ext.util.Renderable', { frameCls: Ext.baseCSSPrefix + 'frame', frameIdRegex: /[\-]frame\d+[TMB][LCR]$/, frameElNames: ['TL','TC','TR','ML','MC','MR','BL','BC','BR','Table'], frameTpl: [ '{%this.renderDockedItems(out,values,0);%}', '', '
{parent.baseCls}-{parent.ui}-{.}-tl{frameElCls}" role="presentation">', '
{parent.baseCls}-{parent.ui}-{.}-tr{frameElCls}" role="presentation">', '
{parent.baseCls}-{parent.ui}-{.}-tc{frameElCls}" role="presentation">
', '
', '
', '
', '
{parent.baseCls}-{parent.ui}-{.}-ml{frameElCls}" role="presentation">', '
{parent.baseCls}-{parent.ui}-{.}-mr{frameElCls}" role="presentation">', '
{parent.baseCls}-{parent.ui}-{.}-mc{frameElCls}" role="presentation">', '{%this.applyRenderTpl(out, values)%}', '
', '
', '
', '', '
{parent.baseCls}-{parent.ui}-{.}-bl{frameElCls}" role="presentation">', '
{parent.baseCls}-{parent.ui}-{.}-br{frameElCls}" role="presentation">', '
{parent.baseCls}-{parent.ui}-{.}-bc{frameElCls}" role="presentation">
', '
', '
', '
', '{%this.renderDockedItems(out,values,1);%}' ], frameTableTpl: [ '{%this.renderDockedItems(out,values,0);%}', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '{%this.renderDockedItems(out,values,1);%}' ], afterRender : function() { var me = this, data = {}, protoEl = me.protoEl, target = me.el, item, pre, hide, contentEl; me.finishRenderChildren(); if (me.contentEl) { pre = Ext.baseCSSPrefix; hide = pre + 'hide-'; contentEl = Ext.get(me.contentEl); contentEl.removeCls([pre+'hidden', hide+'display', hide+'offsets', hide+'nosize']); me.getContentTarget().appendChild(contentEl.dom); } protoEl.writeTo(data); item = data.removed; if (item) { target.removeCls(item); } item = data.cls; if (item.length) { target.addCls(item); } item = data.style; if (data.style) { target.setStyle(item); } me.protoEl = null; if (!me.ownerCt) { me.updateLayout(); } }, afterFirstLayout : function(width, height) { var me = this, x = me.x, y = me.y, hasX, hasY, pos, xy; if (!me.ownerLayout) { hasX = Ext.isDefined(x); hasY = Ext.isDefined(y); } if (me.floating && (!hasX || !hasY)) { if (me.floatParent) { pos = me.floatParent.getTargetEl().getViewRegion(); xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c'); pos.x = xy[0] - pos.x; pos.y = xy[1] - pos.y; } else { xy = me.el.getAlignToXY(me.container, 'c-c'); pos = me.container.translateXY(xy[0], xy[1]); } x = hasX ? x : pos.x; y = hasY ? y : pos.y; hasX = hasY = true; } if (hasX || hasY) { me.setPosition(x, y); } me.onBoxReady(width, height); }, applyRenderSelectors: function() { var me = this, selectors = me.renderSelectors, el = me.el, dom = el.dom, selector; me.applyChildEls(el); if (selectors) { for (selector in selectors) { if (selectors.hasOwnProperty(selector) && selectors[selector]) { me[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], dom)); } } } }, beforeRender: function () { var me = this, target = me.getTargetEl(), overflowEl = me.getOverflowEl(), layout = me.getComponentLayout(), overflowStyle = me.getOverflowStyle(); me.frame = me.frame || me.alwaysFramed; if (!layout.initialized) { layout.initLayout(); } if (overflowEl) { overflowEl.setStyle(overflowStyle); me.overflowStyleSet = true; } me.setUI(me.ui); if (me.disabled) { me.disable(true); } }, doApplyRenderTpl: function(out, values) { var me = values.$comp, tpl; if (!me.rendered) { tpl = me.initRenderTpl(); tpl.applyOut(values.renderData, out); } }, doAutoRender: function() { var me = this; if (!me.rendered) { if (me.floating) { me.render(document.body); } else { me.render(Ext.isBoolean(me.autoRender) ? Ext.getBody() : me.autoRender); } } }, doRenderContent: function (out, renderData) { var me = renderData.$comp; if (me.html) { Ext.DomHelper.generateMarkup(me.html, out); delete me.html; } if (me.tpl) { if (!me.tpl.isTemplate) { me.tpl = new Ext.XTemplate(me.tpl); } if (me.data) { me.tpl.applyOut(me.data, out); delete me.data; } } }, doRenderFramingDockedItems: function (out, renderData, after) { var me = renderData.$comp; if (!me.rendered && me.doRenderDockedItems) { renderData.renderData.$skipDockedItems = true; me.doRenderDockedItems.call(this, out, renderData, after); } }, finishRender: function(containerIdx) { var me = this, tpl, data, el; if (!me.el || me.$pid) { if (me.container) { el = me.container.getById(me.id, true); } else { el = Ext.getDom(me.id); } if (!me.el) { me.wrapPrimaryEl(el); } else { delete me.$pid; if (!me.el.dom) { me.wrapPrimaryEl(me.el); } el.parentNode.insertBefore(me.el.dom, el); Ext.removeNode(el); } } else if (!me.rendering) { tpl = me.initRenderTpl(); if (tpl) { data = me.initRenderData(); tpl.insertFirst(me.getTargetEl(), data); } } if (!me.container) { me.container = Ext.get(me.el.dom.parentNode); } if (me.ctCls) { me.container.addCls(me.ctCls); } me.onRender(me.container, containerIdx); if (!me.overflowStyleSet) { me.getOverflowEl().setStyle(me.getOverflowStyle()); } me.el.setVisibilityMode(Ext.Element[me.hideMode.toUpperCase()]); if (me.overCls) { me.el.hover(me.addOverCls, me.removeOverCls, me); } if (me.hasListeners.render) { me.fireEvent('render', me); } me.afterRender(); if (me.hasListeners.afterrender) { me.fireEvent('afterrender', me); } me.initEvents(); if (me.hidden) { me.el.hide(); } }, finishRenderChildren: function () { var layout = this.getComponentLayout(); layout.finishRender(); }, getElConfig : function() { var me = this, autoEl = me.autoEl, frameInfo = me.getFrameInfo(), config = { tag: 'div', tpl: frameInfo ? me.initFramingTpl(frameInfo.table) : me.initRenderTpl() }, protoEl = me.protoEl, i, frameElNames, len, suffix, frameGenId, frameData; me.initStyles(protoEl); protoEl.writeTo(config); protoEl.flush(); if (Ext.isString(autoEl)) { config.tag = autoEl; } else { Ext.apply(config, autoEl); } config.id = me.id; if (config.tpl) { if (frameInfo) { frameElNames = me.frameElNames; len = frameElNames.length; config.tplData = frameData = me.getFrameRenderData(); frameData.renderData = me.initRenderData(); frameGenId = frameData.fgid; for (i = 0; i < len; i++) { suffix = frameElNames[i]; me.addChildEls({ name: 'frame' + suffix, id: frameGenId + suffix }); } me.addChildEls({ name: 'frameBody', id: frameGenId + 'MC' }); } else { config.tplData = me.initRenderData(); } } return config; }, initFramingTpl: function(table) { var tpl = this.getFrameTpl(table); if (tpl && !tpl.applyRenderTpl) { this.setupFramingTpl(tpl); } return tpl; }, setupFramingTpl: function(frameTpl) { frameTpl.applyRenderTpl = this.doApplyRenderTpl; frameTpl.renderDockedItems = this.doRenderFramingDockedItems; }, getInsertPosition: function(position) { if (position !== undefined) { if (Ext.isNumber(position)) { position = this.container.dom.childNodes[position]; } else { position = Ext.getDom(position); } } return position; }, getRenderTree: function() { var me = this; if (!me.hasListeners.beforerender || me.fireEvent('beforerender', me) !== false) { me.beforeRender(); me.rendering = true; if (me.el) { return { tag: 'div', role: 'presentation', id: (me.$pid = Ext.id()) }; } return me.getElConfig(); } return null; }, initContainer: function(container) { var me = this; if (!container && me.el) { container = me.el.dom.parentNode; me.allowDomMove = false; } me.container = container.dom ? container : Ext.get(container); return me.container; }, initRenderData: function() { var me = this; return Ext.apply({ $comp: me, id: me.id, ui: me.ui, uiCls: me.uiCls, baseCls: me.baseCls, componentCls: me.componentCls, frame: me.frame, role: me.ariaRole, childElCls: '' }, me.renderData); }, initRenderTpl: function() { var tpl = this.getTpl('renderTpl'); if (tpl && !tpl.renderContent) { this.setupRenderTpl(tpl); } return tpl; }, onRender: function(parentNode, containerIdx) { var me = this, x = me.x, y = me.y, lastBox = null, width, height, el = me.el; me.applyRenderSelectors(); me.rendering = null; me.rendered = true; if (x != null) { lastBox = {x:x}; } if (y != null) { (lastBox = lastBox || {}).y = y; } if (!me.getFrameInfo() && Ext.isBorderBox) { width = me.width; height = me.height; if (typeof width === 'number') { lastBox = lastBox || {}; lastBox.width = width; } if (typeof height === 'number') { lastBox = lastBox || {}; lastBox.height = height; } } me.lastBox = el.lastBox = lastBox; }, render: function(container, position) { var me = this, el = me.el && (me.el = Ext.get(me.el)), vetoed, tree, nextSibling; Ext.suspendLayouts(); container = me.initContainer(container); nextSibling = me.getInsertPosition(position); if (!el) { tree = me.getRenderTree(); if (me.ownerLayout && me.ownerLayout.transformItemRenderTree) { tree = me.ownerLayout.transformItemRenderTree(tree); } if (tree) { if (nextSibling) { el = Ext.DomHelper.insertBefore(nextSibling, tree); } else { el = Ext.DomHelper.append(container, tree); } me.wrapPrimaryEl(el); } } else { if (!me.hasListeners.beforerender || me.fireEvent('beforerender', me) !== false) { me.beforeRender(); me.initStyles(el); if (me.allowDomMove !== false) { if (nextSibling) { container.dom.insertBefore(el.dom, nextSibling); } else { container.dom.appendChild(el.dom); } } } else { vetoed = true; } } if (el && !vetoed) { me.finishRender(position); } Ext.resumeLayouts(!me.hidden && !container.isDetachedBody); }, ensureAttachedToBody: function (runLayout) { var comp = this, body; while (comp.ownerCt) { comp = comp.ownerCt; } if (comp.container.isDetachedBody) { comp.container = body = Ext.getBody(); body.appendChild(comp.el.dom); if (runLayout) { comp.updateLayout(); } if (typeof comp.x == 'number' || typeof comp.y == 'number') { comp.setPosition(comp.x, comp.y); } } }, setupRenderTpl: function (renderTpl) { renderTpl.renderBody = renderTpl.renderContent = this.doRenderContent; }, wrapPrimaryEl: function (dom) { this.el = Ext.get(dom, true); }, initFrame : function() { if (Ext.supports.CSS3BorderRadius || !this.frame) { return; } var me = this, frameInfo = me.getFrameInfo(), frameTpl, frameGenId, frameElNames = me.frameElNames, len = frameElNames.length, i, frameData, suffix; if (frameInfo) { frameTpl = me.getFrameTpl(frameInfo.table); frameData = me.getFrameRenderData(); frameGenId = frameData.fgid; frameTpl.insertFirst(me.el, frameData); me.frameBody = me.el.down('.' + me.frameCls + '-mc'); me.removeChildEls(function (c) { return c.id && me.frameIdRegex.test(c.id); }); for (i = 0; i < len; i++) { suffix = frameElNames[i]; me['frame' + suffix] = me.el.getById(frameGenId + suffix); } } }, getFrameRenderData: function () { var me = this, frameInfo = me.frameSize, frameGenId = (me.frameGenId || 0) + 1; me.frameGenId = frameGenId; return { $comp: me, fgid: me.id + '-frame' + frameGenId, ui: me.ui, uiCls: me.uiCls, frameCls: me.frameCls, baseCls: me.baseCls, top: !!frameInfo.top, left: !!frameInfo.left, right: !!frameInfo.right, bottom: !!frameInfo.bottom, frameElCls: '' }; }, updateFrame: function() { if (Ext.supports.CSS3BorderRadius || !this.frame) { return; } var me = this, wasTable = me.frameSize && me.frameSize.table, oldFrameTL = me.frameTL, oldFrameBL = me.frameBL, oldFrameML = me.frameML, oldFrameMC = me.frameMC, newMCClassName; me.initFrame(); if (oldFrameMC) { if (me.frame) { newMCClassName = me.frameMC.dom.className; oldFrameMC.insertAfter(me.frameMC); me.frameMC.remove(); me.frameBody = me.frameMC = oldFrameMC; oldFrameMC.dom.className = newMCClassName; if (wasTable) { me.el.query('> table')[1].remove(); } else { if (oldFrameTL) { oldFrameTL.remove(); } if (oldFrameBL) { oldFrameBL.remove(); } if (oldFrameML) { oldFrameML.remove(); } } } } else if (me.frame) { me.applyRenderSelectors(); } }, getFrameInfo: function() { if (Ext.supports.CSS3BorderRadius || !this.frame) { return false; } var me = this, frameInfoCache = me.frameInfoCache, cls = me.getFramingInfoCls() + '-frameInfo', frameInfo = frameInfoCache[cls], max = Math.max, styleEl, match, info, frameTop, frameRight, frameBottom, frameLeft, borderWidthT, borderWidthR, borderWidthB, borderWidthL, paddingT, paddingR, paddingB, paddingL, borderRadiusTL, borderRadiusTR, borderRadiusBR, borderRadiusBL; if (frameInfo == null) { styleEl = Ext.fly(me.getStyleProxy(cls), 'frame-style-el'); info = styleEl.getStyle('font-family'); if (info) { info = info.split('-'); borderRadiusTL = parseInt(info[1], 10); borderRadiusTR = parseInt(info[2], 10); borderRadiusBR = parseInt(info[3], 10); borderRadiusBL = parseInt(info[4], 10); borderWidthT = parseInt(info[5], 10); borderWidthR = parseInt(info[6], 10); borderWidthB = parseInt(info[7], 10); borderWidthL = parseInt(info[8], 10); paddingT = parseInt(info[9], 10); paddingR = parseInt(info[10], 10); paddingB = parseInt(info[11], 10); paddingL = parseInt(info[12], 10); frameTop = max(borderWidthT, max(borderRadiusTL, borderRadiusTR)); frameRight = max(borderWidthR, max(borderRadiusTR, borderRadiusBR)); frameBottom = max(borderWidthB, max(borderRadiusBL, borderRadiusBR)); frameLeft = max(borderWidthL, max(borderRadiusTL, borderRadiusBL)); frameInfo = { table: info[0].charAt(0) === 't', vertical: info[0].charAt(1) === 'v', top: frameTop, right: frameRight, bottom: frameBottom, left: frameLeft, width: frameLeft + frameRight, height: frameTop + frameBottom, maxWidth: max(frameTop, frameRight, frameBottom, frameLeft), border: { top: borderWidthT, right: borderWidthR, bottom: borderWidthB, left: borderWidthL, width: borderWidthL + borderWidthR, height: borderWidthT + borderWidthB }, padding: { top: paddingT, right: paddingR, bottom: paddingB, left: paddingL, width: paddingL + paddingR, height: paddingT + paddingB }, radius: { tl: borderRadiusTL, tr: borderRadiusTR, br: borderRadiusBR, bl: borderRadiusBL } }; } else { frameInfo = false; } frameInfoCache[cls] = frameInfo; } me.frame = !!frameInfo; me.frameSize = frameInfo; return frameInfo; }, getFramingInfoCls: function(){ return this.baseCls + '-' + this.ui; }, getStyleProxy: function(cls) { var result = this.styleProxyEl || (Ext.AbstractComponent.prototype.styleProxyEl = Ext.getBody().createChild({ role: 'presentation', style: { position: 'absolute', top: '-10000px' } }, null, true)); result.className = cls; return result; }, getFrameTpl : function(table) { return this.getTpl(table ? 'frameTableTpl' : 'frameTpl'); }, frameInfoCache: {} }); Ext.define('Ext.state.Provider', { mixins: { observable: Ext.util.Observable }, prefix: 'ext-', constructor : function(config){ config = config || {}; var me = this; Ext.apply(me, config); me.addEvents("statechange"); me.state = {}; me.mixins.observable.constructor.call(me); }, get : function(name, defaultValue){ return typeof this.state[name] == "undefined" ? defaultValue : this.state[name]; }, clear : function(name){ var me = this; delete me.state[name]; me.fireEvent("statechange", me, name, null); }, set : function(name, value){ var me = this; me.state[name] = value; me.fireEvent("statechange", me, name, value); }, decodeValue : function(value){ var me = this, re = /^(a|n|d|b|s|o|e)\:(.*)$/, matches = re.exec(unescape(value)), all, type, keyValue, values, vLen, v; if(!matches || !matches[1]){ return; } type = matches[1]; value = matches[2]; switch (type) { case 'e': return null; case 'n': return parseFloat(value); case 'd': return new Date(Date.parse(value)); case 'b': return (value == '1'); case 'a': all = []; if(value != ''){ values = value.split('^'); vLen = values.length; for (v = 0; v < vLen; v++) { value = values[v]; all.push(me.decodeValue(value)); } } return all; case 'o': all = {}; if(value != ''){ values = value.split('^'); vLen = values.length; for (v = 0; v < vLen; v++) { value = values[v]; keyValue = value.split('='); all[keyValue[0]] = me.decodeValue(keyValue[1]); } } return all; default: return value; } }, encodeValue : function(value){ var flat = '', i = 0, enc, len, key; if (value == null) { return 'e:1'; } else if(typeof value == 'number') { enc = 'n:' + value; } else if(typeof value == 'boolean') { enc = 'b:' + (value ? '1' : '0'); } else if(Ext.isDate(value)) { enc = 'd:' + value.toGMTString(); } else if(Ext.isArray(value)) { for (len = value.length; i < len; i++) { flat += this.encodeValue(value[i]); if (i != len - 1) { flat += '^'; } } enc = 'a:' + flat; } else if (typeof value == 'object') { for (key in value) { if (typeof value[key] != 'function' && value[key] !== undefined) { flat += key + '=' + this.encodeValue(value[key]) + '^'; } } enc = 'o:' + flat.substring(0, flat.length-1); } else { enc = 's:' + value; } return escape(enc); } }); Ext.define('Ext.state.Manager', { singleton: true, constructor: function() { this.provider = new Ext.state.Provider(); }, setProvider : function(stateProvider){ this.provider = stateProvider; }, get : function(key, defaultValue){ return this.provider.get(key, defaultValue); }, set : function(key, value){ this.provider.set(key, value); }, clear : function(key){ this.provider.clear(key); }, getProvider : function(){ return this.provider; } }); Ext.define('Ext.state.Stateful', { mixins: { observable: Ext.util.Observable }, stateful: false, saveDelay: 100, constructor: function(config) { var me = this; config = config || {}; if (config.stateful !== undefined) { me.stateful = config.stateful; } if (config.saveDelay !== undefined) { me.saveDelay = config.saveDelay; } me.stateId = me.stateId || config.stateId; if (!me.stateEvents) { me.stateEvents = []; } if (config.stateEvents) { me.stateEvents.concat(config.stateEvents); } this.addEvents( 'beforestaterestore', 'staterestore', 'beforestatesave', 'statesave' ); me.mixins.observable.constructor.call(me); if (me.stateful !== false) { me.addStateEvents(me.stateEvents); me.initState(); } }, addStateEvents: function (events) { var me = this, i, event, stateEventsByName; if (me.stateful && me.getStateId()) { if (typeof events == 'string') { events = Array.prototype.slice.call(arguments, 0); } stateEventsByName = me.stateEventsByName || (me.stateEventsByName = {}); for (i = events.length; i--; ) { event = events[i]; if (!stateEventsByName[event]) { stateEventsByName[event] = 1; me.on(event, me.onStateChange, me); } } } }, onStateChange: function(){ var me = this, delay = me.saveDelay, statics, runner; if (!me.stateful) { return; } if (delay) { if (!me.stateTask) { statics = Ext.state.Stateful; runner = statics.runner || (statics.runner = new Ext.util.TaskRunner()); me.stateTask = runner.newTask({ run: me.saveState, scope: me, interval: delay, repeat: 1 }); } me.stateTask.start(); } else { me.saveState(); } }, saveState: function() { var me = this, id = me.stateful && me.getStateId(), hasListeners = me.hasListeners, state; if (id) { state = me.getState() || {}; if (!hasListeners.beforestatesave || me.fireEvent('beforestatesave', me, state) !== false) { Ext.state.Manager.set(id, state); if (hasListeners.statesave) { me.fireEvent('statesave', me, state); } } } }, getState: function(){ return null; }, applyState: function(state) { if (state) { Ext.apply(this, state); } }, getStateId: function() { var me = this; return me.stateId || (me.autoGenId ? null : me.id); }, initState: function(){ var me = this, id = me.stateful && me.getStateId(), hasListeners = me.hasListeners, state; if (id) { state = Ext.state.Manager.get(id); if (state) { state = Ext.apply({}, state); if (!hasListeners.beforestaterestore || me.fireEvent('beforestaterestore', me, state) !== false) { me.applyState(state); if (hasListeners.staterestore) { me.fireEvent('staterestore', me, state); } } } } }, savePropToState: function (propName, state, stateName) { var me = this, value = me[propName], config = me.initialConfig; if (me.hasOwnProperty(propName)) { if (!config || config[propName] !== value) { if (state) { state[stateName || propName] = value; } return true; } } return false; }, savePropsToState: function (propNames, state) { var me = this, i, n; if (typeof propNames == 'string') { me.savePropToState(propNames, state); } else { for (i = 0, n = propNames.length; i < n; ++i) { me.savePropToState(propNames[i], state); } } return state; }, destroy: function(){ var me = this, task = me.stateTask; if (task) { task.destroy(); me.stateTask = null; } me.clearListeners(); } }); Ext.define('Ext.AbstractComponent', { mixins: { positionable: Ext.util.Positionable , observable: Ext.util.Observable , animate: Ext.util.Animate , elementCt: Ext.util.ElementContainer , renderable: Ext.util.Renderable , state: Ext.state.Stateful }, statics: { AUTO_ID: 1000, pendingLayouts: null, layoutSuspendCount: 0, cancelLayout: function(comp, isDestroying) { var context = this.runningLayoutContext || this.pendingLayouts; if (context) { context.cancelComponent(comp, false, isDestroying); } }, flushLayouts: function () { var me = this, context = me.pendingLayouts; if (context && context.invalidQueue.length) { me.pendingLayouts = null; me.runningLayoutContext = context; Ext.override(context, { runComplete: function () { me.runningLayoutContext = null; var result = this.callParent(); if (Ext.globalEvents.hasListeners.afterlayout) { Ext.globalEvents.fireEvent('afterlayout'); } return result; } }); context.run(); } }, resumeLayouts: function (flush) { if (this.layoutSuspendCount && ! --this.layoutSuspendCount) { if (flush) { this.flushLayouts(); } if (Ext.globalEvents.hasListeners.resumelayouts) { Ext.globalEvents.fireEvent('resumelayouts'); } } }, suspendLayouts: function () { ++this.layoutSuspendCount; }, updateLayout: function (comp, defer) { var me = this, running = me.runningLayoutContext, pending; if (running) { running.queueInvalidate(comp); } else { pending = me.pendingLayouts || (me.pendingLayouts = new Ext.layout.Context()); pending.queueInvalidate(comp); if (!defer && !me.layoutSuspendCount && !comp.isLayoutSuspended()) { me.flushLayouts(); } } } }, isComponent: true, getAutoId: function() { this.autoGenId = true; return ++Ext.AbstractComponent.AUTO_ID; }, deferLayouts: false, autoGenId: false, renderTpl: '{%this.renderContent(out,values)%}', frameSize: null, tplWriteMode: 'overwrite', baseCls: Ext.baseCSSPrefix + 'component', disabledCls: Ext.baseCSSPrefix + 'item-disabled', ui: 'default', uiCls: [], hidden: false, disabled: false, draggable: false, floating: false, hideMode: 'display', autoShow: false, autoRender: false, allowDomMove: true, rendered: false, componentLayoutCounter: 0, shrinkWrap: 2, weight: 0, maskOnDisable: true, _isLayoutRoot: false, contentPaddingProperty: 'padding', horizontalPosProp: 'left', borderBoxCls: Ext.baseCSSPrefix + 'border-box', rootCls: Ext.baseCSSPrefix + 'body', constructor : function(config) { var me = this, i, len, xhooks; if (config) { Ext.apply(me, config); xhooks = me.xhooks; if (xhooks) { delete me.xhooks; Ext.override(me, xhooks); } } else { config = {}; } me.initialConfig = config; me.mixins.elementCt.constructor.call(me); me.addEvents( 'beforeactivate', 'activate', 'beforedeactivate', 'deactivate', 'added', 'disable', 'enable', 'beforeshow', 'show', 'beforehide', 'hide', 'removed', 'beforerender', 'render', 'afterrender', 'boxready', 'beforedestroy', 'destroy', 'resize', 'move', 'focus', 'blur' ); me.getId(); me.setupProtoEl(); if (me.cls) { me.initialCls = me.cls; me.protoEl.addCls(me.cls); } if (me.style) { me.initialStyle = me.style; me.protoEl.setStyle(me.style); } me.renderData = me.renderData || {}; me.renderSelectors = me.renderSelectors || {}; if (me.plugins) { me.plugins = me.constructPlugins(); } if (!me.hasListeners) { me.hasListeners = new me.HasListeners(); } me.initComponent(); Ext.ComponentManager.register(me); me.mixins.observable.constructor.call(me); me.mixins.state.constructor.call(me, config); this.addStateEvents('resize'); if (me.plugins) { for (i = 0, len = me.plugins.length; i < len; i++) { me.plugins[i] = me.initPlugin(me.plugins[i]); } } me.loader = me.getLoader(); if (me.renderTo) { me.render(me.renderTo); } if (me.autoShow && !me.isContained) { me.show(); } }, initComponent: function () { var me = this; if (me.plugins && !me.plugins.processed) { me.plugins = me.constructPlugins(); } me.setSize(me.width, me.height); }, getState: function() { var me = this, state = null, sizeModel = me.getSizeModel(); if (sizeModel.width.configured) { state = me.addPropertyToState(state, 'width'); } if (sizeModel.height.configured) { state = me.addPropertyToState(state, 'height'); } return state; }, addPropertyToState: function (state, propName, value) { var me = this, len = arguments.length; if (len == 3 || me.hasOwnProperty(propName)) { if (len < 3) { value = me[propName]; } if (value !== me.initialConfig[propName]) { (state || (state = {}))[propName] = value; } } return state; }, show: Ext.emptyFn, animate: function(animObj) { var me = this, hasToWidth, hasToHeight, toHeight, toWidth, to, clearWidth, clearHeight, curWidth, w, curHeight, h, isExpanding, wasConstrained, wasConstrainedHeader, passedCallback, oldOverflow; animObj = animObj || {}; to = animObj.to || {}; if (Ext.fx.Manager.hasFxBlock(me.id)) { return me; } hasToWidth = Ext.isDefined(to.width); if (hasToWidth) { toWidth = Ext.Number.constrain(to.width, me.minWidth, me.maxWidth); } hasToHeight = Ext.isDefined(to.height); if (hasToHeight) { toHeight = Ext.Number.constrain(to.height, me.minHeight, me.maxHeight); } if (!animObj.dynamic && (hasToWidth || hasToHeight)) { curWidth = (animObj.from ? animObj.from.width : undefined) || me.getWidth(); w = curWidth; curHeight = (animObj.from ? animObj.from.height : undefined) || me.getHeight(); h = curHeight; isExpanding = false; if (hasToHeight && toHeight > curHeight) { h = toHeight; isExpanding = true; } if (hasToWidth && toWidth > curWidth) { w = toWidth; isExpanding = true; } if (hasToHeight || hasToWidth) { oldOverflow = me.el.getStyle('overtflow'); if (oldOverflow !== 'hidden') { me.el.setStyle('overflow', 'hidden'); } } if (isExpanding) { clearWidth = !Ext.isNumber(me.width); clearHeight = !Ext.isNumber(me.height); me.setSize(w, h); me.el.setSize(curWidth, curHeight); if (clearWidth) { delete me.width; } if (clearHeight) { delete me.height; } } if (hasToWidth) { to.width = toWidth; } if (hasToHeight) { to.height = toHeight; } } wasConstrained = me.constrain; wasConstrainedHeader = me.constrainHeader; if (wasConstrained || wasConstrainedHeader) { me.constrain = me.constrainHeader = false; passedCallback = animObj.callback; animObj.callback = function() { me.constrain = wasConstrained; me.constrainHeader = wasConstrainedHeader; if (passedCallback) { passedCallback.call(animObj.scope||me, arguments); } if (oldOverflow !== 'hidden') { me.el.setStyle('overflow', oldOverflow); } }; } return me.mixins.animate.animate.apply(me, arguments); }, setHiddenState: function(hidden){ var hierarchyState = this.getHierarchyState(); this.hidden = hidden; if (hidden) { hierarchyState.hidden = true; } else { delete hierarchyState.hidden; } }, onHide: function() { if (this.ownerLayout) { this.updateLayout({ isRoot: false }); } }, onShow : function() { this.updateLayout({ isRoot: false }); }, constructPlugin: function(plugin) { var me = this; if (typeof plugin == 'string') { plugin = Ext.PluginManager.create({}, plugin, me); } else { plugin = Ext.PluginManager.create(plugin, null, me); } return plugin; }, constructPlugins: function() { var me = this, plugins = me.plugins, result, i, len; if (plugins) { result = []; result.processed = true; if (!Ext.isArray(plugins)) { plugins = [ plugins ]; } for (i = 0, len = plugins.length; i < len; i++) { result[i] = me.constructPlugin(plugins[i]); } } me.pluginsInitialized = true; return result; }, initPlugin : function(plugin) { plugin.init(this); return plugin; }, addPlugin: function(plugin) { var me = this; plugin = me.constructPlugin(plugin); if (me.plugins) { me.plugins.push(plugin); } else { me.plugins = [ plugin ]; } if (me.pluginsInitialized) { me.initPlugin(plugin); } return plugin; }, removePlugin: function(plugin) { Ext.Array.remove(this.plugins, plugin); plugin.destroy(); }, findPlugin: function(ptype) { var i, plugins = this.plugins, ln = plugins && plugins.length; for (i = 0; i < ln; i++) { if (plugins[i].ptype === ptype) { return plugins[i]; } } }, getPlugin: function(pluginId) { var i, plugins = this.plugins, ln = plugins && plugins.length; for (i = 0; i < ln; i++) { if (plugins[i].pluginId === pluginId) { return plugins[i]; } } }, beforeLayout: Ext.emptyFn, registerFloatingItem: function(cmp) { var me = this; if (!me.floatingDescendants) { me.floatingDescendants = new Ext.ZIndexManager(me); } me.floatingDescendants.register(cmp); }, unregisterFloatingItem: function(cmp) { var me = this; if (me.floatingDescendants) { me.floatingDescendants.unregister(cmp); } }, layoutSuspendCount: 0, suspendLayouts: function () { var me = this; if (!me.rendered) { return; } if (++me.layoutSuspendCount == 1) { me.suspendLayout = true; } }, resumeLayouts: function (flushOptions) { var me = this; if (!me.rendered) { return; } if (! --me.layoutSuspendCount) { me.suspendLayout = false; if (flushOptions && !me.isLayoutSuspended()) { me.updateLayout(flushOptions); } } }, setupProtoEl: function() { var cls = this.initCls(); this.protoEl = new Ext.util.ProtoElement({ cls: cls.join(' ') }); }, initCls: function() { var me = this, cls = [ me.baseCls, me.getComponentLayout().targetCls ]; if (Ext.isDefined(me.cmpCls)) { if (Ext.isDefined(Ext.global.console)) { Ext.global.console.warn('Ext.Component: cmpCls has been deprecated. Please use componentCls.'); } me.componentCls = me.cmpCls; delete me.cmpCls; } if (me.componentCls) { cls.push(me.componentCls); } else { me.componentCls = me.baseCls; } return cls; }, setUI: function(ui) { var me = this, uiCls = me.uiCls, activeUI = me.activeUI, classes; if (ui === activeUI) { return; } if (activeUI) { classes = me.removeClsWithUI(uiCls, true); if (classes.length) { me.removeCls(classes); } me.removeUIFromElement(); } else { me.uiCls = []; } me.ui = ui; me.activeUI = ui; me.addUIToElement(); classes = me.addClsWithUI(uiCls, true); if (classes.length) { me.addCls(classes); } if (me.rendered) { me.updateLayout(); } }, addClsWithUI: function(classes, skip) { var me = this, clsArray = [], i = 0, uiCls = me.uiCls = Ext.Array.clone(me.uiCls), activeUI = me.activeUI, length, cls; if (typeof classes === "string") { classes = (classes.indexOf(' ') < 0) ? [classes] : Ext.String.splitWords(classes); } length = classes.length; for (; i < length; i++) { cls = classes[i]; if (cls && !me.hasUICls(cls)) { uiCls.push(cls); if (activeUI) { clsArray = clsArray.concat(me.addUIClsToElement(cls)); } } } if (skip !== true && activeUI) { me.addCls(clsArray); } return clsArray; }, removeClsWithUI: function(classes, skip) { var me = this, clsArray = [], i = 0, extArray = Ext.Array, remove = extArray.remove, uiCls = me.uiCls = extArray.clone(me.uiCls), activeUI = me.activeUI, length, cls; if (typeof classes === "string") { classes = (classes.indexOf(' ') < 0) ? [classes] : Ext.String.splitWords(classes); } length = classes.length; for (i = 0; i < length; i++) { cls = classes[i]; if (cls && me.hasUICls(cls)) { remove(uiCls, cls); if (activeUI) { clsArray = clsArray.concat(me.removeUIClsFromElement(cls)); } } } if (skip !== true && activeUI) { me.removeCls(clsArray); } return clsArray; }, hasUICls: function(cls) { var me = this, uiCls = me.uiCls || []; return Ext.Array.contains(uiCls, cls); }, frameElementsArray: ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'], addUIClsToElement: function(cls) { var me = this, baseClsUi = me.baseCls + '-' + me.ui + '-' + cls, result = [Ext.baseCSSPrefix + cls, me.baseCls + '-' + cls, baseClsUi], frameElementsArray, frameElementsLength, i, el, frameElement; if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) { frameElementsArray = me.frameElementsArray; frameElementsLength = frameElementsArray.length; for (i = 0; i < frameElementsLength; i++) { frameElement = frameElementsArray[i]; el = me['frame' + frameElement.toUpperCase()]; if (el) { el.addCls(baseClsUi + '-' + frameElement); } } } return result; }, removeUIClsFromElement: function(cls) { var me = this, baseClsUi = me.baseCls + '-' + me.ui + '-' + cls, result = [Ext.baseCSSPrefix + cls, me.baseCls + '-' + cls, baseClsUi], frameElementsArray, frameElementsLength, i, el, frameElement; if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) { frameElementsArray = me.frameElementsArray; frameElementsLength = frameElementsArray.length; for (i = 0; i < frameElementsLength; i++) { frameElement = frameElementsArray[i]; el = me['frame' + frameElement.toUpperCase()]; if (el) { el.removeCls(baseClsUi + '-' + frameElement); } } } return result; }, addUIToElement: function() { var me = this, baseClsUI = me.baseCls + '-' + me.ui, frameElementsArray, frameElementsLength, i, el, frameElement; me.addCls(baseClsUI); if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) { frameElementsArray = me.frameElementsArray; frameElementsLength = frameElementsArray.length; for (i = 0; i < frameElementsLength; i++) { frameElement = frameElementsArray[i]; el = me['frame' + frameElement.toUpperCase()]; if (el) { el.addCls(baseClsUI + '-' + frameElement); } } } }, removeUIFromElement: function() { var me = this, baseClsUI = me.baseCls + '-' + me.ui, frameElementsArray, frameElementsLength, i, el, frameElement; me.removeCls(baseClsUI); if (me.rendered && me.frame && !Ext.supports.CSS3BorderRadius) { frameElementsArray = me.frameElementsArray; frameElementsLength = frameElementsArray.length; for (i = 0; i < frameElementsLength; i++) { frameElement = frameElementsArray[i]; el = me['frame' + frameElement.toUpperCase()]; if (el) { el.removeCls(baseClsUI + '-' + frameElement); } } } }, getTpl: function(name) { return Ext.XTemplate.getTpl(this, name); }, initStyles: function(targetEl) { var me = this, Element = Ext.Element, margin = me.margin, border = me.border, cls = me.cls, style = me.style, x = me.x, y = me.y, width, height; me.initPadding(targetEl); if (margin != null) { targetEl.setStyle('margin', this.unitizeBox((margin === true) ? 5 : margin)); } if (border != null) { me.setBorder(border, targetEl); } if (cls && cls != me.initialCls) { targetEl.addCls(cls); me.cls = me.initialCls = null; } if (style && style != me.initialStyle) { targetEl.setStyle(style); me.style = me.initialStyle = null; } if (x != null) { targetEl.setStyle(me.horizontalPosProp, (typeof x == 'number') ? (x + 'px') : x); } if (y != null) { targetEl.setStyle('top', (typeof y == 'number') ? (y + 'px') : y); } if (!me.ownerCt || me.floating) { if (Ext.scopeCss) { targetEl.addCls(me.rootCls); } if (Ext.isBorderBox) { targetEl.addCls(me.borderBoxCls); } } if (!me.getFrameInfo()) { width = me.width; height = me.height; if (width != null) { if (typeof width === 'number') { if (Ext.isBorderBox) { targetEl.setStyle('width', width + 'px'); } } else { targetEl.setStyle('width', width); } } if (height != null) { if (typeof height === 'number') { if (Ext.isBorderBox) { targetEl.setStyle('height', height + 'px'); } } else { targetEl.setStyle('height', height); } } } }, initPadding: function(targetEl) { var me = this, padding = me.padding; if (padding != null) { if (me.layout && me.layout.managePadding && me.contentPaddingProperty === 'padding') { targetEl.setStyle('padding', 0); } else { targetEl.setStyle('padding', this.unitizeBox((padding === true) ? 5 : padding)); } } }, parseBox: function(box) { return Ext.dom.Element.parseBox(box); }, unitizeBox: function(box) { return Ext.dom.Element.unitizeBox(box); }, setMargin: function(margin, preventLayout) { var me = this; if (me.rendered) { if (!margin && margin !== 0) { margin = ''; } else { if (margin === true) { margin = 5; } margin = this.unitizeBox(margin); } me.getTargetEl().setStyle('margin', margin); if (!preventLayout) { me.updateLayout(); } } else { me.margin = margin; } }, initEvents : function() { var me = this, afterRenderEvents = me.afterRenderEvents, afterRenderEvent, el, property, index, len; if (afterRenderEvents) { for (property in afterRenderEvents) { el = me[property]; if (el && el.on) { afterRenderEvent = afterRenderEvents[property]; for (index = 0, len = afterRenderEvent.length ; index < len ; ++index) { me.mon(el, afterRenderEvent[index]); } } } } me.addFocusListener(); }, addFocusListener: function() { var me = this, focusEl = me.getFocusEl(), needsTabIndex; if (focusEl) { if (focusEl.isComponent) { return focusEl.addFocusListener(); } needsTabIndex = focusEl.needsTabIndex(); if (!me.focusListenerAdded && (!needsTabIndex || Ext.FocusManager.enabled)) { if (needsTabIndex) { focusEl.dom.tabIndex = -1; } focusEl.on({ focus: me.onFocus, blur: me.onBlur, scope: me }); me.focusListenerAdded = true; } } }, getFocusEl: Ext.emptyFn, isFocusable: function() { var me = this, focusEl; if ((me.focusable !== false) && (focusEl = me.getFocusEl()) && me.rendered && !me.destroying && !me.isDestroyed && !me.disabled && me.isVisible(true)) { return focusEl.isFocusable(true); } }, beforeFocus: Ext.emptyFn, onFocus: function(e) { var me = this, focusCls = me.focusCls, focusEl = me.getFocusEl(); if (!me.disabled) { me.beforeFocus(e); if (focusCls && focusEl) { focusEl.addCls(me.addClsWithUI(focusCls, true)); } if (!me.hasFocus) { me.hasFocus = true; me.fireEvent('focus', me, e); } } }, beforeBlur : Ext.emptyFn, onBlur : function(e) { var me = this, focusCls = me.focusCls, focusEl = me.getFocusEl(); if (me.destroying) { return; } me.beforeBlur(e); if (focusCls && focusEl) { focusEl.removeCls(me.removeClsWithUI(focusCls, true)); } if (me.validateOnBlur) { me.validate(); } me.hasFocus = false; me.fireEvent('blur', me, e); me.postBlur(e); }, postBlur : Ext.emptyFn, is: function(selector) { return Ext.ComponentQuery.is(this, selector); }, up: function (selector, limit) { var result = this.getRefOwner(), limitSelector = typeof limit === 'string', limitCount = typeof limit === 'number', limitComponent = limit && limit.isComponent, steps = 0; if (selector) { for (; result; result = result.getRefOwner()) { steps++; if (selector.isComponent) { if (result === selector) { return result; } } else { if (Ext.ComponentQuery.is(result, selector)) { return result; } } if (limitSelector && result.is(limit)) { return; } if (limitCount && steps === limit) { return; } if (limitComponent && result === limit) { return; } } } return result; }, nextSibling: function(selector) { var o = this.ownerCt, it, last, idx, c; if (o) { it = o.items; idx = it.indexOf(this) + 1; if (idx) { if (selector) { for (last = it.getCount(); idx < last; idx++) { if ((c = it.getAt(idx)).is(selector)) { return c; } } } else { if (idx < it.getCount()) { return it.getAt(idx); } } } } return null; }, previousSibling: function(selector) { var o = this.ownerCt, it, idx, c; if (o) { it = o.items; idx = it.indexOf(this); if (idx != -1) { if (selector) { for (--idx; idx >= 0; idx--) { if ((c = it.getAt(idx)).is(selector)) { return c; } } } else { if (idx) { return it.getAt(--idx); } } } } return null; }, previousNode: function(selector, includeSelf) { var node = this, ownerCt = node.ownerCt, result, it, i, sib; if (includeSelf && node.is(selector)) { return node; } if (ownerCt) { for (it = ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) { sib = it[i]; if (sib.query) { result = sib.query(selector); result = result[result.length - 1]; if (result) { return result; } } if (sib.is(selector)) { return sib; } } return ownerCt.previousNode(selector, true); } return null; }, nextNode: function(selector, includeSelf) { var node = this, ownerCt = node.ownerCt, result, it, len, i, sib; if (includeSelf && node.is(selector)) { return node; } if (ownerCt) { for (it = ownerCt.items.items, i = Ext.Array.indexOf(it, node) + 1, len = it.length; i < len; i++) { sib = it[i]; if (sib.is(selector)) { return sib; } if (sib.down) { result = sib.down(selector); if (result) { return result; } } } return ownerCt.nextNode(selector); } return null; }, getId : function() { return this.id || (this.id = 'ext-comp-' + (this.getAutoId())); }, getItemId : function() { return this.itemId || this.id; }, getEl : function() { return this.el; }, getTargetEl: function() { return this.frameBody || this.el; }, getOverflowEl: function(){ return this.getTargetEl(); }, getOverflowStyle: function() { var me = this, result = null, auto = me.autoScroll, ox, oy, overflowStyle; if (typeof auto === 'boolean') { result = { overflow: overflowStyle = (auto ? 'auto' : '') }; me.scrollFlags = { overflowX: overflowStyle, overflowY: overflowStyle, x: auto, y: auto, both: auto }; } else { ox = me.overflowX; oy = me.overflowY; if (ox !== undefined || oy !== undefined) { if (ox && ox === true) { ox = 'auto'; } if (oy && oy === true) { oy = 'auto'; } result = { 'overflowX': ox = ox || '', 'overflowY': oy = oy || '' }; me.scrollFlags = { overflowX: ox, overflowY: oy, x: ox = (ox === 'auto' || ox === 'scroll'), y: oy = (oy === 'auto' || oy === 'scroll'), both: ox && oy }; } else { me.scrollFlags = { overflowX: '', overflowY: '', x: false, y: false, both: false }; } } if (result && Ext.isIE7m) { result.position = 'relative'; } return result; }, isXType: function(xtype, shallow) { if (shallow) { return this.xtype === xtype; } else { return this.xtypesMap[xtype]; } }, getXTypes: function() { var self = this.self, xtypes, parentPrototype, parentXtypes; if (!self.xtypes) { xtypes = []; parentPrototype = this; while (parentPrototype) { parentXtypes = parentPrototype.xtypes; if (parentXtypes !== undefined) { xtypes.unshift.apply(xtypes, parentXtypes); } parentPrototype = parentPrototype.superclass; } self.xtypeChain = xtypes; self.xtypes = xtypes.join('/'); } return self.xtypes; }, update : function(htmlOrData, loadScripts, cb) { var me = this, isData = (me.tpl && !Ext.isString(htmlOrData)), el; if (isData) { me.data = htmlOrData; } else { me.html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData; } if (me.rendered) { el = me.isContainer ? me.layout.getRenderTarget() : me.getTargetEl(); if (isData) { me.tpl[me.tplWriteMode](el, htmlOrData || {}); } else { el.update(me.html, loadScripts, cb); } me.updateLayout(); } }, setVisible : function(visible) { return this[visible ? 'show': 'hide'](); }, isVisible: function(deep) { var me = this, hidden; if (me.hidden || !me.rendered || me.isDestroyed) { hidden = true; } else if (deep) { hidden = me.isHierarchicallyHidden(); } return !hidden; }, isHierarchicallyHidden: function() { var child = this, hidden = false, parent, parentHierarchyState; for (; (parent = child.ownerCt || child.floatParent); child = parent) { parentHierarchyState = parent.getHierarchyState(); if (parentHierarchyState.hidden) { hidden = true; break; } if (child.getHierarchyState().collapseImmune) { if (parent.collapsed && !child.collapseImmune) { hidden = true; break; } } else { hidden = !!parentHierarchyState.collapsed; break; } } return hidden; }, onBoxReady: function(width, height) { var me = this; if (me.disableOnBoxReady) { me.onDisable(); } else if (me.enableOnBoxReady) { me.onEnable(); } if (me.resizable) { me.initResizable(me.resizable); } if (me.draggable) { me.initDraggable(); } if (me.hasListeners.boxready) { me.fireEvent('boxready', me, width, height); } }, enable: function(silent) { var me = this; delete me.disableOnBoxReady; me.removeCls(me.disabledCls); if (me.rendered) { me.onEnable(); } else { me.enableOnBoxReady = true; } me.disabled = false; delete me.resetDisable; if (silent !== true) { me.fireEvent('enable', me); } return me; }, disable: function(silent) { var me = this; delete me.enableOnBoxReady; me.addCls(me.disabledCls); if (me.rendered) { me.onDisable(); } else { me.disableOnBoxReady = true; } me.disabled = true; if (silent !== true) { delete me.resetDisable; me.fireEvent('disable', me); } return me; }, onEnable: function() { if (this.maskOnDisable) { this.el.dom.disabled = false; this.unmask(); } }, onDisable : function() { var me = this, focusCls = me.focusCls, focusEl = me.getFocusEl(); if (focusCls && focusEl) { focusEl.removeCls(me.removeClsWithUI(focusCls, true)); } if (me.maskOnDisable) { me.el.dom.disabled = true; me.mask(); } }, mask: function (msg, msgCls, elHeight) { var box = this.lastBox, target = this.getMaskTarget(); if (box) { elHeight = box.height; } target.mask(msg, msgCls, elHeight); }, unmask: function() { this.getMaskTarget().unmask(); }, getMaskTarget: function(){ return this.el; }, isDisabled : function() { return this.disabled; }, setDisabled : function(disabled) { return this[disabled ? 'disable': 'enable'](); }, isHidden : function() { return this.hidden; }, addCls : function(cls) { var me = this, el = me.rendered ? me.el : me.protoEl; el.addCls.apply(el, arguments); return me; }, addClass : function() { return this.addCls.apply(this, arguments); }, hasCls: function (cls) { var me = this, el = me.rendered ? me.el : me.protoEl; return el.hasCls.apply(el, arguments); }, removeCls : function(cls) { var me = this, el = me.rendered ? me.el : me.protoEl; el.removeCls.apply(el, arguments); return me; }, addOverCls: function() { var me = this; if (!me.disabled) { me.el.addCls(me.overCls); } }, removeOverCls: function() { this.el.removeCls(this.overCls); }, addListener : function(element, listeners, scope, options) { var me = this, fn, option; if (Ext.isString(element) && (Ext.isObject(listeners) || options && options.element)) { if (options.element) { fn = listeners; listeners = {}; listeners[element] = fn; element = options.element; if (scope) { listeners.scope = scope; } for (option in options) { if (options.hasOwnProperty(option)) { if (me.eventOptionsRe.test(option)) { listeners[option] = options[option]; } } } } if (me[element] && me[element].on) { me.mon(me[element], listeners); } else { me.afterRenderEvents = me.afterRenderEvents || {}; if (!me.afterRenderEvents[element]) { me.afterRenderEvents[element] = []; } me.afterRenderEvents[element].push(listeners); } return; } return me.mixins.observable.addListener.apply(me, arguments); }, removeManagedListenerItem: function(isClear, managedListener, item, ename, fn, scope){ var me = this, element = managedListener.options ? managedListener.options.element : null; if (element) { element = me[element]; if (element && element.un) { if (isClear || (managedListener.item === item && managedListener.ename === ename && (!fn || managedListener.fn === fn) && (!scope || managedListener.scope === scope))) { element.un(managedListener.ename, managedListener.fn, managedListener.scope); if (!isClear) { Ext.Array.remove(me.managedListeners, managedListener); } } } } else { return me.mixins.observable.removeManagedListenerItem.apply(me, arguments); } }, getBubbleTarget : function() { return this.ownerCt; }, isFloating : function() { return this.floating; }, isDraggable : function() { return !!this.draggable; }, isDroppable : function() { return !!this.droppable; }, onAdded : function(container, pos) { var me = this; me.ownerCt = container; if (me.hierarchyState) { me.hierarchyState.invalid = true; delete me.hierarchyState; } if (me.hasListeners.added) { me.fireEvent('added', me, container, pos); } }, onRemoved : function(destroying) { var me = this; if (me.hasListeners.removed) { me.fireEvent('removed', me, me.ownerCt); } delete me.ownerCt; delete me.ownerLayout; }, beforeDestroy : Ext.emptyFn, onResize: function(width, height, oldWidth, oldHeight) { var me = this; if (me.floating && me.constrain) { me.doConstrain(); } if (me.hasListeners.resize) { me.fireEvent('resize', me, width, height, oldWidth, oldHeight); } }, setSize : function(width, height) { var me = this; if (width && typeof width == 'object') { height = width.height; width = width.width; } if (typeof width == 'number') { me.width = Ext.Number.constrain(width, me.minWidth, me.maxWidth); } else if (width === null) { delete me.width; } if (typeof height == 'number') { me.height = Ext.Number.constrain(height, me.minHeight, me.maxHeight); } else if (height === null) { delete me.height; } if (me.rendered && me.isVisible()) { me.updateLayout({ isRoot: false }); } return me; }, isLayoutRoot: function() { var me = this, ownerLayout = me.ownerLayout; if (!ownerLayout || me._isLayoutRoot || me.floating) { return true; } return ownerLayout.isItemLayoutRoot(me); }, isLayoutSuspended: function () { var comp = this, ownerLayout; while (comp) { if (comp.layoutSuspendCount || comp.suspendLayout) { return true; } ownerLayout = comp.ownerLayout; if (!ownerLayout) { break; } comp = ownerLayout.owner; } return false; }, updateLayout: function (options) { var me = this, defer, lastBox = me.lastBox, isRoot = options && options.isRoot; if (lastBox) { lastBox.invalid = true; } if (!me.rendered || me.layoutSuspendCount || me.suspendLayout) { return; } if (me.hidden) { Ext.AbstractComponent.cancelLayout(me); } else if (typeof isRoot != 'boolean') { isRoot = me.isLayoutRoot(); } if (isRoot || !me.ownerLayout || !me.ownerLayout.onContentChange(me)) { if (!me.isLayoutSuspended()) { defer = (options && options.hasOwnProperty('defer')) ? options.defer : me.deferLayouts; Ext.AbstractComponent.updateLayout(me, defer); } } }, getSizeModel: function (ownerCtSizeModel) { var me = this, models = Ext.layout.SizeModel, ownerContext = me.componentLayout.ownerContext, width = me.width, height = me.height, typeofWidth, typeofHeight, hasPixelWidth, hasPixelHeight, heightModel, ownerLayout, policy, shrinkWrap, topLevel, widthModel; if (ownerContext) { widthModel = ownerContext.widthModel; heightModel = ownerContext.heightModel; } if (!widthModel || !heightModel) { hasPixelWidth = ((typeofWidth = typeof width) == 'number'); hasPixelHeight = ((typeofHeight = typeof height) == 'number'); topLevel = me.floating || !(ownerLayout = me.ownerLayout); if (topLevel) { policy = Ext.layout.Layout.prototype.autoSizePolicy; shrinkWrap = me.floating ? 3 : me.shrinkWrap; if (hasPixelWidth) { widthModel = models.configured; } if (hasPixelHeight) { heightModel = models.configured; } } else { policy = ownerLayout.getItemSizePolicy(me, ownerCtSizeModel); shrinkWrap = ownerLayout.isItemShrinkWrap(me); } if (ownerContext) { ownerContext.ownerSizePolicy = policy; } shrinkWrap = (shrinkWrap === true) ? 3 : (shrinkWrap || 0); if (topLevel && shrinkWrap) { if (width && typeofWidth == 'string') { shrinkWrap &= 2; } if (height && typeofHeight == 'string') { shrinkWrap &= 1; } } if (shrinkWrap !== 3) { if (!ownerCtSizeModel) { ownerCtSizeModel = me.ownerCt && me.ownerCt.getSizeModel(); } if (ownerCtSizeModel) { shrinkWrap |= (ownerCtSizeModel.width.shrinkWrap ? 1 : 0) | (ownerCtSizeModel.height.shrinkWrap ? 2 : 0); } } if (!widthModel) { if (!policy.setsWidth) { if (hasPixelWidth) { widthModel = models.configured; } else { widthModel = (shrinkWrap & 1) ? models.shrinkWrap : models.natural; } } else if (policy.readsWidth) { if (hasPixelWidth) { widthModel = models.calculatedFromConfigured; } else { widthModel = (shrinkWrap & 1) ? models.calculatedFromShrinkWrap : models.calculatedFromNatural; } } else { widthModel = models.calculated; } } if (!heightModel) { if (!policy.setsHeight) { if (hasPixelHeight) { heightModel = models.configured; } else { heightModel = (shrinkWrap & 2) ? models.shrinkWrap : models.natural; } } else if (policy.readsHeight) { if (hasPixelHeight) { heightModel = models.calculatedFromConfigured; } else { heightModel = (shrinkWrap & 2) ? models.calculatedFromShrinkWrap : models.calculatedFromNatural; } } else { heightModel = models.calculated; } } } return widthModel.pairsByHeightOrdinal[heightModel.ordinal]; }, isDescendant: function(ancestor) { if (ancestor.isContainer) { for (var c = this.ownerCt; c; c = c.ownerCt) { if (c === ancestor) { return true; } } } return false; }, doComponentLayout : function() { this.updateLayout(); return this; }, forceComponentLayout: function () { this.updateLayout(); }, setComponentLayout : function(layout) { var currentLayout = this.componentLayout; if (currentLayout && currentLayout.isLayout && currentLayout != layout) { currentLayout.setOwner(null); } this.componentLayout = layout; layout.setOwner(this); }, getComponentLayout : function() { var me = this; if (!me.componentLayout || !me.componentLayout.isLayout) { me.setComponentLayout(Ext.layout.Layout.create(me.componentLayout, 'autocomponent')); } return me.componentLayout; }, afterComponentLayout: function(width, height, oldWidth, oldHeight) { var me = this; if (++me.componentLayoutCounter === 1) { me.afterFirstLayout(width, height); } if (width !== oldWidth || height !== oldHeight) { me.onResize(width, height, oldWidth, oldHeight); } }, beforeComponentLayout: function(width, height) { return true; }, setPosition: function(x, y, animate) { var me = this, pos = me.beforeSetPosition.apply(me, arguments); if (pos && me.rendered) { x = pos.x; y = pos.y; if (animate) { if (x !== me.getLocalX() || y !== me.getLocalY()) { me.stopAnimation(); me.animate(Ext.apply({ duration: 1000, listeners: { afteranimate: Ext.Function.bind(me.afterSetPosition, me, [x, y]) }, to: { left: x, top: y } }, animate)); } } else { me.setLocalXY(x, y); me.afterSetPosition(x, y); } } return me; }, beforeSetPosition: function (x, y, animate) { var pos, x0; if (x) { if (Ext.isNumber(x0 = x[0])) { animate = y; y = x[1]; x = x0; } else if ((x0 = x.x) !== undefined) { animate = y; y = x.y; x = x0; } } if (this.constrain || this.constrainHeader) { pos = this.calculateConstrainedPosition(null, [x, y], true); if (pos) { x = pos[0]; y = pos[1]; } } pos = { x : this.x = x, y : this.y = y, anim: animate, hasX: x !== undefined, hasY: y !== undefined }; return (pos.hasX || pos.hasY) ? pos : null; }, afterSetPosition: function(x, y) { var me = this; me.onPosition(x, y); if (me.hasListeners.move) { me.fireEvent('move', me, x, y); } }, onPosition: Ext.emptyFn, setWidth : function(width) { return this.setSize(width); }, setHeight : function(height) { return this.setSize(undefined, height); }, getSize : function(contentSize) { return this.el.getSize(contentSize); }, getWidth : function() { return this.el.getWidth(); }, getHeight : function() { return this.el.getHeight(); }, getLoader: function(){ var me = this, autoLoad = me.autoLoad ? (Ext.isObject(me.autoLoad) ? me.autoLoad : {url: me.autoLoad}) : null, loader = me.loader || autoLoad; if (loader) { if (!loader.isLoader) { me.loader = new Ext.ComponentLoader(Ext.apply({ target: me, autoLoad: autoLoad }, loader)); } else { loader.setTarget(me); } return me.loader; } return null; }, setDocked : function(dock, layoutParent) { var me = this; me.dock = dock; if (layoutParent && me.ownerCt && me.rendered) { me.ownerCt.updateLayout(); } return me; }, setBorder: function(border, targetEl) { var me = this, initial = !!targetEl; if (me.rendered || initial) { if (!initial) { targetEl = me.el; } if (!border) { border = 0; } else if (border === true) { border = '1px'; } else { border = this.unitizeBox(border); } targetEl.setStyle('border-width', border); if (!initial) { me.updateLayout(); } } me.border = border; }, onDestroy : function() { var me = this; if (me.monitorResize && Ext.EventManager.resizeEvent) { Ext.EventManager.resizeEvent.removeListener(me.setSize, me); } Ext.destroy( me.componentLayout, me.loadMask, me.floatingDescendants ); }, destroy : function() { var me = this, selectors = me.renderSelectors, selector, el; if (!me.isDestroyed) { if (!me.hasListeners.beforedestroy || me.fireEvent('beforedestroy', me) !== false) { me.destroying = true; me.beforeDestroy(); if (me.floating) { delete me.floatParent; if (me.zIndexManager) { me.zIndexManager.unregister(me); } } else if (me.ownerCt && me.ownerCt.remove) { me.ownerCt.remove(me, false); } me.stopAnimation(); me.onDestroy(); Ext.destroy(me.plugins); if (me.hasListeners.destroy) { me.fireEvent('destroy', me); } Ext.ComponentManager.unregister(me); me.mixins.state.destroy.call(me); me.clearListeners(); if (me.rendered) { if (!me.preserveElOnDestroy) { me.el.remove(); } me.mixins.elementCt.destroy.call(me); if (selectors) { for (selector in selectors) { if (selectors.hasOwnProperty(selector)) { el = me[selector]; if (el) { delete me[selector]; el.remove(); } } } } delete me.el; delete me.frameBody; delete me.rendered; } me.destroying = false; me.isDestroyed = true; } } }, isDescendantOf: function(container) { return !!this.findParentBy(function(p){ return p === container; }); }, getHierarchyState: function (inner) { var me = this, hierarchyState = (inner && me.hierarchyStateInner) || me.hierarchyState, ownerCt = me.ownerCt, parent, layout, hierarchyStateInner, getInner; if (!hierarchyState || hierarchyState.invalid) { parent = me.getRefOwner(); if (ownerCt) { getInner = me.ownerLayout === ownerCt.layout; } me.hierarchyState = hierarchyState = Ext.Object.chain(parent ? parent.getHierarchyState(getInner) : Ext.rootHierarchyState); me.initHierarchyState(hierarchyState); if ((layout = me.componentLayout).initHierarchyState) { layout.initHierarchyState(hierarchyState); } if (me.isContainer) { me.hierarchyStateInner = hierarchyStateInner = Ext.Object.chain(hierarchyState); layout = me.layout; if (layout && layout.initHierarchyState) { layout.initHierarchyState(hierarchyStateInner, hierarchyState); } if (inner) { hierarchyState = hierarchyStateInner; } } } return hierarchyState; }, initHierarchyState: function(hierarchyState) { var me = this; if (me.collapsed) { hierarchyState.collapsed = true; } if (me.hidden) { hierarchyState.hidden = true; } if (me.collapseImmune) { hierarchyState.collapseImmune = true; } }, getAnchorToXY: function(el, anchor, local, mySize) { return el.getAnchorXY(anchor, local, mySize); }, getBorderPadding: function() { return this.el.getBorderPadding(); }, getLocalX: function() { return this.el.getLocalX(); }, getLocalXY: function() { return this.el.getLocalXY(); }, getLocalY: function() { return this.el.getLocalY(); }, getX: function() { return this.el.getX(); }, getXY: function() { return this.el.getXY(); }, getY: function() { return this.el.getY(); }, setLocalX: function(x) { this.el.setLocalX(x); }, setLocalXY: function(x, y) { this.el.setLocalXY(x, y); }, setLocalY: function(y) { this.el.setLocalY(y); }, setX: function(x, animate) { this.el.setX(x, animate); }, setXY: function(xy, animate) { this.el.setXY(xy, animate); }, setY: function(y, animate) { this.el.setY(y, animate); } }, function() { var AbstractComponent = this; AbstractComponent.createAlias({ on: 'addListener', prev: 'previousSibling', next: 'nextSibling' }); Ext.resumeLayouts = function (flush) { AbstractComponent.resumeLayouts(flush); }; Ext.suspendLayouts = function () { AbstractComponent.suspendLayouts(); }; Ext.batchLayouts = function(fn, scope) { AbstractComponent.suspendLayouts(); fn.call(scope); AbstractComponent.resumeLayouts(true); }; }); Ext.define('Ext.AbstractPlugin', { disabled: false, isPlugin: true, constructor: function(config) { this.pluginConfig = config; Ext.apply(this, config); }, clonePlugin: function(overrideCfg) { return new this.self(Ext.apply({}, overrideCfg, this.pluginConfig)); }, setCmp: function(cmp) { this.cmp = cmp; }, getCmp: function() { return this.cmp; }, init: Ext.emptyFn, destroy: Ext.emptyFn, enable: function() { this.disabled = false; }, disable: function() { this.disabled = true; }, onClassExtended: function(cls, data, hooks) { var alias = data.alias; if (alias && !data.ptype) { if (Ext.isArray(alias)) { alias = alias[0]; } cls.prototype.ptype = alias.split('plugin.')[1]; } } }); Ext.define('Ext.Action', { constructor : function(config){ this.initialConfig = config; this.itemId = config.itemId = (config.itemId || config.id || Ext.id()); this.items = []; }, isAction : true, setText : function(text){ this.initialConfig.text = text; this.callEach('setText', [text]); }, getText : function(){ return this.initialConfig.text; }, setIconCls : function(cls){ this.initialConfig.iconCls = cls; this.callEach('setIconCls', [cls]); }, getIconCls : function(){ return this.initialConfig.iconCls; }, setDisabled : function(v){ this.initialConfig.disabled = v; this.callEach('setDisabled', [v]); }, enable : function(){ this.setDisabled(false); }, disable : function(){ this.setDisabled(true); }, isDisabled : function(){ return this.initialConfig.disabled; }, setHidden : function(v){ this.initialConfig.hidden = v; this.callEach('setVisible', [!v]); }, show : function(){ this.setHidden(false); }, hide : function(){ this.setHidden(true); }, isHidden : function(){ return this.initialConfig.hidden; }, setHandler : function(fn, scope){ this.initialConfig.handler = fn; this.initialConfig.scope = scope; this.callEach('setHandler', [fn, scope]); }, each : function(fn, scope){ Ext.each(this.items, fn, scope); }, callEach : function(fnName, args){ var items = this.items, i = 0, len = items.length, item; Ext.suspendLayouts(); for(; i < len; i++){ item = items[i]; item[fnName].apply(item, args); } Ext.resumeLayouts(true); }, addComponent : function(comp){ this.items.push(comp); comp.on('destroy', this.removeComponent, this); }, removeComponent : function(comp){ Ext.Array.remove(this.items, comp); }, execute : function(){ this.initialConfig.handler.apply(this.initialConfig.scope || Ext.global, arguments); } }); Ext.define('Ext.data.flash.BinaryXhr', { statics: { flashPluginActivated: function() { Ext.data.flash.BinaryXhr.flashPluginActive = true; Ext.data.flash.BinaryXhr.flashPlugin = document.getElementById("ext-flash-polyfill"); Ext.globalEvents.fireEvent("flashready"); }, flashPluginActive: false, flashPluginInjected: false, connectionIndex: 1, liveConnections: {}, flashPlugin: null, onFlashStateChange: function(javascriptId, state, data) { var connection; connection = this.liveConnections[Number(javascriptId)]; if (connection) { connection.onFlashStateChange(state, data); } }, registerConnection: function(conn) { var i = this.connectionIndex; this.conectionIndex = this.connectionIndex + 1; this.liveConnections[i] = conn; return i; }, injectFlashPlugin: function() { var me = this, flashLoaderPath, flashObjectPath; me.flashPolyfillEl = Ext.getBody().appendChild({ id: 'ext-flash-polyfill', cn: [ { tag: 'p', html: 'To view this page ensure that Adobe Flash Player version 11.1.0 or greater is installed.' }, { tag: 'a', href: 'http://www.adobe.com/go/getflashplayer', cn: [ { tag: 'img', src: window.location.protocol + '//www.adobe.com/images/shared/download_buttons/get_flash_player.gif', alt: 'Get Adobe Flash player' } ] } ] }); flashLoaderPath = [Ext.Loader.getPath('Ext.data.Connection'), '../../../plugins/flash/swfobject.js'].join('/'); flashObjectPath = "/plugins/flash/FlashPlugin.swf"; if (Ext.flashPluginPath) { flashObjectPath = Ext.flashPluginPath; } Ext.Loader.loadScript({ url:flashLoaderPath, onLoad: function() { var swfVersionStr = "11.4.0"; var xiSwfUrlStr = "playerProductInstall.swf"; var flashvars = {}; var params = {}; params.quality = "high"; params.bgcolor = "#ffffff"; params.allowscriptaccess = "sameDomain"; params.allowfullscreen = "true"; var attributes = {}; attributes.id = "ext-flash-polyfill"; attributes.name = "polyfill"; attributes.align = "middle"; swfobject.embedSWF( flashObjectPath, "ext-flash-polyfill", "0", "0", swfVersionStr, xiSwfUrlStr, flashvars, params, attributes); }, onError: function() { }, scope: me }); Ext.globalEvents.addEvents("flashready"); Ext.data.flash.BinaryXhr.flashPluginInjected = true; } }, readyState: 0, status: 0, statusText: "", responseBytes: null, javascriptId: null, constructor: function (config) { if (!Ext.data.flash.BinaryXhr.flashPluginInjected) { Ext.data.flash.BinaryXhr.injectFlashPlugin(); } var me = this; Ext.apply(me, config); me.requestHeaders = {}; }, abort: function () { var me = this; if (me.readyState == 4) { return; } me.aborted = true; if (!Ext.data.flash.BinaryXhr.flashPluginActive) { Ext.globalEvents.removeListener("flashready", me.onFlashReady, me); return; } Ext.data.flash.BinaryXhr.flashPlugin.abortRequest(me.javascriptId); delete Ext.data.flash.BinaryXhr.liveConnections[me.javascriptId]; }, getAllResponseHeaders: function () { var headers = []; Ext.Object.each(this.responseHeaders, function (name, value) { headers.push(name + ': ' + value); }); return headers.join('\x0d\x0a'); }, getResponseHeader: function (header) { var headers = this.responseHeaders; return (headers && headers[header]) || null; }, open: function (method, url, async, user, password) { var me = this; me.method = method; me.url = url; me.async = async !== false; me.user = user; me.password = password; }, overrideMimeType: function (mimeType) { this.mimeType = mimeType; }, send: function (body) { var me = this; me.body = body; if (!Ext.data.flash.BinaryXhr.flashPluginActive) { Ext.globalEvents.addListener("flashready", me.onFlashReady, me); } else { this.onFlashReady(); } }, onFlashReady: function() { var me = this, req, status; me.javascriptId = Ext.data.flash.BinaryXhr.registerConnection(me); req = { method: me.method, url: me.url, user: me.user, password: me.password, mimeType: me.mimeType, requestHeaders: me.requestHeaders, body: me.body, javascriptId: me.javascriptId }; status = Ext.data.flash.BinaryXhr.flashPlugin.postBinary(req); }, setReadyState: function (state) { var me = this; if (me.readyState != state) { me.readyState = state; me.onreadystatechange(); } }, setRequestHeader: function (header, value) { this.requestHeaders[header] = value; }, onreadystatechange: Ext.emptyFn, parseData: function (data) { var me = this; this.status = data.status || 0; me.responseHeaders = {}; if (me.mimeType) { me.responseHeaders["content-type"] = me.mimeType; } if (data.reason == "complete") { this.responseBytes = data.data; me.responseHeaders["content-length"] = data.data.length; } else if (data.reason == "error" || data.reason == "securityError") { this.statusText = data.text; me.responseHeaders["content-length"] = 0; } }, onFlashStateChange: function(state, data) { var me = this; if (state == 4) { me.parseData(data); delete Ext.data.flash.BinaryXhr.liveConnections[me.javascriptId]; } me.setReadyState(state); } }); Ext.define('Ext.data.Connection', { mixins: { observable: Ext.util.Observable }, statics: { requestId: 0 }, url: null, async: true, method: null, username: '', password: '', disableCaching: true, withCredentials: false, binary: false, cors: false, isXdr: false, defaultXdrContentType: 'text/plain', disableCachingParam: '_dc', timeout : 30000, useDefaultHeader : true, defaultPostHeader : 'application/x-www-form-urlencoded; charset=UTF-8', useDefaultXhrHeader : true, defaultXhrHeader : 'XMLHttpRequest', constructor : function(config) { config = config || {}; Ext.apply(this, config); this.requests = {}; this.mixins.observable.constructor.call(this); }, request : function(options) { options = options || {}; var me = this, scope = options.scope || window, username = options.username || me.username, password = options.password || me.password || '', async, requestOptions, request, headers, xhr; if (me.fireEvent('beforerequest', me, options) !== false) { requestOptions = me.setOptions(options, scope); if (me.isFormUpload(options)) { me.upload(options.form, requestOptions.url, requestOptions.data, options); return null; } if (options.autoAbort || me.autoAbort) { me.abort(); } async = options.async !== false ? (options.async || me.async) : false; xhr = me.openRequest(options, requestOptions, async, username, password); if (!me.isXdr) { headers = me.setupHeaders(xhr, options, requestOptions.data, requestOptions.params); } request = { id: ++Ext.data.Connection.requestId, xhr: xhr, headers: headers, options: options, async: async, binary: options.binary || me.binary, timeout: setTimeout(function() { request.timedout = true; me.abort(request); }, options.timeout || me.timeout) }; me.requests[request.id] = request; me.latestId = request.id; if (async) { if (!me.isXdr) { xhr.onreadystatechange = Ext.Function.bind(me.onStateChange, me, [request]); } } if (me.isXdr) { me.processXdrRequest(request, xhr); } xhr.send(requestOptions.data); if (!async) { return me.onComplete(request); } return request; } else { Ext.callback(options.callback, options.scope, [options, undefined, undefined]); return null; } }, processXdrRequest: function(request, xhr) { var me = this; delete request.headers; request.contentType = request.options.contentType || me.defaultXdrContentType; xhr.onload = Ext.Function.bind(me.onStateChange, me, [request, true]); xhr.onerror = xhr.ontimeout = Ext.Function.bind(me.onStateChange, me, [request, false]); }, processXdrResponse: function(response, xhr) { response.getAllResponseHeaders = function () { return []; }; response.getResponseHeader = function () { return ''; }; response.contentType = xhr.contentType || this.defaultXdrContentType; }, upload: function(form, url, params, options) { form = Ext.getDom(form); options = options || {}; var id = Ext.id(), frame = document.createElement('iframe'), hiddens = [], encoding = 'multipart/form-data', buf = { target: form.target, method: form.method, encoding: form.encoding, enctype: form.enctype, action: form.action }, addField = function(name, value) { hiddenItem = document.createElement('input'); Ext.fly(hiddenItem).set({ type: 'hidden', value: value, name: name }); form.appendChild(hiddenItem); hiddens.push(hiddenItem); }, hiddenItem, obj, value, name, vLen, v, hLen, h; Ext.fly(frame).set({ id: id, name: id, cls: Ext.baseCSSPrefix + 'hide-display', src: Ext.SSL_SECURE_URL }); document.body.appendChild(frame); if (document.frames) { document.frames[id].name = id; } Ext.fly(form).set({ target: id, method: 'POST', enctype: encoding, encoding: encoding, action: url || buf.action }); if (params) { obj = Ext.Object.fromQueryString(params) || {}; for (name in obj) { if (obj.hasOwnProperty(name)) { value = obj[name]; if (Ext.isArray(value)) { vLen = value.length; for (v = 0; v < vLen; v++) { addField(name, value[v]); } } else { addField(name, value); } } } } Ext.fly(frame).on('load', Ext.Function.bind(this.onUploadComplete, this, [frame, options]), null, {single: !Ext.isOpera}); form.submit(); Ext.fly(form).set(buf); hLen = hiddens.length; for (h = 0; h < hLen; h++) { Ext.removeNode(hiddens[h]); } }, onUploadComplete: function(frame, options) { var me = this, response = { responseText: '', responseXML: null }, callback, success, doc, contentNode; try { doc = frame.contentWindow.document || frame.contentDocument || window.frames[frame.id].document; if (doc) { if (Ext.isOpera && doc.location == 'about:blank') { return; } if (doc.body) { if ((contentNode = doc.body.firstChild) && /pre/i.test(contentNode.tagName)) { response.responseText = contentNode.textContent; } else if ((contentNode = doc.getElementsByTagName('textarea')[0])) { response.responseText = contentNode.value; } else { response.responseText = doc.body.textContent || doc.body.innerText; } } response.responseXML = doc.XMLDocument || doc; callback = options.success; success = true; } } catch (e) { response.responseText = '{success:false,message:"' + Ext.String.trim(e.message || e.description) + '"}'; callback = options.failure; success = false; } me.fireEvent('requestcomplete', me, response, options); Ext.callback(callback, options.scope, [response, options]); Ext.callback(options.callback, options.scope, [options, success, response]); setTimeout(function() { Ext.removeNode(frame); }, 100); }, isFormUpload: function(options) { var form = this.getForm(options); if (form) { return (options.isUpload || (/multipart\/form-data/i).test(form.getAttribute('enctype'))); } return false; }, getForm: function(options) { return Ext.getDom(options.form) || null; }, setOptions: function(options, scope) { var me = this, params = options.params || {}, extraParams = me.extraParams, urlParams = options.urlParams, url = options.url || me.url, jsonData = options.jsonData, method, disableCache, data; if (Ext.isFunction(params)) { params = params.call(scope, options); } if (Ext.isFunction(url)) { url = url.call(scope, options); } url = this.setupUrl(options, url); data = options.rawData || options.binaryData || options.xmlData || jsonData || null; if (jsonData && !Ext.isPrimitive(jsonData)) { data = Ext.encode(data); } if (options.binaryData) { if (me.nativeBinaryPostSupport()) { data = (new Uint8Array(options.binaryData)); if ((Ext.isChrome && Ext.chromeVersion < 22) || Ext.isSafari || Ext.isGecko) { data = data.buffer; } } } if (Ext.isObject(params)) { params = Ext.Object.toQueryString(params); } if (Ext.isObject(extraParams)) { extraParams = Ext.Object.toQueryString(extraParams); } params = params + ((extraParams) ? ((params) ? '&' : '') + extraParams : ''); urlParams = Ext.isObject(urlParams) ? Ext.Object.toQueryString(urlParams) : urlParams; params = this.setupParams(options, params); method = (options.method || me.method || ((params || data) ? 'POST' : 'GET')).toUpperCase(); this.setupMethod(options, method); disableCache = options.disableCaching !== false ? (options.disableCaching || me.disableCaching) : false; if (method === 'GET' && disableCache) { url = Ext.urlAppend(url, (options.disableCachingParam || me.disableCachingParam) + '=' + (new Date().getTime())); } if ((method == 'GET' || data) && params) { url = Ext.urlAppend(url, params); params = null; } if (urlParams) { url = Ext.urlAppend(url, urlParams); } return { url: url, method: method, data: data || params || null }; }, setupUrl: function(options, url) { var form = this.getForm(options); if (form) { url = url || form.action; } return url; }, setupParams: function(options, params) { var form = this.getForm(options), serializedForm; if (form && !this.isFormUpload(options)) { serializedForm = Ext.Element.serializeForm(form); params = params ? (params + '&' + serializedForm) : serializedForm; } return params; }, setupMethod: function(options, method) { if (this.isFormUpload(options)) { return 'POST'; } return method; }, setupHeaders: function(xhr, options, data, params) { var me = this, headers = Ext.apply({}, options.headers || {}, me.defaultHeaders || {}), contentType = me.defaultPostHeader, jsonData = options.jsonData, xmlData = options.xmlData, type = 'Content-Type', key, header; if (!headers.hasOwnProperty(type) && (data || params)) { if (data) { if (options.rawData) { contentType = 'text/plain'; } else { if (xmlData && Ext.isDefined(xmlData)) { contentType = 'text/xml'; } else if (jsonData && Ext.isDefined(jsonData)) { contentType = 'application/json'; } } } headers[type] = contentType; } if (me.useDefaultXhrHeader && !headers['X-Requested-With']) { headers['X-Requested-With'] = me.defaultXhrHeader; } if (headers[type] === undefined || headers[type] === null) { delete headers[type]; } try { for (key in headers) { if (headers.hasOwnProperty(key)) { header = headers[key]; xhr.setRequestHeader(key, header); } } } catch(e) { me.fireEvent('exception', key, header); } return headers; }, newRequest: function (options) { var me = this, xhr; if (options.binaryData) { if (me.nativeBinaryPostSupport()) { xhr = this.getXhrInstance(); } else { xhr = new Ext.data.flash.BinaryXhr(); } } else if ((options.cors || me.cors) && Ext.isIE && Ext.ieVersion <= 9) { xhr = me.getXdrInstance(); me.isXdr = true; } else { xhr = me.getXhrInstance(); } return xhr; }, openRequest: function (options, requestOptions, async, username, password) { var me = this, xhr = me.newRequest(options); if (username) { xhr.open(requestOptions.method, requestOptions.url, async, username, password); } else { if (me.isXdr) { xhr.open(requestOptions.method, requestOptions.url); } else { xhr.open(requestOptions.method, requestOptions.url, async); } } if (options.binary || me.binary) { if (window.Uint8Array) { xhr.responseType = 'arraybuffer'; } else if (xhr.overrideMimeType) { xhr.overrideMimeType('text\/plain; charset=x-user-defined'); } } if (options.withCredentials || me.withCredentials) { xhr.withCredentials = true; } return xhr; }, getXdrInstance: function() { var xdr; if (Ext.ieVersion >= 8) { xdr = new XDomainRequest(); } else { Ext.Error.raise({ msg: 'Your browser does not support CORS' }); } return xdr; }, getXhrInstance: (function() { var options = [function() { return new XMLHttpRequest(); }, function() { return new ActiveXObject('MSXML2.XMLHTTP.3.0'); }, function() { return new ActiveXObject('MSXML2.XMLHTTP'); }, function() { return new ActiveXObject('Microsoft.XMLHTTP'); }], i = 0, len = options.length, xhr; for (; i < len; ++i) { try { xhr = options[i]; xhr(); break; } catch(e) { } } return xhr; }()), isLoading : function(request) { if (!request) { request = this.getLatest(); } if (!(request && request.xhr)) { return false; } var state = request.xhr.readyState; return ((request.xhr instanceof Ext.data.flash.BinaryXhr) && state != 4) || !(state === 0 || state == 4); }, abort : function(request) { var me = this, xhr; if (!request) { request = me.getLatest(); } if (request && me.isLoading(request)) { xhr = request.xhr; try { xhr.onreadystatechange = null; } catch (e) { xhr.onreadystatechange = Ext.emptyFn; } xhr.abort(); me.clearTimeout(request); if (!request.timedout) { request.aborted = true; } me.onComplete(request); me.cleanup(request); } }, abortAll: function(){ var requests = this.requests, id; for (id in requests) { if (requests.hasOwnProperty(id)) { this.abort(requests[id]); } } }, getLatest: function(){ var id = this.latestId, request; if (id) { request = this.requests[id]; } return request || null; }, onStateChange : function(request, xdrResult) { var me = this; if ((request.xhr && request.xhr.readyState == 4) || me.isXdr) { me.clearTimeout(request); me.onComplete(request, xdrResult); me.cleanup(request); Ext.EventManager.idleEvent.fire(); } }, clearTimeout: function(request) { clearTimeout(request.timeout); delete request.timeout; }, cleanup: function(request) { request.xhr = null; delete request.xhr; }, onComplete : function(request, xdrResult) { var me = this, options = request.options, xhr, result, success, response; try { xhr = request.xhr; result = me.parseStatus(xhr.status); if (result.success) { result.success = xhr.readyState === 4; } } catch (e) { result = { success : false, isException : false }; } success = me.isXdr ? xdrResult : result.success; if (success) { response = me.createResponse(request); me.fireEvent('requestcomplete', me, response, options); Ext.callback(options.success, options.scope, [response, options]); } else { if (result.isException || request.aborted || request.timedout) { response = me.createException(request); } else { response = me.createResponse(request); } me.fireEvent('requestexception', me, response, options); Ext.callback(options.failure, options.scope, [response, options]); } Ext.callback(options.callback, options.scope, [options, success, response]); delete me.requests[request.id]; return response; }, parseStatus: function(status) { status = status == 1223 ? 204 : status; var success = (status >= 200 && status < 300) || status == 304, isException = false; if (!success) { switch (status) { case 12002: case 12029: case 12030: case 12031: case 12152: case 13030: isException = true; break; } } return { success: success, isException: isException }; }, createResponse : function(request) { var me = this, xhr = request.xhr, isXdr = me.isXdr, headers = {}, lines = isXdr ? [] : xhr.getAllResponseHeaders().replace(/\r\n/g, '\n').split('\n'), count = lines.length, line, index, key, response, byteArray; while (count--) { line = lines[count]; index = line.indexOf(':'); if (index >= 0) { key = line.substr(0, index).toLowerCase(); if (line.charAt(index + 1) == ' ') { ++index; } headers[key] = line.substr(index + 1); } } request.xhr = null; delete request.xhr; response = { request: request, requestId: request.id, status: xhr.status, statusText: xhr.statusText, getResponseHeader: function(header) { return headers[header.toLowerCase()]; }, getAllResponseHeaders: function() { return headers; } }; if (isXdr) { me.processXdrResponse(response, xhr); } if (request.binary) { response.responseBytes = me.getByteArray(xhr); } else { response.responseText = xhr.responseText; response.responseXML = xhr.responseXML; } xhr = null; return response; }, createException : function(request) { return { request : request, requestId : request.id, status : request.aborted ? -1 : 0, statusText : request.aborted ? 'transaction aborted' : 'communication failure', aborted: request.aborted, timedout: request.timedout }; }, getByteArray: function(xhr) { var response = xhr.response, responseBody = xhr.responseBody, byteArray, responseText, len, i; if (xhr instanceof Ext.data.flash.BinaryXhr) { byteArray = xhr.responseBytes; } else if (window.Uint8Array) { byteArray = response ? new Uint8Array(response) : []; } else if (Ext.isIE9p) { try { byteArray = new VBArray(responseBody).toArray(); } catch(e) { byteArray = []; } } else if (Ext.isIE) { if (!this.self.vbScriptInjected) { this.injectVBScript(); } getIEByteArray(xhr.responseBody, byteArray = []); } else { byteArray = []; responseText = xhr.responseText; len = responseText.length; for (i = 0; i < len; i++) { byteArray.push(responseText.charCodeAt(i) & 0xFF); } } return byteArray; }, injectVBScript: function() { var scriptTag = document.createElement('script'); scriptTag.type = 'text/vbscript'; scriptTag.text = [ 'Function getIEByteArray(byteArray, out)', 'Dim len, i', 'len = LenB(byteArray)', 'For i = 1 to len', 'out.push(AscB(MidB(byteArray, i, 1)))', 'Next', 'End Function' ].join('\n'); Ext.getHead().dom.appendChild(scriptTag); this.self.vbScriptInjected = true; }, nativeBinaryPostSupport: function() { return Ext.isChrome || (Ext.isSafari && Ext.isDefined(window.Uint8Array)) || (Ext.isGecko && Ext.isDefined(window.Uint8Array)); } }); Ext.define('Ext.Ajax', { extend: Ext.data.Connection , singleton: true, autoAbort : false }); Ext.define('Ext.util.Floating', { focusOnToFront: true, shadow: 'sides', constrain: false, constructor: function (dom) { var me = this; me.fixed = me.fixed && !(Ext.isIE6 || Ext.isIEQuirks); me.el = new Ext.dom.Layer(Ext.apply({ preventSync : true, hideMode : me.hideMode, shadow : (typeof me.shadow != 'undefined') ? me.shadow : 'sides', shadowOffset : me.shadowOffset, constrain : false, fixed : me.fixed, shim : (me.shim === false) ? false : undefined }, me.floating), dom); if (me.modal && !(Ext.FocusManager && Ext.FocusManager.enabled)) { me.mon(me.el, { keydown: me.onKeyDown, scope: me }); } me.mon(me.el, { mousedown: me.onMouseDown, scope: me }); me.floating = true; me.registerWithOwnerCt(); me.initHierarchyEvents(); }, initHierarchyEvents: function() { var me = this, syncHidden = this.syncHidden; if (!me.hasHierarchyEventListeners) { me.mon(me.hierarchyEventSource, { hide: syncHidden, collapse: syncHidden, show: syncHidden, expand: syncHidden, added: syncHidden, scope: me }); me.hasHierarchyEventListeners = true; } }, registerWithOwnerCt: function() { var me = this, ownerCt = me.ownerCt, zip = me.zIndexParent; if (zip) { zip.unregisterFloatingItem(me); } zip = me.zIndexParent = me.up('[floating]'); me.setFloatParent(ownerCt || zip); delete me.ownerCt; if (zip) { zip.registerFloatingItem(me); } else { Ext.WindowManager.register(me); } }, onKeyDown: function(e) { var me = this, shift, focusables, first, last; if (e.getKey() == Ext.EventObject.TAB) { shift = e.shiftKey; focusables = me.el.query(':focusable'); first = focusables[0]; last = focusables[focusables.length - 1]; if (first && last && e.target === (shift ? first : last)) { e.stopEvent(); (shift ? last : first).focus(false, true); } } }, onMouseDown: function (e) { var focusTask = this.focusTask; if (this.floating && (!focusTask || !focusTask.id)) { this.toFront(!!e.getTarget(':focusable')); } }, setFloatParent: function(floatParent) { var me = this; me.floatParent = floatParent; if ((me.constrain || me.constrainHeader) && !me.constrainTo) { me.constrainTo = floatParent ? floatParent.getTargetEl() : me.container; } }, syncShadow : function() { if (this.floating) { this.el.sync(true); } }, onBeforeFloatLayout: function(){ this.el.preventSync = true; }, onAfterFloatLayout: function(){ delete this.el.preventSync; this.syncShadow(); }, syncHidden: function() { var me = this, hidden = me.hidden || !me.rendered, hierarchicallyHidden = me.hierarchicallyHidden = me.isHierarchicallyHidden(), pendingShow = me.pendingShow; if (hidden !== hierarchicallyHidden) { if (hierarchicallyHidden) { me.hide(); me.pendingShow = true; } else if (pendingShow) { delete me.pendingShow; if (pendingShow.length) { me.show.apply(me, pendingShow); } else { me.show(); } } } }, setZIndex: function(index) { var me = this; me.el.setZIndex(index); index += 10; if (me.floatingDescendants) { index = Math.floor(me.floatingDescendants.setBase(index) / 100) * 100 + 10000; } return index; }, doConstrain: function(constrainTo) { var me = this, xy = me.calculateConstrainedPosition(constrainTo, null, true); if (xy) { me.setPosition(xy); } }, toFront: function(preventFocus) { var me = this, zip = me.zIndexParent, preventFocusSetting = me.preventFocusOnActivate; if (zip && me.bringParentToFront !== false) { zip.toFront(true); } if (!Ext.isDefined(preventFocus)) { preventFocus = !me.focusOnToFront; } if (preventFocus) { me.preventFocusOnActivate = true; } if (me.zIndexManager.bringToFront(me, preventFocus)) { if (!preventFocus) { me.focus(false, true); } } me.preventFocusOnActivate = preventFocusSetting; return me; }, setActive: function(active, newActive) { var me = this; if (active) { if (me.el.shadow && !me.maximized) { me.el.enableShadow(true); } if (!me.preventFocusOnActivate) { me.focus(false, true); } me.fireEvent('activate', me); } else { if (me.isWindow && (newActive && newActive.isWindow) && me.hideShadowOnDeactivate) { me.el.disableShadow(); } me.fireEvent('deactivate', me); } }, toBack: function() { this.zIndexManager.sendToBack(this); return this; }, center: function() { var me = this, xy; if (me.isVisible()) { xy = me.getAlignToXY(me.container, 'c-c'); me.setPagePosition(xy); } else { me.needsCenter = true; } return me; }, onFloatShow: function() { if (this.needsCenter) { this.center(); } delete this.needsCenter; if (this.toFrontOnShow) { this.toFront(); } }, fitContainer: function(animate) { var me = this, parent = me.floatParent, container = parent ? parent.getTargetEl() : me.container, newBox = container.getViewSize(false), newPosition = parent || (container.dom !== document.body) ? [0, 0] : container.getXY(); newBox.x = newPosition[0]; newBox.y = newPosition[1]; me.setBox(newBox, animate); } }); Ext.define('Ext.Component', { alias: ['widget.component', 'widget.box'], extend: Ext.AbstractComponent , mixins: { floating: Ext.util.Floating }, statics: { DIRECTION_TOP: 'top', DIRECTION_RIGHT: 'right', DIRECTION_BOTTOM: 'bottom', DIRECTION_LEFT: 'left', VERTICAL_DIRECTION_Re: /^(?:top|bottom)$/, INVALID_ID_CHARS_Re: /[\.,\s]/g }, resizeHandles: 'all', floating: false, defaultAlign: 'tl-bl?', toFrontOnShow: true, hideMode: 'display', offsetsCls: Ext.baseCSSPrefix + 'hide-offsets', bubbleEvents: [], defaultComponentLayoutType: 'autocomponent', constructor: function(config) { var me = this; config = config || {}; if (config.initialConfig) { if (config.isAction) { me.baseAction = config; } config = config.initialConfig; } else if (config.tagName || config.dom || Ext.isString(config)) { config = { applyTo: config, id: config.id || config }; } me.callParent([config]); if (me.baseAction){ me.baseAction.addComponent(me); } }, initComponent: function() { var me = this; me.callParent(); if (me.listeners) { me.on(me.listeners); me.listeners = null; } me.enableBubble(me.bubbleEvents); }, afterRender: function() { var me = this; me.callParent(); if (!(me.x && me.y) && (me.pageX || me.pageY)) { me.setPagePosition(me.pageX, me.pageY); } }, setAutoScroll : function(scroll) { var me = this; me.autoScroll = !!scroll; if (me.rendered) { me.getOverflowEl().setStyle(me.getOverflowStyle()); } me.updateLayout(); return me; }, setOverflowXY: function(overflowX, overflowY) { var me = this, argCount = arguments.length; if (argCount) { me.overflowX = overflowX || ''; if (argCount > 1) { me.overflowY = overflowY || ''; } } if (me.rendered) { me.getOverflowEl().setStyle(me.getOverflowStyle()); } me.updateLayout(); return me; }, beforeRender: function () { var me = this, floating = me.floating, cls; if (floating) { me.addCls(Ext.baseCSSPrefix + 'layer'); cls = floating.cls; if (cls) { me.addCls(cls); } } return me.callParent(); }, beforeLayout: function(){ this.callParent(arguments); if (this.floating) { this.onBeforeFloatLayout(); } }, afterComponentLayout: function(){ this.callParent(arguments); if (this.floating) { this.onAfterFloatLayout(); } }, makeFloating : function (dom) { this.mixins.floating.constructor.call(this, dom); }, wrapPrimaryEl: function (dom) { if (this.floating) { this.makeFloating(dom); } else { this.callParent(arguments); } }, initResizable: function(resizable) { var me = this; resizable = Ext.apply({ target: me, dynamic: false, constrainTo: me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : null), handles: me.resizeHandles }, resizable); resizable.target = me; me.resizer = new Ext.resizer.Resizer(resizable); }, getDragEl: function() { return this.el; }, initDraggable: function() { var me = this, dragTarget = (me.resizer && me.resizer.el !== me.el) ? me.resizerComponent = new Ext.Component({ ariaRole: 'presentation', el: me.resizer.el, rendered: true, container: me.container }) : me, ddConfig = Ext.applyIf({ el: dragTarget.getDragEl(), constrainTo: (me.constrain||me.draggable.constrain) ? (me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.container)) : undefined }, me.draggable); if (me.constrain || me.constrainDelegate) { ddConfig.constrain = me.constrain; ddConfig.constrainDelegate = me.constrainDelegate; } me.dd = new Ext.util.ComponentDragger(dragTarget, ddConfig); }, scrollBy: function(deltaX, deltaY, animate) { var el; if ((el = this.getTargetEl()) && el.dom) { el.scrollBy.apply(el, arguments); } }, setLoading : function(load, targetEl) { var me = this, config = { target: me }; if (me.rendered) { Ext.destroy(me.loadMask); me.loadMask = null; if (load !== false && !me.collapsed) { if (Ext.isObject(load)) { Ext.apply(config, load); } else if (Ext.isString(load)) { config.msg = load; } if (targetEl) { Ext.applyIf(config, { useTargetEl: true }); } me.loadMask = new Ext.LoadMask(config); me.loadMask.show(); } } return me.loadMask; }, beforeSetPosition: function () { var me = this, pos = me.callParent(arguments), adj; if (pos) { adj = me.adjustPosition(pos.x, pos.y); pos.x = adj.x; pos.y = adj.y; } return pos || null; }, afterSetPosition: function(ax, ay) { this.onPosition(ax, ay); this.fireEvent('move', this, ax, ay); }, showAt: function(x, y, animate) { var me = this; if (!me.rendered && (me.autoRender || me.floating)) { me.x = x; me.y = y; return me.show(); } if (me.floating) { me.setPosition(x, y, animate); } else { me.setPagePosition(x, y, animate); } me.show(); }, showBy: function(cmp, pos, off) { var me = this; if (me.floating && cmp) { me.show(); if (me.rendered && !me.hidden) { me.alignTo(cmp, pos || me.defaultAlign, off); } } return me; }, setPagePosition: function(x, y, animate) { var me = this, p, floatParentBox; if (Ext.isArray(x)) { y = x[1]; x = x[0]; } me.pageX = x; me.pageY = y; if (me.floating) { if (me.isContainedFloater()) { floatParentBox = me.floatParent.getTargetEl().getViewRegion(); if (Ext.isNumber(x) && Ext.isNumber(floatParentBox.left)) { x -= floatParentBox.left; } if (Ext.isNumber(y) && Ext.isNumber(floatParentBox.top)) { y -= floatParentBox.top; } } else { p = me.el.translateXY(x, y); x = p.x; y = p.y; } me.setPosition(x, y, animate); } else { p = me.el.translateXY(x, y); me.setPosition(p.x, p.y, animate); } return me; }, isContainedFloater: function() { return (this.floating && this.floatParent); }, updateBox : function(box){ this.setSize(box.width, box.height); this.setPagePosition(box.x, box.y); return this; }, getOuterSize: function() { var el = this.el; return { width: el.getWidth() + el.getMargin('lr'), height: el.getHeight() + el.getMargin('tb') }; }, adjustPosition: function(x, y) { var me = this, floatParentBox; if (me.isContainedFloater()) { floatParentBox = me.floatParent.getTargetEl().getViewRegion(); x += floatParentBox.left; y += floatParentBox.top; } return { x: x, y: y }; }, getPosition: function(local) { var me = this, xy, isContainedFloater = me.isContainedFloater(), floatParentBox; if ((local === true) && !isContainedFloater) { return [me.getLocalX(), me.getLocalY()]; } xy = me.getXY(); if ((local === true) && isContainedFloater) { floatParentBox = me.floatParent.getTargetEl().getViewRegion(); xy[0] -= floatParentBox.left; xy[1] -= floatParentBox.top; } return xy; }, getId: function() { var me = this, xtype; if (!me.id) { xtype = me.getXType(); if (xtype) { xtype = xtype.replace(Ext.Component.INVALID_ID_CHARS_Re, '-'); } else { xtype = Ext.name.toLowerCase() + '-comp'; } me.id = xtype + '-' + me.getAutoId(); } return me.id; }, show: function(animateTarget, cb, scope) { var me = this, rendered = me.rendered; if (me.hierarchicallyHidden || (me.floating && !rendered && me.isHierarchicallyHidden())) { if (!rendered) { me.initHierarchyEvents(); } if (arguments.length > 1) { arguments[0] = null; me.pendingShow = arguments; } else { me.pendingShow = true; } } else if (rendered && me.isVisible()) { if (me.floating) { me.onFloatShow(); } } else { if (me.fireEvent('beforeshow', me) !== false) { me.hidden = false; delete this.getHierarchyState().hidden; Ext.suspendLayouts(); if (!rendered && (me.autoRender || me.floating)) { me.doAutoRender(); rendered = me.rendered; } if (rendered) { me.beforeShow(); Ext.resumeLayouts(); me.onShow.apply(me, arguments); me.afterShow.apply(me, arguments); } else { Ext.resumeLayouts(true); } } else { me.onShowVeto(); } } return me; }, onShowVeto: Ext.emptyFn, beforeShow: Ext.emptyFn, onShow: function() { var me = this; me.el.show(); me.callParent(arguments); if (me.floating) { if (me.maximized) { me.fitContainer(); } else if (me.constrain) { me.doConstrain(); } } }, getAnimateTarget: function(target){ target = target || this.animateTarget; if (target) { target = target.isComponent ? target.getEl() : Ext.get(target); } return target || null; }, afterShow: function(animateTarget, cb, scope) { var me = this, myEl = me.el, fromBox, toBox, ghostPanel; animateTarget = me.getAnimateTarget(animateTarget); if (!me.ghost) { animateTarget = null; } if (animateTarget) { toBox = { x: myEl.getX(), y: myEl.getY(), width: myEl.dom.offsetWidth, height: myEl.dom.offsetHeight }; fromBox = { x: animateTarget.getX(), y: animateTarget.getY(), width: animateTarget.dom.offsetWidth, height: animateTarget.dom.offsetHeight }; myEl.addCls(me.offsetsCls); ghostPanel = me.ghost(); ghostPanel.el.stopAnimation(); ghostPanel.setX(-10000); me.ghostBox = toBox; ghostPanel.el.animate({ from: fromBox, to: toBox, listeners: { afteranimate: function() { delete ghostPanel.componentLayout.lastComponentSize; me.unghost(); delete me.ghostBox; myEl.removeCls(me.offsetsCls); me.onShowComplete(cb, scope); } } }); } else { me.onShowComplete(cb, scope); } me.fireHierarchyEvent('show'); }, onShowComplete: function(cb, scope) { var me = this; if (me.floating) { me.onFloatShow(); } Ext.callback(cb, scope || me); me.fireEvent('show', me); delete me.hiddenByLayout; }, hide: function(animateTarget, cb, scope) { var me = this, continueHide; if (me.pendingShow) { delete me.pendingShow; } if (!(me.rendered && !me.isVisible())) { continueHide = (me.fireEvent('beforehide', me) !== false); if (me.hierarchicallyHidden || continueHide) { me.hidden = true; me.getHierarchyState().hidden = true; if (me.rendered) { me.onHide.apply(me, arguments); } } } return me; }, onHide: function(animateTarget, cb, scope) { var me = this, ghostPanel, fromSize, toBox, activeEl = Ext.Element.getActiveElement(); if (activeEl === me.el || me.el.contains(activeEl)) { Ext.fly(activeEl).blur(); } animateTarget = me.getAnimateTarget(animateTarget); if (!me.ghost) { animateTarget = null; } if (animateTarget) { toBox = { x: animateTarget.getX(), y: animateTarget.getY(), width: animateTarget.dom.offsetWidth, height: animateTarget.dom.offsetHeight }; ghostPanel = me.ghost(); ghostPanel.el.stopAnimation(); fromSize = me.getSize(); ghostPanel.el.animate({ to: toBox, listeners: { afteranimate: function() { delete ghostPanel.componentLayout.lastComponentSize; ghostPanel.el.hide(); ghostPanel.setHiddenState(true); ghostPanel.el.setSize(fromSize); me.afterHide(cb, scope); } } }); } me.el.hide(); if (!animateTarget) { me.afterHide(cb, scope); } }, afterHide: function(cb, scope) { var me = this; me.hiddenByLayout = null; Ext.AbstractComponent.prototype.onHide.call(me); Ext.callback(cb, scope || me); me.fireEvent('hide', me); me.fireHierarchyEvent('hide'); }, onDestroy: function() { var me = this; if (me.rendered) { Ext.destroy( me.dd, me.resizer, me.proxy, me.proxyWrap, me.resizerComponent ); } delete me.focusTask; me.callParent(); }, deleteMembers: function() { var args = arguments, len = args.length, i = 0; for (; i < len; ++i) { delete this[args[i]]; } }, focus: function(selectText, delay, callback, scope) { var me = this, focusEl, focusElDom, containerScrollTop; if (delay) { me.getFocusTask().delay(Ext.isNumber(delay) ? delay : 10, me.focus, me, [selectText, false, callback, scope]); return me; } if (me.focusTask) { me.focusTask.cancel(); } if (me.rendered && !me.isDestroyed && me.isVisible(true) && (focusEl = me.getFocusEl())) { if (focusEl.isComponent) { return focusEl.focus(selectText, delay); } if ((focusElDom = focusEl.dom)) { if (focusEl.needsTabIndex()) { focusElDom.tabIndex = -1; } if (me.floating) { containerScrollTop = me.container.dom.scrollTop; } focusEl.focus(); if (selectText) { if (Ext.isArray(selectText)) { if (me.selectText) { me.selectText.apply(me, selectText); } } else { focusElDom.select(); } } Ext.callback(callback, scope); } if (me.floating) { if (me !== me.zIndexManager.getActive()) { me.toFront(true); } if (containerScrollTop !== undefined) { me.container.dom.scrollTop = containerScrollTop; } } } return me; }, getFocusTask: function() { if (!this.focusTask) { Ext.Component.prototype.focusTask = new Ext.util.DelayedTask(); } return this.focusTask; }, cancelFocus: function() { var task = this.focusTask; if (task) { task.cancel(); } }, blur: function() { var me = this, focusEl; if (me.rendered && (focusEl = me.getFocusEl())) { me.blurring = true; focusEl.blur(); delete me.blurring; } return me; }, getEl: function() { return this.el; }, getResizeEl: function() { return this.el; }, getPositionEl: function() { return this.el; }, getActionEl: function() { return this.el; }, getVisibilityEl: function() { return this.el; }, getRefOwner: function() { return this.ownerCt || this.floatParent; }, getBubbleTarget: function() { return this.getRefOwner(); }, getContentTarget: function() { return this.el; }, cloneConfig: function(overrides) { overrides = overrides || {}; var id = overrides.id || Ext.id(), cfg = Ext.applyIf(overrides, this.initialConfig), self; cfg.id = id; self = Ext.getClass(this); return new self(cfg); }, getXType: function() { return this.self.xtype; }, findParentBy: function(fn) { var p; for (p = this.getBubbleTarget(); p && !fn(p, this); p = p.getBubbleTarget()) { } return p || null; }, findParentByType: function(xtype) { return Ext.isFunction(xtype) ? this.findParentBy(function(p) { return p.constructor === xtype; }) : this.up(xtype); }, bubble: function(fn, scope, args) { var p = this; while (p) { if (fn.apply(scope || p, args || [p]) === false) { break; } p = p.getBubbleTarget(); } return this; }, getProxy: function() { var me = this, target; if (!me.proxy) { target = Ext.getBody(); me.proxy = me.el.createProxy(Ext.baseCSSPrefix + 'proxy-el', target, true); } return me.proxy; }, fireHierarchyEvent: function (ename) { this.hierarchyEventSource.fireEvent(ename, this); }, onAdded: function() { this.callParent(arguments); if (this.hierarchyEventSource.hasListeners.added) { this.fireHierarchyEvent('added'); } } }, function () { this.hierarchyEventSource = this.prototype.hierarchyEventSource = new Ext.util.Observable({ events: { hide: true, show: true, collapse: true, expand: true, added: true }}); }); Ext.define('Ext.layout.container.border.Region', { override: 'Ext.Component', initBorderRegion: function () { var me = this; if (!me._borderRegionInited) { me._borderRegionInited = true; me.addStateEvents(['changeregion', 'changeweight']); Ext.override(me, { getState: function () { var state = me.callParent(); state = me.addPropertyToState(state, 'region'); state = me.addPropertyToState(state, 'weight'); return state; } }); } }, getOwningBorderContainer: function () { var layout = this.getOwningBorderLayout(); return layout && layout.owner; }, getOwningBorderLayout: function () { var layout = this.ownerLayout; return (layout && layout.isBorderLayout) ? layout : null; }, setBorderRegion: function (region) { var me = this, borderLayout, old = me.region; if (region !== old) { borderLayout = me.getOwningBorderLayout(); if (borderLayout) { var regionFlags = borderLayout.regionFlags[region], placeholder = me.placeholder, splitter = me.splitter, owner = borderLayout.owner, regionMeta = borderLayout.regionMeta, collapsed = me.collapsed || me.floated, delta, items, index; if (me.fireEventArgs('beforechangeregion', [me, region]) === false) { return old; } Ext.suspendLayouts(); me.region = region; Ext.apply(me, regionFlags); if (me.updateCollapseTool) { me.updateCollapseTool(); } if (splitter) { Ext.apply(splitter, regionFlags); splitter.updateOrientation(); items = owner.items; index = items.indexOf(me); if (index >= 0) { delta = regionMeta[region].splitterDelta; if (items.getAt(index + delta) !== splitter) { items.remove(splitter); index = items.indexOf(me); if (delta > 0) { ++index; } items.insert(index, splitter); } } } if (placeholder) { if (collapsed) { me.expand(false); } owner.remove(placeholder); me.placeholder = null; if (collapsed) { me.collapse(null, false); } } owner.updateLayout(); Ext.resumeLayouts(true); me.fireEventArgs('changeregion', [me, old]); } else { me.region = region; } } return old; }, setRegionWeight: function (weight) { var me = this, ownerCt = me.getOwningBorderContainer(), placeholder = me.placeholder, old = me.weight; if (weight !== old) { if (me.fireEventArgs('beforechangeweight', [me, weight]) !== false) { me.weight = weight; if (placeholder) { placeholder.weight = weight; } if (ownerCt) { ownerCt.updateLayout(); } me.fireEventArgs('changeweight', [me, old]); } } return old; } }); Ext.define('Ext.ElementLoader', { mixins: { observable: Ext.util.Observable }, statics: { Renderer: { Html: function(loader, response, active){ loader.getTarget().update(response.responseText, active.scripts === true); return true; } } }, url: null, params: null, baseParams: null, autoLoad: false, target: null, loadMask: false, ajaxOptions: null, scripts: false, isLoader: true, constructor: function(config) { var me = this, autoLoad; config = config || {}; Ext.apply(me, config); me.setTarget(me.target); me.addEvents( 'beforeload', 'exception', 'load' ); me.mixins.observable.constructor.call(me); if (me.autoLoad) { autoLoad = me.autoLoad; if (autoLoad === true) { autoLoad = {}; } me.load(autoLoad); } }, setTarget: function(target){ var me = this; target = Ext.get(target); if (me.target && me.target != target) { me.abort(); } me.target = target; }, getTarget: function(){ return this.target || null; }, abort: function(){ var active = this.active; if (active !== undefined) { Ext.Ajax.abort(active.request); if (active.mask) { this.removeMask(); } delete this.active; } }, removeMask: function(){ this.target.unmask(); }, addMask: function(mask){ this.target.mask(mask === true ? null : mask); }, load: function(options) { options = Ext.apply({}, options); var me = this, mask = Ext.isDefined(options.loadMask) ? options.loadMask : me.loadMask, params = Ext.apply({}, options.params), ajaxOptions = Ext.apply({}, options.ajaxOptions), callback = options.callback || me.callback, scope = options.scope || me.scope || me; Ext.applyIf(ajaxOptions, me.ajaxOptions); Ext.applyIf(options, ajaxOptions); Ext.applyIf(params, me.params); Ext.apply(params, me.baseParams); Ext.applyIf(options, { url: me.url }); Ext.apply(options, { scope: me, params: params, callback: me.onComplete }); if (me.fireEvent('beforeload', me, options) === false) { return; } if (mask) { me.addMask(mask); } me.active = { options: options, mask: mask, scope: scope, callback: callback, success: options.success || me.success, failure: options.failure || me.failure, renderer: options.renderer || me.renderer, scripts: Ext.isDefined(options.scripts) ? options.scripts : me.scripts }; me.active.request = Ext.Ajax.request(options); me.setOptions(me.active, options); }, setOptions: Ext.emptyFn, onComplete: function(options, success, response) { var me = this, active = me.active, scope; if (active) { scope = active.scope; if (success) { success = me.getRenderer(active.renderer).call(me, me, response, active) !== false; } if (success) { Ext.callback(active.success, scope, [me, response, options]); me.fireEvent('load', me, response, options); } else { Ext.callback(active.failure, scope, [me, response, options]); me.fireEvent('exception', me, response, options); } Ext.callback(active.callback, scope, [me, success, response, options]); if (active.mask) { me.removeMask(); } } delete me.active; }, getRenderer: function(renderer){ if (Ext.isFunction(renderer)) { return renderer; } return this.statics().Renderer.Html; }, startAutoRefresh: function(interval, options){ var me = this; me.stopAutoRefresh(); me.autoRefresh = setInterval(function(){ me.load(options); }, interval); }, stopAutoRefresh: function(){ clearInterval(this.autoRefresh); delete this.autoRefresh; }, isAutoRefreshing: function(){ return Ext.isDefined(this.autoRefresh); }, destroy: function(){ var me = this; me.stopAutoRefresh(); delete me.target; me.abort(); me.clearListeners(); } }); Ext.define('Ext.ComponentLoader', { extend: Ext.ElementLoader , statics: { Renderer: { Data: function(loader, response, active){ var success = true; try { loader.getTarget().update(Ext.decode(response.responseText)); } catch (e) { success = false; } return success; }, Component: function(loader, response, active){ var success = true, target = loader.getTarget(), items = []; try { items = Ext.decode(response.responseText); } catch (e) { success = false; } if (success) { target.suspendLayouts(); if (active.removeAll) { target.removeAll(); } target.add(items); target.resumeLayouts(true); } return success; } } }, target: null, loadMask: false, renderer: 'html', setTarget: function(target){ var me = this; if (Ext.isString(target)) { target = Ext.getCmp(target); } if (me.target && me.target != target) { me.abort(); } me.target = target; }, removeMask: function(){ this.target.setLoading(false); }, addMask: function(mask){ this.target.setLoading(mask); }, setOptions: function(active, options){ active.removeAll = Ext.isDefined(options.removeAll) ? options.removeAll : this.removeAll; }, getRenderer: function(renderer){ if (Ext.isFunction(renderer)) { return renderer; } var renderers = this.statics().Renderer; switch (renderer) { case 'component': return renderers.Component; case 'data': return renderers.Data; default: return Ext.ElementLoader.Renderer.Html; } } }); Ext.define('Ext.layout.SizeModel', { constructor: function (config) { var me = this, SizeModel = me.self, sizeModelsArray = SizeModel.sizeModelsArray, name; Ext.apply(me, config); me[name = me.name] = true; me.fixed = !(me.auto = me.natural || me.shrinkWrap); sizeModelsArray[me.ordinal = sizeModelsArray.length] = SizeModel[name] = SizeModel.sizeModels[name] = me; }, statics: { sizeModelsArray: [], sizeModels: {} }, calculated: false, configured: false, constrainedMax: false, constrainedMin: false, natural: false, shrinkWrap: false, calculatedFromConfigured: false, calculatedFromNatural: false, calculatedFromShrinkWrap: false, names: null }, function () { var SizeModel = this, sizeModelsArray = SizeModel.sizeModelsArray, i, j, n, pairs, sizeModel; new SizeModel({ name: 'calculated' }); new SizeModel({ name: 'configured', names: { width: 'width', height: 'height' } }); new SizeModel({ name: 'natural' }); new SizeModel({ name: 'shrinkWrap' }); new SizeModel({ name: 'calculatedFromConfigured', configured: true, names: { width: 'width', height: 'height' } }); new SizeModel({ name: 'calculatedFromNatural', natural: true }); new SizeModel({ name: 'calculatedFromShrinkWrap', shrinkWrap: true }); new SizeModel({ name: 'constrainedMax', configured: true, constrained: true, names: { width: 'maxWidth', height: 'maxHeight' } }); new SizeModel({ name: 'constrainedMin', configured: true, constrained: true, names: { width: 'minWidth', height: 'minHeight' } }); new SizeModel({ name: 'constrainedDock', configured: true, constrained: true, constrainedByMin: true, names: { width: 'dockConstrainedWidth', height: 'dockConstrainedHeight' } }); for (i = 0, n = sizeModelsArray.length; i < n; ++i) { sizeModel = sizeModelsArray[i]; sizeModel.pairsByHeightOrdinal = pairs = []; for (j = 0; j < n; ++j) { pairs.push({ width: sizeModel, height: sizeModelsArray[j] }); } } }); Ext.define('Ext.layout.Layout', { isLayout: true, initialized: false, running: false, autoSizePolicy: { readsWidth: 1, readsHeight: 1, setsWidth: 0, setsHeight: 0 }, statics: { layoutsByType: {}, create: function(layout, defaultType) { var ClassManager = Ext.ClassManager, layoutsByType = this.layoutsByType, alias, className, config, layoutClass, type, load; if (!layout || typeof layout === 'string') { type = layout || defaultType; config = {}; } else if (layout.isLayout) { return layout; } else { config = layout; type = layout.type || defaultType; } if (!(layoutClass = layoutsByType[type])) { alias = 'layout.' + type; className = ClassManager.getNameByAlias(alias); if (!className) { load = true; } layoutClass = ClassManager.get(className); if (load || !layoutClass) { return ClassManager.instantiateByAlias(alias, config || {}); } layoutsByType[type] = layoutClass; } return new layoutClass(config); } }, constructor : function(config) { var me = this; me.id = Ext.id(null, me.type + '-'); Ext.apply(me, config); me.layoutCount = 0; }, beginLayout: Ext.emptyFn, beginLayoutCycle: function (ownerContext) { var me = this, context = me.context, changed; if (me.lastWidthModel != ownerContext.widthModel) { if (me.lastWidthModel) { changed = true; } me.lastWidthModel = ownerContext.widthModel; } if (me.lastHeightModel != ownerContext.heightModel) { if (me.lastWidthModel) { changed = true; } me.lastHeightModel = ownerContext.heightModel; } if (changed) { (context = ownerContext.context).clearTriggers(me, false); context.clearTriggers(me, true); me.triggerCount = 0; } }, finishedLayout: function (ownerContext) { this.lastWidthModel = ownerContext.widthModel; this.lastHeightModel = ownerContext.heightModel; this.ownerContext = null; }, redoLayout: Ext.emptyFn, undoLayout: Ext.emptyFn, getAnimatePolicy: function() { return this.animatePolicy; }, getItemSizePolicy: function (item) { return this.autoSizePolicy; }, isItemBoxParent: function (itemContext) { return false; }, isItemLayoutRoot: function (item) { var sizeModel = item.getSizeModel(), width = sizeModel.width, height = sizeModel.height; if (!item.componentLayout.lastComponentSize && (width.calculated || height.calculated)) { return false; } return !width.shrinkWrap && !height.shrinkWrap; }, isItemShrinkWrap: function (item) { return item.shrinkWrap; }, isRunning: function () { return !!this.ownerContext; }, getItemsRenderTree: function (items, renderCfgs) { var length = items.length, i, item, itemConfig, result; if (length) { result = []; for (i = 0; i < length; ++i) { item = items[i]; if (!item.rendered) { if (renderCfgs && (renderCfgs[item.id] !== undefined)) { itemConfig = renderCfgs[item.id]; } else { this.configureItem(item); itemConfig = item.getRenderTree(); if (renderCfgs) { renderCfgs[item.id] = itemConfig; } } if (itemConfig) { result.push(itemConfig); } } } } return result; }, finishRender: Ext.emptyFn, finishRenderItems: function (target, items) { var length = items.length, i, item; for (i = 0; i < length; i++) { item = items[i]; if (item.rendering) { item.finishRender(i); this.afterRenderItem(item); } } }, renderChildren: function () { var me = this, items = me.getLayoutItems(), target = me.getRenderTarget(); me.renderItems(items, target); }, renderItems : function(items, target) { var me = this, ln = items.length, i = 0, item; if (ln) { Ext.suspendLayouts(); for (; i < ln; i++) { item = items[i]; if (item && !item.rendered) { me.renderItem(item, target, i); } else if (!me.isValidParent(item, target, i)) { me.moveItem(item, target, i); } else { me.configureItem(item); } } Ext.resumeLayouts(true); } }, isValidParent : function(item, target, position) { var itemDom = item.el ? item.el.dom : Ext.getDom(item), targetDom = (target && target.dom) || target, parentNode = itemDom.parentNode, className; if (parentNode) { className = parentNode.className; if (className && className.indexOf(Ext.baseCSSPrefix + 'resizable-wrap') !== -1) { itemDom = itemDom.parentNode; } } if (itemDom && targetDom) { if (typeof position == 'number') { position = this.getPositionOffset(position); return itemDom === targetDom.childNodes[position]; } return itemDom.parentNode === targetDom; } return false; }, getPositionOffset: function(position){ return position; }, configureItem: function(item) { item.ownerLayout = this; }, renderItem : function(item, target, position) { var me = this; if (!item.rendered) { me.configureItem(item); item.render(target, position); me.afterRenderItem(item); } }, moveItem : function(item, target, position) { target = target.dom || target; if (typeof position == 'number') { position = target.childNodes[position]; } target.insertBefore(item.el.dom, position || null); item.container = Ext.get(target); this.configureItem(item); }, onContentChange: function () { this.owner.updateLayout(); return true; }, initLayout : function() { this.initialized = true; }, setOwner : function(owner) { this.owner = owner; }, getLayoutItems : function() { return []; }, onAdd: function (item) { item.ownerLayout = this; }, afterRenderItem: Ext.emptyFn, onRemove : Ext.emptyFn, onDestroy : Ext.emptyFn, afterRemove : function(item) { var me = this, el = item.el, owner = me.owner, removeClasses; if (item.rendered) { removeClasses = [].concat(me.itemCls || []); if (owner.itemCls) { removeClasses = Ext.Array.push(removeClasses, owner.itemCls); } if (removeClasses.length) { el.removeCls(removeClasses); } } delete item.ownerLayout; }, destroy : function() { var me = this, target; if (me.targetCls) { target = me.getTarget(); if (target) { target.removeCls(me.targetCls); } } me.onDestroy(); }, sortWeightedItems: function (items, reverseProp) { for (var i = 0, length = items.length; i < length; ++i) { items[i].$i = i; } Ext.Array.sort(items, function (item1, item2) { var ret = item2.weight - item1.weight; if (!ret) { ret = item1.$i - item2.$i; if (item1[reverseProp]) { ret = -ret; } } return ret; }); for (i = 0; i < length; ++i) { delete items[i].$i; } } }, function () { var Layout = this; Layout.prototype.sizeModels = Layout.sizeModels = Ext.layout.SizeModel.sizeModels; }); Ext.define('Ext.layout.container.Container', { alias: ['layout.container'], extend: Ext.layout.Layout , alternateClassName: 'Ext.layout.ContainerLayout', mixins: { elementCt: Ext.util.ElementContainer }, type: 'container', beginCollapse: Ext.emptyFn, beginExpand: Ext.emptyFn, animatePolicy: null, childEls: [ 'overflowPadderEl' ], renderTpl: [ '{%this.renderBody(out,values)%}' ], usesContainerHeight: true, usesContainerWidth: true, usesHeight: true, usesWidth: true, constructor: function () { this.callParent(arguments); this.mixins.elementCt.constructor.call(this); }, destroy : function() { this.callParent(); this.mixins.elementCt.destroy.call(this); }, beginLayout: function (ownerContext) { this.callParent(arguments); ownerContext.targetContext = ownerContext.paddingContext = ownerContext.getEl('getTarget', this); this.cacheChildItems(ownerContext); }, beginLayoutCycle: function (ownerContext, firstCycle) { var me = this; me.callParent(arguments); if (firstCycle) { if (me.usesContainerHeight) { ++ownerContext.consumersContainerHeight; } if (me.usesContainerWidth) { ++ownerContext.consumersContainerWidth; } } }, cacheChildItems: function (ownerContext) { var context = ownerContext.context, childItems = [], items = this.getVisibleItems(), length = items.length, i; ownerContext.childItems = childItems; ownerContext.visibleItems = items; for (i = 0; i < length; ++i) { childItems.push(context.getCmp(items[i])); } }, cacheElements: function () { var owner = this.owner; this.applyChildEls(owner.el, owner.id); }, configureItem: function(item) { var me = this, itemCls = me.itemCls, ownerItemCls = me.owner.itemCls, addClasses; item.ownerLayout = me; if (itemCls) { addClasses = typeof itemCls === 'string' ? [itemCls] : itemCls; } if (ownerItemCls) { addClasses = Ext.Array.push(addClasses||[], ownerItemCls); } if (addClasses) { item.addCls(addClasses); } }, doRenderBody: function (out, renderData) { this.renderItems(out, renderData); this.renderContent(out, renderData); }, doRenderContainer: function (out, renderData) { var me = renderData.$comp.layout, tpl = me.getRenderTpl(), data = me.getRenderData(); tpl.applyOut(data, out); }, doRenderItems: function (out, renderData) { var me = renderData.$layout, tree = me.getRenderTree(); if (tree) { Ext.DomHelper.generateMarkup(tree, out); } }, finishRender: function () { var me = this, target, items; me.callParent(); me.cacheElements(); target = me.getRenderTarget(); items = me.getLayoutItems(); me.finishRenderItems(target, items); }, notifyOwner: function() { this.owner.afterLayout(this); }, getContainerSize : function(ownerContext, inDom) { var targetContext = ownerContext.targetContext, frameInfo = targetContext.getFrameInfo(), padding = ownerContext.paddingContext.getPaddingInfo(), got = 0, needed = 0, gotWidth, gotHeight, width, height; if (!ownerContext.widthModel.shrinkWrap) { ++needed; width = inDom ? targetContext.getDomProp('width') : targetContext.getProp('width'); gotWidth = (typeof width == 'number'); if (gotWidth) { ++got; width -= frameInfo.width + padding.width; if (width < 0) { width = 0; } } } if (!ownerContext.heightModel.shrinkWrap) { ++needed; height = inDom ? targetContext.getDomProp('height') : targetContext.getProp('height'); gotHeight = (typeof height == 'number'); if (gotHeight) { ++got; height -= frameInfo.height + padding.height; if (height < 0) { height = 0; } } } return { width: width, height: height, needed: needed, got: got, gotAll: got == needed, gotWidth: gotWidth, gotHeight: gotHeight }; }, getPositionOffset: function(position) { if (!this.createsInnerCt) { var offset = this.owner.itemNodeOffset; if (offset) { position += offset; } } return position; }, getLayoutItems: function() { var owner = this.owner, items = owner && owner.items; return (items && items.items) || []; }, getRenderData: function () { var comp = this.owner; return { $comp: comp, $layout: this, ownerId: comp.id }; }, getRenderedItems: function() { var me = this, target = me.getRenderTarget(), items = me.getLayoutItems(), ln = items.length, renderedItems = [], i, item; for (i = 0; i < ln; i++) { item = items[i]; if (item.rendered && me.isValidParent(item, target, i)) { renderedItems.push(item); } } return renderedItems; }, getRenderTarget: function() { return this.owner.getTargetEl(); }, getElementTarget: function() { return this.getRenderTarget(); }, getRenderTpl: function () { var me = this, renderTpl = Ext.XTemplate.getTpl(this, 'renderTpl'); if (!renderTpl.renderContent) { me.owner.setupRenderTpl(renderTpl); } return renderTpl; }, getRenderTree: function () { var result, items = this.owner.items, itemsGen, renderCfgs = {}; do { itemsGen = items.generation; result = this.getItemsRenderTree(this.getLayoutItems(), renderCfgs); } while (items.generation !== itemsGen); return result; }, renderChildren: function () { var me = this, ownerItems = me.owner.items, target = me.getRenderTarget(), itemsGen, items; do { itemsGen = ownerItems.generation; items = me.getLayoutItems(); me.renderItems(items, target); } while (ownerItems.generation !== itemsGen); }, getScrollbarsNeeded: function (width, height, contentWidth, contentHeight) { var scrollbarSize = Ext.getScrollbarSize(), hasWidth = typeof width == 'number', hasHeight = typeof height == 'number', needHorz = 0, needVert = 0; if (!scrollbarSize.width) { return 0; } if (hasHeight && height < contentHeight) { needVert = 2; width -= scrollbarSize.width; } if (hasWidth && width < contentWidth) { needHorz = 1; if (!needVert && hasHeight) { height -= scrollbarSize.height; if (height < contentHeight) { needVert = 2; } } } return needVert + needHorz; }, getTarget: function() { return this.owner.getTargetEl(); }, getVisibleItems: function() { var target = this.getRenderTarget(), items = this.getLayoutItems(), ln = items.length, visibleItems = [], i, item; for (i = 0; i < ln; i++) { item = items[i]; if (item.rendered && this.isValidParent(item, target, i) && item.hidden !== true) { visibleItems.push(item); } } return visibleItems; }, setupRenderTpl: function (renderTpl) { var me = this; renderTpl.renderBody = me.doRenderBody; renderTpl.renderContainer = me.doRenderContainer; renderTpl.renderItems = me.doRenderItems; }, getContentTarget: function(){ return this.owner.getDefaultContentTarget(); } }); Ext.define('Ext.layout.container.Auto', { alias: ['layout.auto', 'layout.autocontainer'], extend: Ext.layout.container.Container , type: 'autocontainer', childEls: [ 'outerCt', 'innerCt', 'clearEl' ], reserveScrollbar: false, managePadding: true, manageOverflow: false, lastOverflowAdjust: { width: 0, height: 0 }, renderTpl: [ '{% if (!(Ext.isIEQuirks || Ext.isIE7m)) { %}', '', '', '', '{% } else if (values.shrinkWrapWidth) { %}', '', '', '', '', '', '', '', '{% } else { %}', '', '{% values.$layout.isShrinkWrapTpl = false %}', '{% } %}' ], tableTpl: [ '', '', '', '', '', '', '' ], isShrinkWrapTpl: true, beginLayout: function(ownerContext) { var me = this, bottomPadding, overflowYStyle, overflowXStyle, needsTable; me.callParent(arguments); me.initContextItems(ownerContext); if (!me.isShrinkWrapTpl) { if (ownerContext.widthModel.shrinkWrap) { needsTable = true; } if (Ext.isStrict && Ext.isIE7) { overflowXStyle = me.getOverflowXStyle(ownerContext); if ((overflowXStyle === 'auto' || overflowXStyle === 'scroll') && ownerContext.paddingContext.getPaddingInfo().right) { needsTable = true; } } if (needsTable) { me.insertTableCt(ownerContext); } } if (!me.isShrinkWrapTpl && Ext.isIE7 && Ext.isStrict && !me.clearElHasPadding) { bottomPadding = ownerContext.paddingContext.getPaddingInfo().bottom; overflowYStyle = me.getOverflowYStyle(ownerContext); if (bottomPadding && (overflowYStyle === 'auto' || overflowYStyle === 'scroll')) { me.clearEl.setStyle('height', bottomPadding); me.clearElHasPadding = true; } } }, beforeLayoutCycle: function(ownerContext){ var comp = this.owner, hierarchyState = comp.hierarchyState, hierarchyStateInner = comp.hierarchyStateInner; if (!hierarchyState || hierarchyState.invalid) { hierarchyState = comp.getHierarchyState(); hierarchyStateInner = comp.hierarchyStateInner; } if (ownerContext.widthModel.shrinkWrap && this.isShrinkWrapTpl) { hierarchyStateInner.inShrinkWrapTable = true; } else { delete hierarchyStateInner.inShrinkWrapTable; } }, beginLayoutCycle: function(ownerContext) { var me = this, outerCt = me.outerCt, lastOuterCtWidth = me.lastOuterCtWidth || '', lastOuterCtHeight = me.lastOuterCtHeight || '', lastOuterCtTableLayout = me.lastOuterCtTableLayout || '', state = ownerContext.state, overflowXStyle, overflowYStyle, outerCtWidth, outerCtHeight, outerCtTableLayout, deferWidth, hierarchyStateInner; me.callParent(arguments); outerCtWidth = outerCtHeight = outerCtTableLayout = ''; if (!ownerContext.widthModel.shrinkWrap && me.isShrinkWrapTpl) { if (Ext.isIE7m && Ext.isStrict) { overflowYStyle = me.getOverflowYStyle(ownerContext); if (overflowYStyle === 'auto' || overflowYStyle === 'scroll') { deferWidth = true; } } if (!deferWidth) { outerCtWidth = '100%'; } hierarchyStateInner = me.owner.hierarchyStateInner; overflowXStyle = me.getOverflowXStyle(ownerContext); outerCtTableLayout = (hierarchyStateInner.inShrinkWrapTable || overflowXStyle === 'auto' || overflowXStyle === 'scroll') ? '' : 'fixed'; } if (!ownerContext.heightModel.shrinkWrap && !Ext.supports.PercentageHeightOverflowBug) { outerCtHeight = '100%'; } if ((outerCtWidth !== lastOuterCtWidth) || me.hasOuterCtPxWidth) { outerCt.setStyle('width', outerCtWidth); me.lastOuterCtWidth = outerCtWidth; me.hasOuterCtPxWidth = false; } if (outerCtTableLayout !== lastOuterCtTableLayout) { outerCt.setStyle('table-layout', outerCtTableLayout); me.lastOuterCtTableLayout = outerCtTableLayout; } if ((outerCtHeight !== lastOuterCtHeight) || me.hasOuterCtPxHeight) { outerCt.setStyle('height', outerCtHeight); me.lastOuterCtHeight = outerCtHeight; me.hasOuterCtPxHeight = false; } if (me.hasInnerCtPxHeight) { me.innerCt.setStyle('height', ''); me.hasInnerCtPxHeight = false; } state.overflowAdjust = state.overflowAdjust || me.lastOverflowAdjust; }, calculate: function(ownerContext) { var me = this, state = ownerContext.state, containerSize = me.getContainerSize(ownerContext, true), calculatedItems = state.calculatedItems || (state.calculatedItems = me.calculateItems ? me.calculateItems(ownerContext, containerSize) : true); me.setCtSizeIfNeeded(ownerContext, containerSize); if (calculatedItems && ownerContext.hasDomProp('containerChildrenSizeDone')) { me.calculateContentSize(ownerContext); if (containerSize.gotAll) { if (me.manageOverflow && !ownerContext.state.secondPass && !me.reserveScrollbar) { me.calculateOverflow(ownerContext, containerSize); } return; } } me.done = false; }, calculateContentSize: function (ownerContext) { var me = this, containerDimensions = ((ownerContext.widthModel.shrinkWrap ? 1 : 0) | (ownerContext.heightModel.shrinkWrap ? 2 : 0)), calcWidth = (containerDimensions & 1) || undefined, calcHeight = (containerDimensions & 2) || undefined, needed = 0, props = ownerContext.props; if (calcWidth) { if (isNaN(props.contentWidth)) { ++needed; } else { calcWidth = undefined; } } if (calcHeight) { if (isNaN(props.contentHeight)) { ++needed; } else { calcHeight = undefined; } } if (needed) { if (calcWidth && !ownerContext.setContentWidth(me.measureContentWidth(ownerContext))) { me.done = false; } if (calcHeight && !ownerContext.setContentHeight(me.measureContentHeight(ownerContext))) { me.done = false; } } }, calculateOverflow: function (ownerContext) { var me = this, width, height, scrollbarSize, scrollbars, xauto, yauto, targetEl; xauto = (me.getOverflowXStyle(ownerContext) === 'auto'); yauto = (me.getOverflowYStyle(ownerContext) === 'auto'); if (xauto || yauto) { scrollbarSize = Ext.getScrollbarSize(); targetEl = ownerContext.overflowContext.el.dom; scrollbars = 0; if (targetEl.scrollWidth > targetEl.clientWidth) { scrollbars |= 1; } if (targetEl.scrollHeight > targetEl.clientHeight) { scrollbars |= 2; } width = (yauto && (scrollbars & 2)) ? scrollbarSize.width : 0; height = (xauto && (scrollbars & 1)) ? scrollbarSize.height : 0; if (width !== me.lastOverflowAdjust.width || height !== me.lastOverflowAdjust.height) { me.done = false; ownerContext.invalidate({ state: { overflowAdjust: { width: width, height: height }, overflowState: scrollbars, secondPass: true } }); } } }, completeLayout: function(ownerContext) { this.lastOverflowAdjust = ownerContext.state.overflowAdjust; }, doRenderPadding: function(out, renderData) { var me = renderData.$layout, owner = renderData.$layout.owner, padding = owner[owner.contentPaddingProperty]; if (me.managePadding && padding) { out.push('padding:', owner.unitizeBox(padding)); } }, finishedLayout: function (ownerContext) { var innerCt = this.innerCt; this.callParent(arguments); if (Ext.isIEQuirks || Ext.isIE8m) { innerCt.repaint(); } if (Ext.isOpera) { innerCt.setStyle('position', 'relative'); innerCt.dom.scrollWidth; innerCt.setStyle('position', ''); } }, getContainerSize : function(ownerContext, inDom) { var size = this.callParent(arguments), overflowAdjust = ownerContext.state.overflowAdjust; if (overflowAdjust) { size.width -= overflowAdjust.width; size.height -= overflowAdjust.height; } return size; }, getRenderData: function() { var owner = this.owner, data = this.callParent(); if ((Ext.isIEQuirks || Ext.isIE7m) && ((owner.shrinkWrap & 1) || (owner.floating && !owner.width))) { data.shrinkWrapWidth = true; } return data; }, getRenderTarget: function() { return this.innerCt; }, getElementTarget: function() { return this.innerCt; }, getOverflowXStyle: function(ownerContext) { return ownerContext.overflowXStyle || (ownerContext.overflowXStyle = this.owner.scrollFlags.overflowX || ownerContext.overflowContext.getStyle('overflow-x')); }, getOverflowYStyle: function(ownerContext) { return ownerContext.overflowYStyle || (ownerContext.overflowYStyle = this.owner.scrollFlags.overflowY || ownerContext.overflowContext.getStyle('overflow-y')); }, initContextItems: function(ownerContext) { var me = this, target = ownerContext.target, customOverflowEl = me.owner.customOverflowEl; ownerContext.outerCtContext = ownerContext.getEl('outerCt', me); ownerContext.innerCtContext = ownerContext.getEl('innerCt', me); if (customOverflowEl) { ownerContext.overflowContext = ownerContext.getEl(customOverflowEl); } else { ownerContext.overflowContext = ownerContext.targetContext; } if (target[target.contentPaddingProperty] !== undefined) { ownerContext.paddingContext = me.isShrinkWrapTpl ? ownerContext.innerCtContext : ownerContext.outerCtContext; } }, initLayout: function() { var me = this, scrollbarWidth = Ext.getScrollbarSize().width, owner = me.owner; me.callParent(); if (scrollbarWidth && me.manageOverflow && !me.hasOwnProperty('lastOverflowAdjust')) { if (owner.autoScroll || me.reserveScrollbar) { me.lastOverflowAdjust = { width: scrollbarWidth, height: 0 }; } } }, insertTableCt: function(ownerContext) { var me = this, owner = me.owner, i = 0, renderTpl, fragment, childNodes, childLength, targetEl; renderTpl = Ext.XTemplate.getTpl(this, 'tableTpl'); renderTpl.renderPadding = me.doRenderPadding; me.outerCt.dom.removeChild(me.innerCt.dom); fragment = document.createDocumentFragment(); childNodes = me.innerCt.dom.childNodes; childLength = childNodes.length; for (; i < childLength; i++) { fragment.appendChild(childNodes[0]); } targetEl = me.getTarget(); targetEl.dom.innerHTML = renderTpl.apply({ $layout: me, ownerId: me.owner.id }); targetEl.down('td').dom.appendChild(fragment); me.applyChildEls(owner.el, owner.id) me.isShrinkWrapTpl = true; ownerContext.removeEl(me.outerCt); ownerContext.removeEl(me.innerCt); me.initContextItems(ownerContext); }, measureContentHeight: function (ownerContext) { var contentHeight = this.outerCt.getHeight(), target = ownerContext.target; if (this.managePadding && (target[target.contentPaddingProperty] === undefined)) { contentHeight += ownerContext.targetContext.getPaddingInfo().height; } return contentHeight; }, measureContentWidth: function (ownerContext) { var dom, style, old, contentWidth, target; if (this.chromeCellMeasureBug) { dom = this.innerCt.dom; style = dom.style; old = style.display; if (old == 'table-cell') { style.display = ''; dom.offsetWidth; style.display = old; } } contentWidth = this.outerCt.getWidth(); target = ownerContext.target; if (this.managePadding && (target[target.contentPaddingProperty] === undefined)) { contentWidth += ownerContext.targetContext.getPaddingInfo().width; } return contentWidth; }, setCtSizeIfNeeded: function(ownerContext, containerSize) { var me = this, width = containerSize.width, height = containerSize.height, padding = ownerContext.paddingContext.getPaddingInfo(), targetEl = me.getTarget(), overflowXStyle = me.getOverflowXStyle(ownerContext), overflowYStyle = me.getOverflowYStyle(ownerContext), canOverflowX = (overflowXStyle === 'auto' || overflowXStyle === 'scroll'), canOverflowY = (overflowYStyle === 'auto' || overflowYStyle === 'scroll'), scrollbarSize = Ext.getScrollbarSize(), isShrinkWrapTpl = me.isShrinkWrapTpl, manageOverflow = me.manageOverflow, overflowStyleName, needsOuterHeight, needsInnerHeight, needsInnerCtPaddingHeight; if (width && !ownerContext.widthModel.shrinkWrap && ((Ext.isIE7m && Ext.isStrict && isShrinkWrapTpl && canOverflowY) || (Ext.isIEQuirks && !isShrinkWrapTpl && !canOverflowX))) { if (!manageOverflow) { if (canOverflowY && (targetEl.dom.scrollHeight > targetEl.dom.clientHeight)) { width -= scrollbarSize.width; } } ownerContext.outerCtContext.setProp('width', width + padding.width); me.hasOuterCtPxWidth = true; } if (height && !ownerContext.heightModel.shrinkWrap) { if (Ext.supports.PercentageHeightOverflowBug) { needsOuterHeight = true; } if (((Ext.isIE8 && Ext.isStrict) || Ext.isIE7m && Ext.isStrict && isShrinkWrapTpl)) { needsInnerHeight = true; needsInnerCtPaddingHeight = !Ext.isIE8; } if ((needsOuterHeight || needsInnerHeight) && canOverflowX && (targetEl.dom.scrollWidth > targetEl.dom.clientWidth)) { height = Math.max(height - scrollbarSize.height, 0); } if (needsOuterHeight) { ownerContext.outerCtContext.setProp('height', height + padding.height); me.hasOuterCtPxHeight = true; } if (needsInnerHeight) { if (needsInnerCtPaddingHeight) { height += padding.height; } ownerContext.innerCtContext.setProp('height', height); me.hasInnerCtPxHeight = true; } } if (Ext.isIE7 && Ext.isStrict && !isShrinkWrapTpl && (overflowYStyle === 'auto')) { overflowStyleName = (overflowXStyle === 'auto') ? 'overflow-x' : 'overflow-y'; targetEl.setStyle(overflowStyleName, 'hidden'); targetEl.setStyle(overflowStyleName, 'auto'); } }, setupRenderTpl: function (renderTpl) { this.callParent(arguments); renderTpl.renderPadding = this.doRenderPadding; }, getContentTarget: function(){ return this.innerCt; } }, function(){ this.prototype.chromeCellMeasureBug = Ext.isChrome && Ext.chromeVersion >= 26; }); Ext.define('Ext.ZIndexManager', { alternateClassName: 'Ext.WindowGroup', statics: { zBase : 9000 }, constructor: function(container) { var me = this; me.map = {}; me.zIndexStack = []; me.front = null; if (container) { if (container.isContainer) { container.on('resize', me._onContainerResize, me); me.zseed = Ext.Number.from(me.rendered ? container.getEl().getStyle('zIndex') : undefined, me.getNextZSeed()); me.targetEl = container.getTargetEl(); me.container = container; } else { Ext.EventManager.onWindowResize(me._onContainerResize, me); me.zseed = me.getNextZSeed(); me.targetEl = Ext.get(container); } } else { Ext.EventManager.onWindowResize(me._onContainerResize, me); me.zseed = me.getNextZSeed(); Ext.onDocumentReady(function() { me.targetEl = Ext.getBody(); }); } }, getNextZSeed: function() { return (Ext.ZIndexManager.zBase += 10000); }, setBase: function(baseZIndex) { this.zseed = baseZIndex; var result = this.assignZIndices(); this._activateLast(); return result; }, assignZIndices: function() { var a = this.zIndexStack, len = a.length, i = 0, zIndex = this.zseed, comp, topModal; for (; i < len; i++) { comp = a[i]; if (comp && !comp.hidden) { zIndex = comp.setZIndex(zIndex); if (comp.modal) { topModal = comp; } } } if (topModal) { this._showModalMask(topModal) } return zIndex; }, _setActiveChild: function(comp, oldFront) { var front = this.front, oldPreventFocus = comp.preventFocusOnActivate; if (comp !== front) { if (front && !front.destroying) { front.setActive(false, comp); } this.front = comp; if (comp && comp != oldFront) { comp.preventFocusOnActivate = comp.preventFocusOnActivate || oldFront && (oldFront.preventFocusOnActivate || !oldFront.focusOnToFront); comp.setActive(true); if (comp.modal) { this._showModalMask(comp); } comp.preventFocusOnActivate = oldPreventFocus; } } }, onComponentHide: function(comp){ this._activateLast(); }, _activateLast: function() { var me = this, stack = me.zIndexStack, i = stack.length - 1, comp; for (; i >= 0 && stack[i].hidden; --i); if ((comp = stack[i])) { me._setActiveChild(comp, me.front); if (comp.modal) { return; } } else { if (me.front && !me.front.destroying) { me.front.setActive(false); } me.front = null; } for (; i >= 0; --i) { comp = stack[i]; if (comp.isVisible() && comp.modal) { me._showModalMask(comp); return; } } me._hideModalMask(); }, _showModalMask: function(comp) { var me = this, zIndex = comp.el.getStyle('zIndex') - 4, maskTarget = comp.floatParent ? comp.floatParent.getTargetEl() : comp.container, mask = me.mask, shim = me.maskShim, viewSize; if (!mask) { if (Ext.isIE6) { shim = me.maskShim = Ext.getBody().createChild({ tag: 'iframe', role: 'presentation', cls : Ext.baseCSSPrefix + 'shim ' + Ext.baseCSSPrefix + 'mask-shim' }); shim.setVisibilityMode(Ext.Element.DISPLAY); } mask = me.mask = Ext.getBody().createChild({ role: 'presentation', cls: Ext.baseCSSPrefix + 'mask', style: 'height:0;width:0' }); mask.setVisibilityMode(Ext.Element.DISPLAY); mask.on('click', me._onMaskClick, me); } mask.maskTarget = maskTarget; viewSize = me.getMaskBox(); if (shim) { shim.setStyle('zIndex', zIndex); shim.show(); shim.setBox(viewSize); } mask.setStyle('zIndex', zIndex); mask.show(); mask.setBox(viewSize); }, _hideModalMask: function() { var mask = this.mask, maskShim = this.maskShim; if (mask && mask.isVisible()) { mask.maskTarget = undefined; mask.hide(); if (maskShim) { maskShim.hide(); } } }, _onMaskClick: function() { if (this.front) { this.front.focus(); } }, getMaskBox: function(){ var maskTarget = this.mask.maskTarget; if (maskTarget.dom === document.body) { return { height: Math.max(document.body.scrollHeight, Ext.dom.Element.getDocumentHeight()), width: Math.max(document.body.scrollWidth, document.documentElement.clientWidth), x: 0, y: 0 }; } else { return maskTarget.getBox(); } }, _onContainerResize: function() { var me = this, mask = me.mask, maskShim = me.maskShim, viewSize; if (mask && mask.isVisible()) { mask.hide(); if (maskShim) { maskShim.hide(); } viewSize = me.getMaskBox(); if (maskShim) { maskShim.setSize(viewSize); maskShim.show(); } mask.setSize(viewSize); mask.show(); } }, register : function(comp) { var me = this, compAfterHide = comp.afterHide; if (comp.zIndexManager) { comp.zIndexManager.unregister(comp); } comp.zIndexManager = me; me.map[comp.id] = comp; me.zIndexStack.push(comp); comp.afterHide = function() { compAfterHide.apply(comp, arguments); me.onComponentHide(comp); }; }, unregister : function(comp) { var me = this, map = me.map; delete comp.zIndexManager; if (map && map[comp.id]) { delete map[comp.id]; delete comp.afterHide; Ext.Array.remove(me.zIndexStack, comp); me._activateLast(); } }, get : function(id) { return id.isComponent ? id : this.map[id]; }, bringToFront : function(comp, preventFocus) { var me = this, result = false, zIndexStack = me.zIndexStack; comp = me.get(comp); if (comp !== me.front) { Ext.Array.remove(zIndexStack, comp); if (comp.preventBringToFront) { zIndexStack.unshift(comp); } else { zIndexStack.push(comp); } me.assignZIndices(); if (!preventFocus) { me._activateLast(); } result = true; me.front = comp; if (comp.modal) { me._showModalMask(comp); } } return result; }, sendToBack : function(comp) { var me = this; comp = me.get(comp); Ext.Array.remove(me.zIndexStack, comp); me.zIndexStack.unshift(comp); me.assignZIndices(); this._activateLast(); return comp; }, hideAll : function() { var map = this.map, item, id; for (id in map) { if (map.hasOwnProperty(id)) { item = map[id]; if (item.isComponent && item.isVisible()) { item.hide(); } } } }, hide: function() { var i = 0, stack = this.zIndexStack, len = stack.length, comp; this.tempHidden = []; for (; i < len; i++) { comp = stack[i]; if (comp.isVisible()) { this.tempHidden.push(comp); comp.el.hide(); comp.hidden = true; } } }, show: function() { var i = 0, tempHidden = this.tempHidden, len = tempHidden ? tempHidden.length : 0, comp; for (; i < len; i++) { comp = tempHidden[i]; comp.el.show(); comp.hidden = false; comp.setPosition(comp.x, comp.y); } delete this.tempHidden; }, getActive : function() { return this.front; }, getBy : function(fn, scope) { var r = [], i = 0, stack = this.zIndexStack, len = stack.length, comp; for (; i < len; i++) { comp = stack[i]; if (fn.call(scope||comp, comp) !== false) { r.push(comp); } } return r; }, each : function(fn, scope) { var map = this.map, id, comp; for (id in map) { if (map.hasOwnProperty(id)) { comp = map[id]; if (comp.isComponent && fn.call(scope || comp, comp) === false) { return; } } } }, eachBottomUp: function (fn, scope) { var stack = this.zIndexStack, i = 0, len = stack.length, comp; for (; i < len; i++) { comp = stack[i]; if (comp.isComponent && fn.call(scope || comp, comp) === false) { return; } } }, eachTopDown: function (fn, scope) { var stack = this.zIndexStack, i = stack.length, comp; for (; i-- > 0; ) { comp = stack[i]; if (comp.isComponent && fn.call(scope || comp, comp) === false) { return; } } }, destroy: function() { var me = this, map = me.map, comp, id; for (id in map) { if (map.hasOwnProperty(id)) { comp = map[id]; if (comp.isComponent) { comp.destroy(); } } } Ext.destroy(me.mask); Ext.destroy(me.maskShim); delete me.zIndexStack; delete me.map; delete me.container; delete me.targetEl; } }, function() { Ext.WindowManager = Ext.WindowMgr = new this(); }); Ext.define('Ext.Queryable', { isQueryable: true, query : function(selector) { selector = selector || '*'; return Ext.ComponentQuery.query(selector, this); }, queryBy: function(fn, scope) { var out = [], items = this.getRefItems(true), i = 0, len = items.length, item; for (; i < len; ++i) { item = items[i]; if (fn.call(scope || item, item) !== false) { out.push(item); } } return out; }, queryById: function(id){ return this.down('#' + id); }, child: function (selector) { if (selector && selector.isComponent) { selector = '#' + Ext.escapeId(selector.getItemId()); } selector = selector || ''; return this.query('> ' + selector)[0] || null; }, down: function (selector) { if (selector && selector.isComponent) { selector = '#' + Ext.escapeId(selector.getItemId()); } selector = selector || ''; return this.query(selector)[0] || null; }, getRefItems: function(){ return []; } }); Ext.define('Ext.layout.component.Component', { extend: Ext.layout.Layout , type: 'component', isComponentLayout: true, nullBox: {}, usesContentHeight: true, usesContentWidth: true, usesHeight: true, usesWidth: true, beginLayoutCycle: function (ownerContext, firstCycle) { var me = this, owner = me.owner, ownerCtContext = ownerContext.ownerCtContext, heightModel = ownerContext.heightModel, widthModel = ownerContext.widthModel, body = owner.el.dom === document.body, lastBox = owner.lastBox || me.nullBox, lastSize = owner.el.lastBox || me.nullBox, dirty = !body, ownerLayout, v, widthName, heightName; me.callParent(arguments); if (firstCycle) { if (me.usesContentWidth) { ++ownerContext.consumersContentWidth; } if (me.usesContentHeight) { ++ownerContext.consumersContentHeight; } if (me.usesWidth) { ++ownerContext.consumersWidth; } if (me.usesHeight) { ++ownerContext.consumersHeight; } if (ownerCtContext && !ownerCtContext.hasRawContent) { ownerLayout = owner.ownerLayout; if (ownerLayout.usesWidth) { ++ownerContext.consumersWidth; } if (ownerLayout.usesHeight) { ++ownerContext.consumersHeight; } } } if (widthModel.configured) { widthName = widthModel.names.width; if (!body) { dirty = me.setWidthInDom || (firstCycle ? owner[widthName] !== lastSize.width : widthModel.constrained); } ownerContext.setWidth(owner[widthName], dirty); } else if (ownerContext.isTopLevel) { if (widthModel.calculated) { v = lastBox.width; ownerContext.setWidth(v, v != lastSize.width); } v = lastBox.x; ownerContext.setProp('x', v, v != lastSize.x); } if (heightModel.configured) { heightName = heightModel.names.height; if (!body) { dirty = firstCycle ? owner[heightName] !== lastSize.height : heightModel.constrained; } ownerContext.setHeight(owner[heightName], dirty); } else if (ownerContext.isTopLevel) { if (heightModel.calculated) { v = lastBox.height; ownerContext.setHeight(v, v != lastSize.height); } v = lastBox.y; ownerContext.setProp('y', v, v != lastSize.y); } }, finishedLayout: function(ownerContext) { var me = this, elementChildren = ownerContext.children, owner = me.owner, len, i, elContext, lastBox, props; if (elementChildren) { len = elementChildren.length; for (i = 0; i < len; i++) { elContext = elementChildren[i]; elContext.el.lastBox = elContext.props; } } ownerContext.previousSize = me.lastComponentSize; me.lastComponentSize = owner.el.lastBox = props = ownerContext.props; lastBox = owner.lastBox || (owner.lastBox = {}); lastBox.x = props.x; lastBox.y = props.y; lastBox.width = props.width; lastBox.height = props.height; lastBox.invalid = false; me.callParent(arguments); }, notifyOwner: function(ownerContext) { var me = this, currentSize = me.lastComponentSize, prevSize = ownerContext.previousSize, args = [currentSize.width, currentSize.height]; if (prevSize) { args.push(prevSize.width, prevSize.height); } me.owner.afterComponentLayout.apply(me.owner, args); }, getTarget : function() { return this.owner.el; }, getRenderTarget : function() { return this.owner.el; }, cacheTargetInfo: function(ownerContext) { var me = this, targetInfo = me.targetInfo, target; if (!targetInfo) { target = ownerContext.getEl('getTarget', me); me.targetInfo = targetInfo = { padding: target.getPaddingInfo(), border: target.getBorderInfo() }; } return targetInfo; }, measureAutoDimensions: function (ownerContext, dimensions) { var me = this, owner = me.owner, containerLayout = owner.layout, heightModel = ownerContext.heightModel, widthModel = ownerContext.widthModel, boxParent = ownerContext.boxParent, isBoxParent = ownerContext.isBoxParent, props = ownerContext.props, isContainer, ret = { gotWidth: false, gotHeight: false, isContainer: (isContainer = !ownerContext.hasRawContent) }, hv = dimensions || 3, zeroWidth, zeroHeight, needed = 0, got = 0, ready, size, temp; if (widthModel.shrinkWrap && ownerContext.consumersContentWidth) { ++needed; zeroWidth = !(hv & 1); if (isContainer) { if (zeroWidth) { ret.contentWidth = 0; ret.gotWidth = true; ++got; } else if ((ret.contentWidth = ownerContext.getProp('contentWidth')) !== undefined) { ret.gotWidth = true; ++got; } } else { size = props.contentWidth; if (typeof size == 'number') { ret.contentWidth = size; ret.gotWidth = true; ++got; } else { if (zeroWidth) { ready = true; } else if (!ownerContext.hasDomProp('containerChildrenSizeDone')) { ready = false; } else if (isBoxParent || !boxParent || boxParent.widthModel.shrinkWrap) { ready = true; } else { ready = boxParent.hasDomProp('width'); } if (ready) { if (zeroWidth) { temp = 0; } else if (containerLayout && containerLayout.measureContentWidth) { temp = containerLayout.measureContentWidth(ownerContext); } else { temp = me.measureContentWidth(ownerContext); } if (!isNaN(ret.contentWidth = temp)) { ownerContext.setContentWidth(temp, true); ret.gotWidth = true; ++got; } } } } } else if (widthModel.natural && ownerContext.consumersWidth) { ++needed; size = props.width; if (typeof size == 'number') { ret.width = size; ret.gotWidth = true; ++got; } else { if (isBoxParent || !boxParent) { ready = true; } else { ready = boxParent.hasDomProp('width'); } if (ready) { if (!isNaN(ret.width = me.measureOwnerWidth(ownerContext))) { ownerContext.setWidth(ret.width, false); ret.gotWidth = true; ++got; } } } } if (heightModel.shrinkWrap && ownerContext.consumersContentHeight) { ++needed; zeroHeight = !(hv & 2); if (isContainer) { if (zeroHeight) { ret.contentHeight = 0; ret.gotHeight = true; ++got; } else if ((ret.contentHeight = ownerContext.getProp('contentHeight')) !== undefined) { ret.gotHeight = true; ++got; } } else { size = props.contentHeight; if (typeof size == 'number') { ret.contentHeight = size; ret.gotHeight = true; ++got; } else { if (zeroHeight) { ready = true; } else if (!ownerContext.hasDomProp('containerChildrenSizeDone')) { ready = false; } else if (owner.noWrap) { ready = true; } else if (!widthModel.shrinkWrap) { ready = (ownerContext.bodyContext || ownerContext).hasDomProp('width'); } else if (isBoxParent || !boxParent || boxParent.widthModel.shrinkWrap) { ready = true; } else { ready = boxParent.hasDomProp('width'); } if (ready) { if (zeroHeight) { temp = 0; } else if (containerLayout && containerLayout.measureContentHeight) { temp = containerLayout.measureContentHeight(ownerContext); } else { temp = me.measureContentHeight(ownerContext); } if (!isNaN(ret.contentHeight = temp)) { ownerContext.setContentHeight(temp, true); ret.gotHeight = true; ++got; } } } } } else if (heightModel.natural && ownerContext.consumersHeight) { ++needed; size = props.height; if (typeof size == 'number') { ret.height = size; ret.gotHeight = true; ++got; } else { if (isBoxParent || !boxParent) { ready = true; } else { ready = boxParent.hasDomProp('width'); } if (ready) { if (!isNaN(ret.height = me.measureOwnerHeight(ownerContext))) { ownerContext.setHeight(ret.height, false); ret.gotHeight = true; ++got; } } } } if (boxParent) { ownerContext.onBoxMeasured(); } ret.gotAll = got == needed; return ret; }, measureContentWidth: function (ownerContext) { return ownerContext.el.getWidth() - ownerContext.getFrameInfo().width; }, measureContentHeight: function (ownerContext) { return ownerContext.el.getHeight() - ownerContext.getFrameInfo().height; }, measureOwnerHeight: function (ownerContext) { return ownerContext.el.getHeight(); }, measureOwnerWidth: function (ownerContext) { return ownerContext.el.getWidth(); } }); Ext.define('Ext.layout.component.Auto', { alias: 'layout.autocomponent', extend: Ext.layout.component.Component , type: 'autocomponent', setHeightInDom: false, setWidthInDom: false, waitForOuterHeightInDom: false, waitForOuterWidthInDom: false, beginLayoutCycle: function(ownerContext, firstCycle){ var me = this, lastWidthModel = me.lastWidthModel, lastHeightModel = me.lastHeightModel, el = me.owner.el; me.callParent(arguments); if (lastWidthModel && lastWidthModel.fixed && ownerContext.widthModel.shrinkWrap) { el.setWidth(null); } if (lastHeightModel && lastHeightModel.fixed && ownerContext.heightModel.shrinkWrap) { el.setHeight(null); } }, calculate: function(ownerContext) { var me = this, measurement = me.measureAutoDimensions(ownerContext), heightModel = ownerContext.heightModel, widthModel = ownerContext.widthModel, width, height; if (measurement.gotWidth) { if (widthModel.shrinkWrap) { me.publishOwnerWidth(ownerContext, measurement.contentWidth); } else if (me.publishInnerWidth) { me.publishInnerWidth(ownerContext, measurement.width); } } else if (!widthModel.auto && me.publishInnerWidth) { width = me.waitForOuterWidthInDom ? ownerContext.getDomProp('width') : ownerContext.getProp('width'); if (width === undefined) { me.done = false; } else { me.publishInnerWidth(ownerContext, width); } } if (measurement.gotHeight) { if (heightModel.shrinkWrap) { me.publishOwnerHeight(ownerContext, measurement.contentHeight); } else if (me.publishInnerHeight) { me.publishInnerHeight(ownerContext, measurement.height); } } else if (!heightModel.auto && me.publishInnerHeight) { height = me.waitForOuterHeightInDom ? ownerContext.getDomProp('height') : ownerContext.getProp('height'); if (height === undefined) { me.done = false; } else { me.publishInnerHeight(ownerContext, height); } } if (!measurement.gotAll) { me.done = false; } }, calculateOwnerHeightFromContentHeight: function (ownerContext, contentHeight) { return contentHeight + ownerContext.getFrameInfo().height; }, calculateOwnerWidthFromContentWidth: function (ownerContext, contentWidth) { return contentWidth + ownerContext.getFrameInfo().width; }, publishOwnerHeight: function (ownerContext, contentHeight) { var me = this, owner = me.owner, height = me.calculateOwnerHeightFromContentHeight(ownerContext, contentHeight), constrainedHeight, dirty, heightModel; if (isNaN(height)) { me.done = false; } else { constrainedHeight = Ext.Number.constrain(height, owner.minHeight, owner.maxHeight); if (constrainedHeight == height) { dirty = me.setHeightInDom; } else { heightModel = me.sizeModels[ (constrainedHeight < height) ? 'constrainedMax' : 'constrainedMin']; height = constrainedHeight; if (ownerContext.heightModel.calculatedFromShrinkWrap) { ownerContext.heightModel = heightModel; } else { ownerContext.invalidate({ heightModel: heightModel }); } } ownerContext.setHeight(height, dirty); } }, publishOwnerWidth: function (ownerContext, contentWidth) { var me = this, owner = me.owner, width = me.calculateOwnerWidthFromContentWidth(ownerContext, contentWidth), constrainedWidth, dirty, widthModel; if (isNaN(width)) { me.done = false; } else { constrainedWidth = Ext.Number.constrain(width, owner.minWidth, owner.maxWidth); if (constrainedWidth == width) { dirty = me.setWidthInDom; } else { widthModel = me.sizeModels[ (constrainedWidth < width) ? 'constrainedMax' : 'constrainedMin']; width = constrainedWidth; if (ownerContext.widthModel.calculatedFromShrinkWrap) { ownerContext.widthModel = widthModel; } else { ownerContext.invalidate({ widthModel: widthModel }); } } ownerContext.setWidth(width, dirty); } } }); Ext.define('Ext.container.AbstractContainer', { extend: Ext.Component , mixins: { queryable: Ext.Queryable }, renderTpl: '{%this.renderContainer(out,values)%}', suspendLayout : false, autoDestroy : true, defaultType: 'panel', detachOnRemove: true, isContainer : true, layoutCounter : 0, baseCls: Ext.baseCSSPrefix + 'container', defaultLayoutType: 'auto', ariaRole: 'presentation', initComponent : function(){ var me = this; me.addEvents( 'afterlayout', 'beforeadd', 'beforeremove', 'add', 'remove' ); me.callParent(); me.getLayout(); me.initItems(); }, initItems : function() { var me = this, items = me.items; me.items = new Ext.util.AbstractMixedCollection(false, me.getComponentId); me.floatingItems = new Ext.util.MixedCollection(false, me.getComponentId); if (items) { if (!Ext.isArray(items)) { items = [items]; } me.add(items); } }, getFocusEl: function() { return this.getTargetEl(); }, finishRenderChildren: function () { this.callParent(); var layout = this.getLayout(); if (layout) { layout.finishRender(); } }, beforeRender: function () { var me = this, layout = me.getLayout(), targetCls; me.callParent(); if (!layout.initialized) { layout.initLayout(); } targetCls = layout.targetCls; if (targetCls) { me.applyTargetCls(targetCls); } }, applyTargetCls: function(targetCls) { this.addCls(targetCls); }, afterComponentLayout: function() { var floaters = this.floatingItems.items, floaterCount = floaters.length, i, floater this.callParent(arguments); for (i = 0; i < floaterCount; i++) { floater = floaters[i]; if (!floater.rendered && floater.autoShow) { floater.show(); } } }, onPosition: function() { this.callParent(arguments); this.repositionFloatingItems(); }, onResize: function() { this.callParent(arguments); this.repositionFloatingItems(); }, repositionFloatingItems: function() { var floaters = this.floatingItems.items, floaterCount = floaters.length, i, floater; for (i = 0; i < floaterCount; i++) { floater = floaters[i]; if (floater.el && !floater.hidden) { floater.setPosition(floater.x, floater.y); } } }, setupRenderTpl: function (renderTpl) { this.callParent(arguments); this.getLayout().setupRenderTpl(renderTpl); }, getDefaultContentTarget: function() { return this.el; }, getContentTarget: function(){ return this.getLayout().getContentTarget(); }, setLayout : function(layout) { var currentLayout = this.layout; if (currentLayout && currentLayout.isLayout && currentLayout != layout) { currentLayout.setOwner(null); } this.layout = layout; layout.setOwner(this); }, getLayout : function() { var me = this; if (!me.layout || !me.layout.isLayout) { me.setLayout(Ext.layout.Layout.create(me.layout, me.self.prototype.layout || me.defaultLayoutType)); } return me.layout; }, doLayout : function() { this.updateLayout(); return this; }, afterLayout : function(layout) { var me = this; ++me.layoutCounter; if (me.hasListeners.afterlayout) { me.fireEvent('afterlayout', me, layout); } }, prepareItems : function(items, applyDefaults) { if (Ext.isArray(items)) { items = items.slice(); } else { items = [items]; } var me = this, i = 0, len = items.length, item; for (; i < len; i++) { item = items[i]; if (item == null) { Ext.Array.erase(items, i, 1); --i; --len; } else { if (applyDefaults) { item = this.applyDefaults(item); } item.isContained = me; items[i] = me.lookupComponent(item); delete item.isContained; delete items[i].isContained; } } return items; }, applyDefaults : function(config) { var defaults = this.defaults; if (defaults) { if (Ext.isFunction(defaults)) { defaults = defaults.call(this, config); } if (Ext.isString(config)) { config = Ext.ComponentManager.get(config); } Ext.applyIf(config, defaults); } return config; }, lookupComponent : function(comp) { return (typeof comp == 'string') ? Ext.ComponentManager.get(comp) : Ext.ComponentManager.create(comp, this.defaultType); }, getComponentId : function(comp) { return comp.getItemId && comp.getItemId(); }, add : function() { var me = this, args = Ext.Array.slice(arguments), index = (typeof args[0] == 'number') ? args.shift() : -1, layout = me.getLayout(), addingArray, items, i, length, item, pos, ret, needsLayout = false; if (args.length == 1 && Ext.isArray(args[0])) { items = args[0]; addingArray = true; } else { items = args; } if (me.rendered) { Ext.suspendLayouts(); } ret = items = me.prepareItems(items, true); length = items.length; if (!addingArray && length == 1) { ret = items[0]; } for (i = 0; i < length; i++) { item = items[i]; pos = (index < 0) ? me.items.length : (index + i); if (item.floating) { me.floatingItems.add(item); item.onAdded(me, pos); if (me.hasListeners.add) { me.fireEvent('add', me, item, pos); } } else if ((!me.hasListeners.beforeadd || me.fireEvent('beforeadd', me, item, pos) !== false) && me.onBeforeAdd(item) !== false) { me.items.insert(pos, item); item.onAdded(me, pos); me.onAdd(item, pos); layout.onAdd(item, pos); needsLayout = true; if (me.hasListeners.add) { me.fireEvent('add', me, item, pos); } } } if (needsLayout) { me.updateLayout(); } if (me.rendered) { Ext.resumeLayouts(true); } return ret; }, onAdd : Ext.emptyFn, onRemove : Ext.emptyFn, insert : function(index, comp) { var compIdx; if (comp && comp.isComponent) { compIdx = this.items.indexOf(comp); if (compIdx !== -1) { return this.move(compIdx, index); } } return this.add(index, comp); }, move : function(fromIdx, toIdx) { var items = this.items, item; if (fromIdx.isComponent) { fromIdx = items.indexOf(fromIdx); } item = items.removeAt(fromIdx); if (item === false) { return false; } items.insert(toIdx, item); this.onMove(item, fromIdx, toIdx); this.updateLayout(); return item; }, onMove: Ext.emptyFn, onBeforeAdd : function(item) { if (item.ownerCt && item.ownerCt !== this) { item.ownerCt.remove(item, false); } }, remove : function(comp, autoDestroy) { var me = this, c = me.getComponent(comp); if (c && (!me.hasListeners.beforeremove || me.fireEvent('beforeremove', me, c) !== false)) { me.doRemove(c, autoDestroy); if (me.hasListeners.remove) { me.fireEvent('remove', me, c); } if (!me.destroying && !c.floating) { me.updateLayout(); } } return c; }, doRemove : function(component, doDestroy) { doDestroy = doDestroy === true || (doDestroy !== false && this.autoDestroy); var me = this, layout = me.layout, hasLayout = layout && me.rendered, isDestroying = component.destroying || doDestroy, floating = component.floating; if (floating) { me.floatingItems.remove(component); } else { me.items.remove(component); } if (hasLayout && !floating) { if (layout.running) { Ext.AbstractComponent.cancelLayout(component, isDestroying); } layout.onRemove(component, isDestroying); } component.onRemoved(isDestroying); me.onRemove(component, isDestroying); if (doDestroy) { component.destroy(); } else { if (hasLayout && !floating) { layout.afterRemove(component); } if (me.detachOnRemove && component.rendered) { me.detachComponent(component); } } }, detachComponent: function(component){ Ext.getDetachedBody().appendChild(component.getEl()); }, removeAll : function(autoDestroy) { var me = this, removeItems = me.items.items.slice().concat(me.floatingItems.items), items = [], i = 0, len = removeItems.length, item; me.suspendLayouts(); for (; i < len; i++) { item = removeItems[i]; me.remove(item, autoDestroy); if (item.ownerCt !== me) { items.push(item); } } me.resumeLayouts(!!len); return items; }, getRefItems : function(deep) { var me = this, items = me.items.items, len = items.length, i = 0, item, result = []; for (; i < len; i++) { item = items[i]; result[result.length] = item; if (deep && item.getRefItems) { result.push.apply(result, item.getRefItems(true)); } } items = me.floatingItems.items; len = items.length; for (i = 0; i < len; i++) { item = items[i]; result[result.length] = item; if (deep && item.getRefItems) { result.push.apply(result, item.getRefItems(true)); } } return result; }, cascade : function(fn, scope, origArgs){ var me = this, cs = me.items ? me.items.items : [], len = cs.length, i = 0, c, args = origArgs ? origArgs.concat(me) : [me], componentIndex = args.length - 1; if (fn.apply(scope || me, args) !== false) { for (; i < len; i++){ c = cs[i]; if (c.cascade) { c.cascade(fn, scope, origArgs); } else { args[componentIndex] = c; fn.apply(scope || cs, args); } } } return this; }, isAncestor: function(possibleDescendant) { while (possibleDescendant) { if (possibleDescendant.ownerCt === this) { return true; } possibleDescendant = possibleDescendant.ownerCt; } }, getComponent : function(comp) { if (Ext.isObject(comp)) { comp = comp.getItemId(); } var c = this.items.get(comp); if (!c && typeof comp != 'number') { c = this.floatingItems.get(comp); } return c; }, contains: function(comp, deep) { var result = false; if (deep) { this.cascade(function(c) { if (c.contains && c.contains(comp)) { result = true; return false; } }); return result; } else { return this.items.contains(comp) || this.floatingItems.contains(comp); } }, nextChild: function(child, selector) { var me = this, result, childIndex = me.items.indexOf(child); if (childIndex !== -1) { result = selector ? Ext.ComponentQuery(selector, me.items.items.slice(childIndex + 1)) : me.items.getAt(childIndex + 1); if (!result && me.ownerCt) { result = me.ownerCt.nextChild(me, selector); } } return result; }, prevChild: function(child, selector) { var me = this, result, childIndex = me.items.indexOf(child); if (childIndex !== -1) { result = selector ? Ext.ComponentQuery(selector, me.items.items.slice(childIndex + 1)) : me.items.getAt(childIndex + 1); if (!result && me.ownerCt) { result = me.ownerCt.nextChild(me, selector); } } return result; }, enable: function() { this.callParent(arguments); var itemsToDisable = this.getChildItemsToDisable(), length = itemsToDisable.length, item, i; for (i = 0; i < length; i++) { item = itemsToDisable[i]; if (item.resetDisable) { item.enable(); } } return this; }, disable: function() { this.callParent(arguments); var itemsToDisable = this.getChildItemsToDisable(), length = itemsToDisable.length, item, i; for (i = 0; i < length; i++) { item = itemsToDisable[i]; if (item.resetDisable !== false && !item.disabled) { item.disable(); item.resetDisable = true; } } return this; }, getChildItemsToDisable: function(){ return this.query('[isFormField],button'); }, beforeDestroy : function() { var me = this, items = me.items, floatingItems = me.floatingItems, c; if (items) { while ((c = items.first())) { me.doRemove(c, true); } } if (floatingItems) { while ((c = floatingItems.first())) { me.doRemove(c, true); } } Ext.destroy( me.layout ); me.callParent(); } }); Ext.define('Ext.container.Container', { extend: Ext.container.AbstractContainer , alias: 'widget.container', alternateClassName: 'Ext.Container', getChildByElement: function(el, deep) { var item, itemEl, i = 0, it = this.getRefItems(), ln = it.length; el = Ext.getDom(el); for (; i < ln; i++) { item = it[i]; itemEl = item.getEl(); if (itemEl && ((itemEl.dom === el) || itemEl.contains(el))) { return (deep && item.getChildByElement) ? item.getChildByElement(el, deep) : item; } } return null; } }); Ext.define('Ext.layout.container.Editor', { alias: 'layout.editor', extend: Ext.layout.container.Container , autoSizeDefault: { width: 'field', height: 'field' }, sizePolicies: { $: { $: { readsWidth: 1, readsHeight: 1, setsWidth: 0, setsHeight: 0 }, boundEl: { readsWidth: 1, readsHeight: 0, setsWidth: 0, setsHeight: 1 } }, boundEl: { $: { readsWidth: 0, readsHeight: 1, setsWidth: 1, setsHeight: 0 }, boundEl: { readsWidth: 0, readsHeight: 0, setsWidth: 1, setsHeight: 1 } } }, getItemSizePolicy: function (item) { var me = this, autoSize = me.owner.autoSize, key = autoSize && autoSize.width, policy = me.sizePolicies; policy = policy[key] || policy.$; key = autoSize && autoSize.height; policy = policy[key] || policy.$; return policy; }, calculate: function(ownerContext) { var me = this, owner = me.owner, autoSize = owner.autoSize, fieldWidth, fieldHeight; if (autoSize === true) { autoSize = me.autoSizeDefault; } if (autoSize) { fieldWidth = me.getDimension(owner, autoSize.width, 'getWidth', owner.width); fieldHeight = me.getDimension(owner, autoSize.height, 'getHeight', owner.height); } ownerContext.childItems[0].setSize(fieldWidth, fieldHeight); ownerContext.setWidth(fieldWidth); ownerContext.setHeight(fieldHeight); ownerContext.setContentSize(fieldWidth || owner.field.getWidth(), fieldHeight || owner.field.getHeight()); }, getDimension: function(owner, type, getMethod, ownerSize){ switch (type) { case 'boundEl': return owner.boundEl[getMethod](); case 'field': return undefined; default: return ownerSize; } } }); Ext.define('Ext.Editor', { extend: Ext.container.Container , alias: 'widget.editor', layout: 'editor', allowBlur: true, revertInvalid: true, value : '', alignment: 'c-c?', offsets: [0, 0], shadow : 'frame', constrain : false, swallowKeys : true, completeOnEnter : true, cancelOnEsc : true, updateEl : false, focusOnToFront: false, hidden: true, baseCls: Ext.baseCSSPrefix + 'editor', initComponent : function() { var me = this, field = me.field = Ext.ComponentManager.create(me.field, 'textfield'); field.inEditor = true; field.msgTarget = field.msgTarget || 'qtip'; me.mon(field, { scope: me, blur: me.onFieldBlur, specialkey: me.onSpecialKey }); if (field.grow) { me.mon(field, 'autosize', me.onFieldAutosize, me, {delay: 1}); } me.floating = { constrain: me.constrain }; me.items = field; me.callParent(arguments); me.addEvents( 'beforestartedit', 'startedit', 'beforecomplete', 'complete', 'canceledit', 'specialkey' ); }, onFieldAutosize: function(){ this.updateLayout(); }, afterRender : function(ct, position) { var me = this, field = me.field, inputEl = field.inputEl; me.callParent(arguments); if (inputEl) { inputEl.dom.name = ''; if (me.swallowKeys) { inputEl.swallowEvent([ 'keypress', 'keydown' ]); } } }, onSpecialKey : function(field, event) { var me = this, key = event.getKey(), complete = me.completeOnEnter && key == event.ENTER, cancel = me.cancelOnEsc && key == event.ESC; if (complete || cancel) { event.stopEvent(); Ext.defer(function() { if (complete) { me.completeEdit(); } else { me.cancelEdit(); } }, 1); } me.fireEvent('specialkey', me, field, event); }, startEdit : function(el, value) { var me = this, field = me.field; me.completeEdit(); me.boundEl = Ext.get(el); value = Ext.isDefined(value) ? value : Ext.String.trim(me.boundEl.dom.innerText || me.boundEl.dom.innerHTML); if (!me.rendered) { if (me.ownerCt) { me.parentEl = me.ownerCt.el; me.parentEl.position(); } me.render(me.parentEl || document.body); } if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) { me.startValue = value; me.show(); field.suspendEvents(); field.reset(); field.setValue(value); field.resumeEvents(); me.realign(true); field.focus([field.getRawValue().length]); if (field.autoSize) { field.autoSize(); } me.editing = true; } }, realign : function(autoSize) { var me = this; if (autoSize === true) { me.updateLayout(); } me.alignTo(me.boundEl, me.alignment, me.offsets); }, completeEdit : function(remainVisible) { var me = this, field = me.field, value; if (!me.editing) { return; } if (field.assertValue) { field.assertValue(); } value = me.getValue(); if (!field.isValid()) { if (me.revertInvalid !== false) { me.cancelEdit(remainVisible); } return; } if (String(value) === String(me.startValue) && me.ignoreNoChange) { me.hideEdit(remainVisible); return; } if (me.fireEvent('beforecomplete', me, value, me.startValue) !== false) { value = me.getValue(); if (me.updateEl && me.boundEl) { me.boundEl.update(value); } me.hideEdit(remainVisible); me.fireEvent('complete', me, value, me.startValue); } }, onShow : function() { var me = this; me.callParent(arguments); if (me.hideEl !== false) { me.boundEl.hide(); } me.fireEvent('startedit', me, me.boundEl, me.startValue); }, cancelEdit : function(remainVisible) { var me = this, startValue = me.startValue, field = me.field, value; if (me.editing) { if (field) { value = me.editedValue = me.getValue(); field.suspendEvents(); me.setValue(startValue); field.resumeEvents(); } me.hideEdit(remainVisible); me.fireEvent('canceledit', me, value, startValue); delete me.editedValue; } }, hideEdit: function(remainVisible) { if (remainVisible !== true) { this.editing = false; this.hide(); } }, onFieldBlur : function(field, e) { var me = this, target = Ext.Element.getActiveElement(); if(me.allowBlur === true && me.editing && me.selectSameEditor !== true) { me.completeEdit(); } if (Ext.fly(target).isFocusable() || target.getAttribute('tabIndex')) { target.focus(); } }, onHide : function() { var me = this, field = me.field; if (me.editing) { me.completeEdit(); return; } if (field.hasFocus && field.triggerBlur) { field.triggerBlur(); } if (field.collapse) { field.collapse(); } if (me.hideEl !== false) { me.boundEl.show(); } me.callParent(arguments); }, setValue : function(value) { this.field.setValue(value); }, getValue : function() { return this.field.getValue(); }, beforeDestroy : function() { var me = this; Ext.destroy(me.field); delete me.field; delete me.parentEl; delete me.boundEl; me.callParent(arguments); } }); Ext.define('Ext.util.KeyMap', { alternateClassName: 'Ext.KeyMap', eventName: 'keydown', constructor: function(config) { var me = this; if ((arguments.length !== 1) || (typeof config === 'string') || config.dom || config.tagName || config === document || config.isComponent) { me.legacyConstructor.apply(me, arguments); return; } Ext.apply(me, config); me.bindings = []; if (!me.target.isComponent) { me.target = Ext.get(me.target); } if (me.binding) { me.addBinding(me.binding); } else if (config.key) { me.addBinding(config); } me.enable(); }, legacyConstructor: function(el, binding, eventName){ var me = this; Ext.apply(me, { target: Ext.get(el), eventName: eventName || me.eventName, bindings: [] }); if (binding) { me.addBinding(binding); } me.enable(); }, addBinding : function(binding){ var me = this, keyCode = binding.key, i, len; if (me.processing) { me.bindings = bindings.slice(0); } if (Ext.isArray(binding)) { for (i = 0, len = binding.length; i < len; i++) { me.addBinding(binding[i]); } return; } me.bindings.push(Ext.apply({ keyCode: me.processKeys(keyCode) }, binding)); }, removeBinding: function(binding){ var me = this, bindings = me.bindings, len = bindings.length, i, item, keys; if (me.processing) { me.bindings = bindings.slice(0); } keys = me.processKeys(binding.key); for (i = 0; i < len; ++i) { item = bindings[i]; if (item.fn === binding.fn && item.scope === binding.scope) { if (binding.alt == item.alt && binding.crtl == item.crtl && binding.shift == item.shift) { if (Ext.Array.equals(item.keyCode, keys)) { Ext.Array.erase(me.bindings, i, 1); return; } } } } }, processKeys: function(keyCode){ var processed = false, key, keys, keyString, len, i; if (Ext.isString(keyCode)) { keys = []; keyString = keyCode.toUpperCase(); for (i = 0, len = keyString.length; i < len; ++i){ keys.push(keyString.charCodeAt(i)); } keyCode = keys; processed = true; } if (!Ext.isArray(keyCode)) { keyCode = [keyCode]; } if (!processed) { for (i = 0, len = keyCode.length; i < len; ++i) { key = keyCode[i]; if (Ext.isString(key)) { keyCode[i] = key.toUpperCase().charCodeAt(0); } } } return keyCode; }, handleTargetEvent: (function() { var tagRe = /input|textarea/i; return function(event) { var me = this, bindings, i, len, target, contentEditable; if (me.enabled) { bindings = me.bindings; i = 0; len = bindings.length; event = me.processEvent.apply(me||me.processEventScope, arguments); if (me.ignoreInputFields) { target = event.target; contentEditable = target.contentEditable; if (tagRe.test(target.tagName) || (contentEditable === '' || contentEditable === 'true')) { return; } } if (!event.getKey) { return event; } me.processing = true; for(; i < len; ++i){ me.processBinding(bindings[i], event); } me.processing = false; } } }()), processEvent: Ext.identityFn, processBinding: function(binding, event){ if (this.checkModifiers(binding, event)) { var key = event.getKey(), handler = binding.fn || binding.handler, scope = binding.scope || this, keyCode = binding.keyCode, defaultEventAction = binding.defaultEventAction, i, len, keydownEvent = new Ext.EventObjectImpl(event); for (i = 0, len = keyCode.length; i < len; ++i) { if (key === keyCode[i]) { if (handler.call(scope, key, event) !== true && defaultEventAction) { keydownEvent[defaultEventAction](); } break; } } } }, checkModifiers: function(binding, e) { var keys = ['shift', 'ctrl', 'alt'], i = 0, len = keys.length, val, key; for (; i < len; ++i){ key = keys[i]; val = binding[key]; if (!(val === undefined || (val === e[key + 'Key']))) { return false; } } return true; }, on: function(key, fn, scope) { var keyCode, shift, ctrl, alt; if (Ext.isObject(key) && !Ext.isArray(key)) { keyCode = key.key; shift = key.shift; ctrl = key.ctrl; alt = key.alt; } else { keyCode = key; } this.addBinding({ key: keyCode, shift: shift, ctrl: ctrl, alt: alt, fn: fn, scope: scope }); }, un: function(key, fn, scope) { var keyCode, shift, ctrl, alt; if (Ext.isObject(key) && !Ext.isArray(key)) { keyCode = key.key; shift = key.shift; ctrl = key.ctrl; alt = key.alt; } else { keyCode = key; } this.removeBinding({ key: keyCode, shift: shift, ctrl: ctrl, alt: alt, fn: fn, scope: scope }); }, isEnabled : function() { return this.enabled; }, enable: function() { var me = this; if (!me.enabled) { me.target.on(me.eventName, me.handleTargetEvent, me); me.enabled = true; } }, disable: function() { var me = this; if (me.enabled) { me.target.removeListener(me.eventName, me.handleTargetEvent, me); me.enabled = false; } }, setDisabled : function(disabled) { if (disabled) { this.disable(); } else { this.enable(); } }, destroy: function(removeTarget) { var me = this, target = me.target; me.bindings = []; me.disable(); if (removeTarget === true) { if (target.isComponent) { target.destroy(); } else { target.remove(); } } delete me.target; } }); Ext.define('Ext.util.KeyNav', { alternateClassName: 'Ext.KeyNav', statics: { keyOptions: { left: 37, right: 39, up: 38, down: 40, space: 32, pageUp: 33, pageDown: 34, del: 46, backspace: 8, home: 36, end: 35, enter: 13, esc: 27, tab: 9 } }, constructor: function(config) { var me = this; if (arguments.length === 2) { me.legacyConstructor.apply(me, arguments); return; } me.setConfig(config); }, legacyConstructor: function(el, config) { this.setConfig(Ext.apply({ target: el }, config)); }, setConfig: function(config) { var me = this, keymapCfg = { target: config.target, ignoreInputFields: config.ignoreInputFields, eventName: me.getKeyEvent('forceKeyDown' in config ? config.forceKeyDown : me.forceKeyDown, config.eventName) }, map, keyCodes, defaultScope, keyName, binding; if (me.map) { me.map.destroy(); } if (config.processEvent) { keymapCfg.processEvent = config.processEvent; keymapCfg.processEventScope = config.processEventScope||me; } if (config.keyMap) { map = me.map = config.keyMap; } else { map = me.map = new Ext.util.KeyMap(keymapCfg); me.destroyKeyMap = true; } keyCodes = Ext.util.KeyNav.keyOptions; defaultScope = config.scope || me; for (keyName in keyCodes) { if (keyCodes.hasOwnProperty(keyName)) { if (binding = config[keyName]) { if (typeof binding === 'function') { binding = { handler: binding, defaultEventAction: (config.defaultEventAction !== undefined) ? config.defaultEventAction : me.defaultEventAction }; } map.addBinding({ key: keyCodes[keyName], handler: Ext.Function.bind(me.handleEvent, binding.scope||defaultScope, binding.handler||binding.fn, true), defaultEventAction: (binding.defaultEventAction !== undefined) ? binding.defaultEventAction : me.defaultEventAction }); } } } map.disable(); if (!config.disabled) { map.enable(); } }, handleEvent: function(keyCode, event, handler){ return handler.call(this, event); }, disabled: false, defaultEventAction: "stopEvent", forceKeyDown: false, eventName: 'keypress', destroy: function(removeEl) { if (this.destroyKeyMap) { this.map.destroy(removeEl); } delete this.map; }, enable: function() { if (this.map) { this.map.enable(); this.disabled = false; } }, disable: function() { if (this.map) { this.map.disable(); } this.disabled = true; }, setDisabled : function(disabled) { this.map.setDisabled(disabled); this.disabled = disabled; }, getKeyEvent: function(forceKeyDown, configuredEventName) { if (forceKeyDown || (Ext.EventManager.useKeyDown && !configuredEventName)) { return 'keydown'; } else { return configuredEventName||this.eventName; } } }); Ext.define('Ext.FocusManager', { singleton: true, alternateClassName: ['Ext.FocusMgr' ], mixins: { observable: Ext.util.Observable }, enabled: false, focusElementCls: Ext.baseCSSPrefix + 'focus-element', focusFrameCls: Ext.baseCSSPrefix + 'focus-frame', whitelist: [ 'textfield' ], constructor: function(config) { var me = this, CQ = Ext.ComponentQuery; me.mixins.observable.constructor.call(me, config); me.addEvents( 'beforecomponentfocus', 'componentfocus', 'disable', 'enable' ); me.focusTask = new Ext.util.DelayedTask(me.handleComponentFocus, me); Ext.override(Ext.AbstractComponent, { onFocus: function() { this.callParent(arguments); if (me.enabled && this.hasFocus) { Array.prototype.unshift.call(arguments, this); me.onComponentFocus.apply(me, arguments); } }, onBlur: function() { this.callParent(arguments); if (me.enabled && !this.hasFocus) { Array.prototype.unshift.call(arguments, this); me.onComponentBlur.apply(me, arguments); } }, onDestroy: function() { this.callParent(arguments); if (me.enabled) { Array.prototype.unshift.call(arguments, this); me.onComponentDestroy.apply(me, arguments); } } }); Ext.override(Ext.Component, { afterHide: function() { this.callParent(arguments); if (me.enabled) { Array.prototype.unshift.call(arguments, this); me.onComponentHide.apply(me, arguments); } } }); me.keyNav = new Ext.util.KeyNav(Ext.getDoc(), { disabled: true, scope: me, backspace: me.focusLast, enter: me.navigateIn, esc: me.navigateOut, tab: me.navigateSiblings, space: me.navigateIn, del: me.focusLast, left: me.navigateSiblings, right: me.navigateSiblings, down: me.navigateSiblings, up: me.navigateSiblings }); me.focusData = {}; me.subscribers = new Ext.util.HashMap(); me.focusChain = {}; Ext.apply(CQ.pseudos, { nextFocus: function(cmps, idx, step) { step = step || 1; idx = parseInt(idx, 10); var len = cmps.length, i = idx, c; for (;;) { if ((i += step) >= len) { i = 0; } else if (i < 0) { i = len - 1; } if (i === idx) { return []; } if ((c = cmps[i]).isFocusable()) { return [c]; } } return []; }, prevFocus: function(cmps, idx) { return this.nextFocus(cmps, idx, -1); }, root: function(cmps) { var len = cmps.length, results = [], i = 0, c; for (; i < len; i++) { c = cmps[i]; if (!c.ownerCt) { results.push(c); } } return results; } }); }, addXTypeToWhitelist: function(xtype) { var me = this; if (Ext.isArray(xtype)) { Ext.Array.forEach(xtype, me.addXTypeToWhitelist, me); return; } if (!Ext.Array.contains(me.whitelist, xtype)) { me.whitelist.push(xtype); } }, clearComponent: function(cmp) { clearTimeout(this.cmpFocusDelay); if (!cmp.isDestroyed) { cmp.blur(); } }, disable: function() { var me = this; if (!me.enabled) { return; } delete me.options; me.enabled = false; me.removeDOM(); me.keyNav.disable(); me.fireEvent('disable', me); }, enable: function(options) { var me = this; if (options === true) { options = { focusFrame: true }; } me.options = options = options || {}; if (me.enabled) { return; } me.enabled = true; me.initDOM(options); me.keyNav.enable(); me.focusEl.focus(); delete me.focusedCmp; me.fireEvent('enable', me); }, focusLast: function(e) { var me = this; if (me.isWhitelisted(me.focusedCmp)) { return true; } if (me.previousFocusedCmp) { me.previousFocusedCmp.focus(); } }, getRootComponents: function() { var CQ = Ext.ComponentQuery, inline = CQ.query(':focusable:root:not([floating])'), floating = CQ.query(':focusable:root[floating]'); floating.sort(function(a, b) { return a.el.getZIndex() > b.el.getZIndex(); }); return floating.concat(inline); }, initDOM: function(options) { var me = this, cls = me.focusFrameCls, needListeners = Ext.ComponentQuery.query('{getFocusEl()}:not([focusListenerAdded])'), i = 0, len = needListeners.length; if (!Ext.isReady) { return Ext.onReady(me.initDOM, me); } for (; i < len; i++) { needListeners[i].addFocusListener(); } if (!me.focusEl) { me.focusEl = Ext.getBody(); me.focusEl.dom.tabIndex = -1; } if (!me.focusFrame && options.focusFrame) { me.focusFrame = Ext.getBody().createChild({ cls: cls, children: [ { cls: cls + '-top' }, { cls: cls + '-bottom' }, { cls: cls + '-left' }, { cls: cls + '-right' } ], style: 'top: -100px; left: -100px;' }); me.focusFrame.setVisibilityMode(Ext.Element.DISPLAY); me.focusFrame.hide().setLocalXY(0, 0); } }, isWhitelisted: function(cmp) { return cmp && Ext.Array.some(this.whitelist, function(x) { return cmp.isXType(x); }); }, navigateIn: function(e) { var me = this, focusedCmp = me.focusedCmp, defaultRoot, firstChild; if (me.isWhitelisted(focusedCmp)) { return true; } if (!focusedCmp) { defaultRoot = me.getRootComponents()[0]; if (defaultRoot) { if (defaultRoot.getFocusEl() === me.focusEl) { me.focusEl.blur(); } defaultRoot.focus(); } } else { firstChild = focusedCmp.hasFocus ? Ext.ComponentQuery.query('>:focusable', focusedCmp)[0] : focusedCmp; if (firstChild) { firstChild.focus(); } else { if (Ext.isFunction(focusedCmp.onClick)) { e.button = 0; focusedCmp.onClick(e); if (focusedCmp.isVisible(true)) { focusedCmp.focus(); } else { me.navigateOut(); } } } } }, navigateOut: function(e) { var me = this, parent; if (!me.focusedCmp || !(parent = me.focusedCmp.up(':focusable'))) { me.focusEl.focus(); } else { parent.focus(); } return true; }, navigateSiblings: function(e, source, parent) { var me = this, src = source || me, key = e.getKey(), EO = Ext.EventObject, goBack = e.shiftKey || key == EO.LEFT || key == EO.UP, checkWhitelist = key == EO.LEFT || key == EO.RIGHT || key == EO.UP || key == EO.DOWN, nextSelector = goBack ? 'prev' : 'next', idx, next, focusedCmp, siblings; focusedCmp = (src.focusedCmp && src.focusedCmp.comp) || src.focusedCmp; if (!focusedCmp && !parent) { return true; } if (checkWhitelist && me.isWhitelisted(focusedCmp)) { return true; } if (!focusedCmp || focusedCmp.is(':root')) { siblings = me.getRootComponents(); } else { parent = parent || focusedCmp.up(); if (parent) { siblings = parent.getRefItems(); } } if (siblings) { idx = focusedCmp ? Ext.Array.indexOf(siblings, focusedCmp) : -1; next = Ext.ComponentQuery.query(':' + nextSelector + 'Focus(' + idx + ')', siblings)[0]; if (next && focusedCmp !== next) { next.focus(); return next; } } }, onComponentBlur: function(cmp, e) { var me = this; if (me.focusedCmp === cmp) { me.previousFocusedCmp = cmp; delete me.focusedCmp; } if (me.focusFrame) { me.focusFrame.hide(); } }, onComponentFocus: function(cmp, e) { var me = this, chain = me.focusChain, parent; if (!cmp.isFocusable()) { me.clearComponent(cmp); if (chain[cmp.id]) { return; } parent = cmp.up(); if (parent) { chain[cmp.id] = true; parent.focus(); } return; } me.focusChain = {}; me.focusTask.delay(10, null, null, [cmp, cmp.getFocusEl()]); }, handleComponentFocus: function(cmp, focusEl) { var me = this, cls, ff, box, bt, bl, bw, bh, ft, fb, fl, fr; if (me.fireEvent('beforecomponentfocus', me, cmp, me.previousFocusedCmp) === false) { me.clearComponent(cmp); return; } me.focusedCmp = cmp; if (me.shouldShowFocusFrame(cmp)) { cls = '.' + me.focusFrameCls + '-'; ff = me.focusFrame; box = (focusEl.dom ? focusEl : focusEl.el).getBox(); bt = box.top; bl = box.left; bw = box.width; bh = box.height; ft = ff.child(cls + 'top'); fb = ff.child(cls + 'bottom'); fl = ff.child(cls + 'left'); fr = ff.child(cls + 'right'); ft.setWidth(bw).setLocalXY(bl, bt); fb.setWidth(bw).setLocalXY(bl, bt + bh - 2); fl.setHeight(bh - 2).setLocalXY(bl, bt + 2); fr.setHeight(bh - 2).setLocalXY(bl + bw - 2, bt + 2); ff.show(); } me.fireEvent('componentfocus', me, cmp, me.previousFocusedCmp); }, onComponentHide: function(cmp) { var me = this, cmpHadFocus = false, focusedCmp = me.focusedCmp, parent; if (focusedCmp) { cmpHadFocus = cmp.hasFocus || (cmp.isContainer && cmp.isAncestor(me.focusedCmp)); } me.clearComponent(cmp); if (cmpHadFocus && (parent = cmp.up(':focusable'))) { parent.focus(); } else { me.focusEl.focus(); } }, onComponentDestroy: function() { }, removeDOM: function() { var me = this; if (me.enabled || me.subscribers.length) { return; } Ext.destroy( me.focusFrame ); delete me.focusEl; delete me.focusFrame; }, removeXTypeFromWhitelist: function(xtype) { var me = this; if (Ext.isArray(xtype)) { Ext.Array.forEach(xtype, me.removeXTypeFromWhitelist, me); return; } Ext.Array.remove(me.whitelist, xtype); }, setupSubscriberKeys: function(container, keys) { var me = this, el = container.getFocusEl(), scope = keys.scope, handlers = { backspace: me.focusLast, enter: me.navigateIn, esc: me.navigateOut, scope: me }, navSiblings = function(e) { if (me.focusedCmp === container) { return me.navigateSiblings(e, me, container); } else { return me.navigateSiblings(e); } }; Ext.iterate(keys, function(key, cb) { handlers[key] = function(e) { var ret = navSiblings(e); if (Ext.isFunction(cb) && cb.call(scope || container, e, ret) === true) { return true; } return ret; }; }, me); return new Ext.util.KeyNav(el, handlers); }, shouldShowFocusFrame: function(cmp) { var me = this, opts = me.options || {}; if (!me.focusFrame || !cmp) { return false; } if (opts.focusFrame) { return true; } if (me.focusData[cmp.id].focusFrame) { return true; } return false; } }); Ext.define('Ext.Img', { extend: Ext.Component , alias: ['widget.image', 'widget.imagecomponent'], autoEl: 'img', baseCls: Ext.baseCSSPrefix + 'img', src: '', alt: '', title: '', imgCls: '', ariaRole: 'img', initComponent: function() { if (this.glyph) { this.autoEl = 'div'; } this.callParent(); }, getElConfig: function() { var me = this, autoEl = me.autoEl, config = me.callParent(), glyphFontFamily = Ext._glyphFontFamily, glyph = me.glyph, img, glyphParts; if (autoEl === 'img' || (Ext.isObject(autoEl) && autoEl.tag === 'img')) { img = config; } else if (me.glyph) { if (typeof glyph === 'string') { glyphParts = glyph.split('@'); glyph = glyphParts[0]; glyphFontFamily = glyphParts[1]; } config.html = '&#' + glyph + ';'; if (glyphFontFamily) { config.style = 'font-family:' + glyphFontFamily; } } else { config.cn = [img = { tag: 'img', role: me.ariaRole, id: me.id + '-img' }]; } if (img) { if (me.imgCls) { img.cls = (img.cls ? img.cls + ' ' : '') + me.imgCls; } img.src = me.src || Ext.BLANK_IMAGE_URL; } if (me.alt) { (img || config).alt = me.alt; } if (me.title) { (img || config).title = me.title; } return config; }, onRender: function () { var me = this, autoEl = me.autoEl, el; me.callParent(arguments); el = me.el; if (autoEl === 'img' || (Ext.isObject(autoEl) && autoEl.tag === 'img')) { me.imgEl = el; } else { me.imgEl = el.getById(me.id + '-img'); } }, onDestroy: function () { Ext.destroy(this.imgEl); this.imgEl = null; this.callParent(); }, setSrc: function(src) { var me = this, imgEl = me.imgEl; me.src = src; if (imgEl) { imgEl.dom.src = src || Ext.BLANK_IMAGE_URL; } }, setGlyph: function(glyph) { var me = this, glyphFontFamily = Ext._glyphFontFamily, glyphParts, dom; if (glyph != me.glyph) { if (typeof glyph === 'string') { glyphParts = glyph.split('@'); glyph = glyphParts[0]; glyphFontFamily = glyphParts[1]; } dom = me.el.dom; dom.innerHTML = '&#' + glyph + ';'; if (glyphFontFamily) { dom.style = 'font-family:' + glyphFontFamily; } } } }); Ext.define('Ext.util.Bindable', { bindStore: function(store, initial, propertyName) { propertyName = propertyName || 'store'; var me = this, oldStore = me[propertyName]; if (!initial && oldStore) { me.onUnbindStore(oldStore, initial, propertyName); if (store !== oldStore && oldStore.autoDestroy) { oldStore.destroyStore(); } else { me.unbindStoreListeners(oldStore); } } if (store) { store = Ext.data.StoreManager.lookup(store); me.bindStoreListeners(store); me.onBindStore(store, initial, propertyName); } me[propertyName] = store || null; return me; }, getStore: function(){ return this.store; }, unbindStoreListeners: function(store) { var listeners = this.storeListeners; if (listeners) { store.un(listeners); } }, bindStoreListeners: function(store) { var me = this, listeners = Ext.apply({}, me.getStoreListeners(store)); if (!listeners.scope) { listeners.scope = me; } me.storeListeners = listeners; store.on(listeners); }, getStoreListeners: Ext.emptyFn, onUnbindStore: Ext.emptyFn, onBindStore: Ext.emptyFn }); Ext.define('Ext.LoadMask', { extend: Ext.Component , alias: 'widget.loadmask', mixins: { floating: Ext.util.Floating , bindable: Ext.util.Bindable }, msg : 'Loading...', msgCls : Ext.baseCSSPrefix + 'mask-loading', maskCls: Ext.baseCSSPrefix + 'mask', useMsg: true, useTargetEl: false, baseCls: Ext.baseCSSPrefix + 'mask-msg', ariaRole: 'presentation', childEls: [ 'msgEl', 'msgTextEl' ], renderTpl: [ '
{ariaAttr}', ' class="{[values.$comp.msgCls]} ', Ext.baseCSSPrefix, 'mask-msg-inner{childElCls}">', '
', '
' ], floating: { shadow: 'frame' }, focusOnToFront: false, bringParentToFront: false, constructor : function(config) { var me = this, comp; if (arguments.length === 2) { comp = config; config = arguments[1]; } else { comp = config.target; } if (!comp.isComponent) { comp = Ext.get(comp); this.isElement = true; } me.ownerCt = comp; if (!this.isElement) { me.bindComponent(comp); } me.callParent([config]); if (me.store) { me.bindStore(me.store, true); } }, bindComponent: function(comp) { var me = this, listeners = { scope: this, resize: me.sizeMask, added: me.onComponentAdded, removed: me.onComponentRemoved }; if (comp.floating) { listeners.move = me.sizeMask; me.activeOwner = comp; } else if (comp.ownerCt) { me.onComponentAdded(comp.ownerCt); } else { me.preventBringToFront = true; } me.mon(comp, listeners); me.mon(me.hierarchyEventSource, { show: me.onContainerShow, hide: me.onContainerHide, expand: me.onContainerExpand, collapse: me.onContainerCollapse, scope: me }); }, onComponentAdded: function(owner) { var me = this; delete me.activeOwner; me.floatParent = owner; if (!owner.floating) { owner = owner.up('[floating]'); } if (owner) { me.activeOwner = owner; me.mon(owner, 'move', me.sizeMask, me); } else { me.preventBringToFront = true; } owner = me.floatParent.ownerCt; if (me.rendered && me.isVisible() && owner) { me.floatOwner = owner; me.mon(owner, 'afterlayout', me.sizeMask, me, {single: true}); } }, onComponentRemoved: function(owner) { var me = this, activeOwner = me.activeOwner, floatOwner = me.floatOwner; if (activeOwner) { me.mun(activeOwner, 'move', me.sizeMask, me); } if (floatOwner) { me.mun(floatOwner, 'afterlayout', me.sizeMask, me); } delete me.activeOwner; delete me.floatOwner; }, afterRender: function() { this.callParent(arguments); this.container = this.floatParent.getContentTarget(); }, onContainerShow: function(container) { if (this.isActiveContainer(container)) { this.onComponentShow(); } }, onContainerHide: function(container) { if (this.isActiveContainer(container)) { this.onComponentHide(); } }, onContainerExpand: function(container) { if (this.isActiveContainer(container)) { this.onComponentShow(); } }, onContainerCollapse: function(container) { if (this.isActiveContainer(container)) { this.onComponentHide(); } }, isActiveContainer: function(container) { return this.isDescendantOf(container); }, onComponentHide: function() { var me = this; if (me.rendered && me.isVisible()) { me.hide(); me.showNext = true; } }, onComponentShow: function() { if (this.showNext) { this.show(); } delete this.showNext; }, sizeMask: function() { var me = this, target; if (me.rendered && me.isVisible()) { me.center(); target = me.getMaskTarget(); me.getMaskEl().show().setSize(target.getSize()).alignTo(target, 'tl-tl'); } }, bindStore : function(store, initial) { var me = this; me.mixins.bindable.bindStore.apply(me, arguments); store = me.store; if (store && store.isLoading()) { me.onBeforeLoad(); } }, getStoreListeners: function(store) { var load = this.onLoad, beforeLoad = this.onBeforeLoad, result = { cachemiss: beforeLoad, cachefilled: load }; if (!store.proxy.isSynchronous) { result.beforeLoad = beforeLoad; result.load = load; } return result; }, onDisable : function() { this.callParent(arguments); if (this.loading) { this.onLoad(); } }, getOwner: function() { return this.ownerCt || this.floatParent; }, getMaskTarget: function() { var owner = this.getOwner(); return this.useTargetEl ? owner.getTargetEl() : owner.getEl(); }, onBeforeLoad : function() { var me = this, owner = me.getOwner(), origin; if (!me.disabled) { me.loading = true; if (owner.componentLayoutCounter) { me.maybeShow(); } else { origin = owner.afterComponentLayout; owner.afterComponentLayout = function() { owner.afterComponentLayout = origin; origin.apply(owner, arguments); me.maybeShow(); }; } } }, maybeShow: function() { var me = this, owner = me.getOwner(); if (!owner.isVisible(true)) { me.showNext = true; } else if (me.loading && owner.rendered) { me.show(); } }, getMaskEl: function(){ var me = this; return me.maskEl || (me.maskEl = me.el.insertSibling({ role: 'presentation', cls: me.maskCls, style: { zIndex: me.el.getStyle('zIndex') - 2 } }, 'before')); }, onShow: function() { var me = this, msgEl = me.msgEl; me.callParent(arguments); me.loading = true; if (me.useMsg) { msgEl.show(); me.msgTextEl.update(me.msg); } else { msgEl.parent().hide(); } }, hide: function() { if (this.isElement) { this.ownerCt.unmask(); this.fireEvent('hide', this); return; } delete this.showNext; return this.callParent(arguments); }, onHide: function() { this.callParent(); this.getMaskEl().hide(); }, show: function() { if (this.isElement) { this.ownerCt.mask(this.useMsg ? this.msg : '', this.msgCls); this.fireEvent('show', this); return; } return this.callParent(arguments); }, afterShow: function() { this.callParent(arguments); this.sizeMask(); }, setZIndex: function(index) { var me = this, owner = me.activeOwner; if (owner) { index = parseInt(owner.el.getStyle('zIndex'), 10) + 1; } me.getMaskEl().setStyle('zIndex', index - 1); return me.mixins.floating.setZIndex.apply(me, arguments); }, onLoad : function() { this.loading = false; this.hide(); }, onDestroy: function() { var me = this; if (me.isElement) { me.ownerCt.unmask(); } Ext.destroy(me.maskEl); me.callParent(); } }); Ext.define('Ext.data.association.Association', { alternateClassName: 'Ext.data.Association', primaryKey: 'id', associationKeyFunction : null, defaultReaderType: 'json', isAssociation: true, initialConfig: null, statics: { AUTO_ID: 1000, create: function(association){ if (Ext.isString(association)) { association = { type: association }; } switch (association.type) { case 'belongsTo': return new Ext.data.association.BelongsTo(association); case 'hasMany': return new Ext.data.association.HasMany(association); case 'hasOne': return new Ext.data.association.HasOne(association); default: } return association; } }, constructor: function(config) { Ext.apply(this, config); var me = this, types = Ext.ModelManager.types, ownerName = config.ownerModel, associatedName = config.associatedModel, ownerModel = types[ownerName], associatedModel = types[associatedName], associationKey = config.associationKey, keyReIdx; if (associationKey) { keyReIdx = String(associationKey).search(/[\[\.]/); if (keyReIdx >= 0) { me.associationKeyFunction = Ext.functionFactory('obj', 'return obj' + (keyReIdx > 0 ? '.' : '') + associationKey); } } me.initialConfig = config; me.ownerModel = ownerModel; me.associatedModel = associatedModel; Ext.applyIf(me, { ownerName : ownerName, associatedName: associatedName }); me.associationId = 'association' + (++me.statics().AUTO_ID); }, getReader: function(){ var me = this, reader = me.reader, model = me.associatedModel; if (reader) { if (Ext.isString(reader)) { reader = { type: reader }; } if (reader.isReader) { reader.setModel(model); } else { Ext.applyIf(reader, { model: model, type : me.defaultReaderType }); } me.reader = Ext.createByAlias('reader.' + reader.type, reader); } return me.reader || null; } }); Ext.define('Ext.ModelManager', { extend: Ext.AbstractManager , alternateClassName: 'Ext.ModelMgr', singleton: true, typeName: 'mtype', associationStack: [], registerType: function(name, config) { var proto = config.prototype, model; if (proto && proto.isModel) { model = config; } else { if (!config.extend) { config.extend = 'Ext.data.Model'; } model = Ext.define(name, config); } this.types[name] = model; return model; }, unregisterType: function(name) { delete this.types[name]; }, onModelDefined: function(model) { var stack = this.associationStack, length = stack.length, create = [], association, i, created; for (i = 0; i < length; i++) { association = stack[i]; if (association.associatedModel == model.modelName) { create.push(association); } } for (i = 0, length = create.length; i < length; i++) { created = create[i]; this.types[created.ownerModel].prototype.associations.add(Ext.data.association.Association.create(created)); Ext.Array.remove(stack, created); } }, registerDeferredAssociation: function(association){ this.associationStack.push(association); }, getModel: function(id) { var model = id; if (typeof model == 'string') { model = this.types[model]; } return model; }, create: function(config, name, id) { var Con = typeof name == 'function' ? name : this.types[name || config.name]; return new Con(config, id); } }, function() { Ext.regModel = function() { return this.ModelManager.registerType.apply(this.ModelManager, arguments); }; }); Ext.define('Ext.layout.component.ProgressBar', { alias: ['layout.progressbar'], extend: Ext.layout.component.Auto , type: 'progressbar', beginLayout: function (ownerContext) { var me = this, i, textEls; me.callParent(arguments); if (!ownerContext.textEls) { textEls = me.owner.textEl; if (textEls.isComposite) { ownerContext.textEls = []; textEls = textEls.elements; for (i = textEls.length; i--; ) { ownerContext.textEls[i] = ownerContext.getEl(Ext.get(textEls[i])); } } else { ownerContext.textEls = [ ownerContext.getEl('textEl') ]; } } }, calculate: function(ownerContext) { var me = this, i, textEls, width; me.callParent(arguments); if (Ext.isNumber(width = ownerContext.getProp('width'))) { width -= ownerContext.getBorderInfo().width; textEls = ownerContext.textEls; for (i = textEls.length; i--; ) { textEls[i].setWidth(width); } } else { me.done = false; } } }); Ext.define('Ext.ProgressBar', { extend: Ext.Component , alias: 'widget.progressbar', baseCls: Ext.baseCSSPrefix + 'progress', animate: false, text: '', waitTimer: null, childEls: [ 'bar' ], renderTpl: [ '', '
{text}
', '
', '' ], componentLayout: 'progressbar', ariaRole: 'progressbar', initComponent: function() { this.callParent(); this.addEvents( "update" ); }, initRenderData: function() { var me = this; return Ext.apply(me.callParent(), { internalText : !me.hasOwnProperty('textEl'), text : me.text || ' ', percentage : me.value ? me.value * 100 : 0 }); }, onRender : function() { var me = this; me.callParent(arguments); if (me.textEl) { me.textEl = Ext.get(me.textEl); me.updateText(me.text); } else { me.textEl = me.el.select('.' + me.baseCls + '-text'); } }, updateProgress: function(value, text, animate) { var me = this, oldValue = me.value; me.value = value || 0; if (text) { me.updateText(text); } if (me.rendered && !me.isDestroyed) { if (animate === true || (animate !== false && me.animate)) { me.bar.stopAnimation(); me.bar.animate(Ext.apply({ from: { width: (oldValue * 100) + '%' }, to: { width: (me.value * 100) + '%' } }, me.animate)); } else { me.bar.setStyle('width', (me.value * 100) + '%'); } } me.fireEvent('update', me, me.value, text); return me; }, updateText: function(text) { var me = this; me.text = text; if (me.rendered) { me.textEl.update(me.text); } return me; }, applyText : function(text) { this.updateText(text); }, getText: function(){ return this.text; }, wait: function(o) { var me = this, scope; if (!me.waitTimer) { scope = me; o = o || {}; me.updateText(o.text); me.waitTimer = Ext.TaskManager.start({ run: function(i){ var inc = o.increment || 10; i -= 1; me.updateProgress(((((i+inc)%inc)+1)*(100/inc))*0.01, null, o.animate); }, interval: o.interval || 1000, duration: o.duration, onStop: function(){ if (o.fn) { o.fn.apply(o.scope || me); } me.reset(); }, scope: scope }); } return me; }, isWaiting: function(){ return this.waitTimer !== null; }, reset: function(hide){ var me = this; me.updateProgress(0); me.clearTimer(); if (hide === true) { me.hide(); } return me; }, clearTimer: function(){ var me = this; if (me.waitTimer) { me.waitTimer.onStop = null; Ext.TaskManager.stop(me.waitTimer); me.waitTimer = null; } }, onDestroy: function(){ var me = this, bar = me.bar; me.clearTimer(); if (me.rendered) { if (me.textEl.isComposite) { me.textEl.clear(); } Ext.destroyMembers(me, 'textEl', 'progressBar'); if (bar && me.animate) { bar.stopAnimation(); } } me.callParent(); } }); Ext.define('Ext.ShadowPool', { singleton: true, markup: (function() { return Ext.String.format( '', Ext.baseCSSPrefix, Ext.isIE && !Ext.supports.CSS3BoxShadow ? 'ie' : 'css' ); }()), shadows: [], pull: function() { var sh = this.shadows.shift(); if (!sh) { sh = Ext.get(Ext.DomHelper.insertHtml("beforeBegin", document.body.firstChild, this.markup)); sh.autoBoxAdjust = false; } return sh; }, push: function(sh) { this.shadows.push(sh); }, reset: function() { var shadows = [].concat(this.shadows), s, sLen = shadows.length; for (s = 0; s < sLen; s++) { shadows[s].remove(); } this.shadows = []; } }); Ext.define('Ext.Shadow', { localXYNames: { get: 'getLocalXY', set: 'setLocalXY' }, constructor: function(config) { var me = this, adjusts, offset, rad; Ext.apply(me, config); if (!Ext.isString(me.mode)) { me.mode = me.defaultMode; } offset = me.offset; rad = Math.floor(offset / 2); me.opacity = 50; switch (me.mode.toLowerCase()) { case "drop": if (Ext.supports.CSS3BoxShadow) { adjusts = { t: offset, l: offset, h: -offset, w: -offset }; } else { adjusts = { t: -rad, l: -rad, h: -rad, w: -rad }; } break; case "sides": if (Ext.supports.CSS3BoxShadow) { adjusts = { t: offset, l: 0, h: -offset, w: 0 }; } else { adjusts = { t: - (1 + rad), l: 1 + rad - 2 * offset, h: -1, w: rad - 1 }; } break; case "frame": if (Ext.supports.CSS3BoxShadow) { adjusts = { t: 0, l: 0, h: 0, w: 0 }; } else { adjusts = { t: 1 + rad - 2 * offset, l: 1 + rad - 2 * offset, h: offset - rad - 1, w: offset - rad - 1 }; } break; case "bottom": if (Ext.supports.CSS3BoxShadow) { adjusts = { t: offset, l: 0, h: -offset, w: 0 }; } else { adjusts = { t: offset, l: 0, h: 0, w: 0 }; } break; } me.adjusts = adjusts; }, getShadowSize: function() { var me = this, offset = me.el ? me.offset : 0, result = [offset, offset, offset, offset], mode = me.mode.toLowerCase(); if (me.el && mode !== 'frame') { result[0] = 0; if (mode == 'drop') { result[3] = 0; } } return result; }, offset: 4, defaultMode: "drop", boxShadowProperty: (function() { var property = 'boxShadow', style = document.documentElement.style; if (!('boxShadow' in style)) { if ('WebkitBoxShadow' in style) { property = 'WebkitBoxShadow'; } else if ('MozBoxShadow' in style) { property = 'MozBoxShadow'; } } return property; }()), show: function(target) { var me = this, index, xy; target = Ext.get(target); index = (parseInt(target.getStyle("z-index"), 10) - 1) || 0; xy = target[me.localXYNames.get](); if (!me.el) { me.el = Ext.ShadowPool.pull(); if (me.fixed) { me.el.dom.style.position = 'fixed'; } else { me.el.dom.style.position = ''; } if (me.el.dom.nextSibling != target.dom) { me.el.insertBefore(target); } } me.el.setStyle("z-index", me.zIndex || index); if (Ext.isIE && !Ext.supports.CSS3BoxShadow) { me.el.dom.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=" + me.opacity + ") progid:DXImageTransform.Microsoft.Blur(pixelradius=" + (me.offset) + ")"; } me.realign( xy[0], xy[1], target.dom.offsetWidth, target.dom.offsetHeight ); me.el.dom.style.display = "block"; }, isVisible: function() { return this.el ? true: false; }, realign: function(l, t, targetWidth, targetHeight) { if (!this.el) { return; } var adjusts = this.adjusts, el = this.el, targetStyle = el.dom.style, shadowWidth, shadowHeight, sws, shs; el[this.localXYNames.set](l + adjusts.l, t + adjusts.t); shadowWidth = Math.max(targetWidth + adjusts.w, 0); shadowHeight = Math.max(targetHeight + adjusts.h, 0); sws = shadowWidth + "px"; shs = shadowHeight + "px"; if (targetStyle.width != sws || targetStyle.height != shs) { targetStyle.width = sws; targetStyle.height = shs; if (Ext.supports.CSS3BoxShadow) { targetStyle[this.boxShadowProperty] = '0 0 ' + (this.offset + 2) + 'px #888'; } } }, hide: function() { var me = this; if (me.el) { me.el.dom.style.display = "none"; Ext.ShadowPool.push(me.el); delete me.el; } }, setZIndex: function(z) { this.zIndex = z; if (this.el) { this.el.setStyle("z-index", z); } }, setOpacity: function(opacity){ if (this.el) { if (Ext.isIE && !Ext.supports.CSS3BoxShadow) { opacity = Math.floor(opacity * 100 / 2) / 100; } this.opacity = opacity; this.el.setOpacity(opacity); } } }); Ext.define('Ext.app.EventDomain', { statics: { instances: {} }, isEventDomain: true, constructor: function() { var me = this; Ext.app.EventDomain.instances[me.type] = me; me.bus = {}; me.monitoredClasses = []; }, dispatch: function(target, ev, args) { var me = this, bus = me.bus, selectors = bus[ev], selector, controllers, id, events, event, i, ln; if (!selectors) { return true; } for (selector in selectors) { if (selectors.hasOwnProperty(selector) && me.match(target, selector)) { controllers = selectors[selector]; for (id in controllers) { if (controllers.hasOwnProperty(id)) { events = controllers[id]; for (i = 0, ln = events.length; i < ln; i++) { event = events[i]; if (event.fire.apply(event, args) === false) { return false; } } } } } } return true; }, listen: function(selectors, controller) { var me = this, bus = me.bus, idProperty = me.idProperty, monitoredClasses = me.monitoredClasses, monitoredClassesCount = monitoredClasses.length, i, tree, list, selector, options, listener, scope, event, listeners, ev; for (selector in selectors) { if (selectors.hasOwnProperty(selector) && (listeners = selectors[selector])) { if (idProperty) { selector = selector === '*' ? selector : selector.substring(1); } for (ev in listeners) { if (listeners.hasOwnProperty(ev)) { options = null; listener = listeners[ev]; scope = controller; event = new Ext.util.Event(controller, ev); if (Ext.isObject(listener)) { options = listener; listener = options.fn; scope = options.scope || controller; delete options.fn; delete options.scope; } if (typeof listener === 'string') { listener = scope[listener]; } event.addListener(listener, scope, options); for (i = monitoredClassesCount; i-- > 0;) { monitoredClasses[i].hasListeners._incr_(ev); } tree = bus[ev] || (bus[ev] = {}); tree = tree[selector] || (tree[selector] = {}); list = tree[controller.id] || (tree[controller.id] = []); list.push(event); } } } } }, match: function(target, selector) { var idProperty = this.idProperty; if (idProperty) { return selector === '*' || target[idProperty] === selector; } return false; }, monitor: function(observable) { var domain = this, prototype = observable.isInstance ? observable : observable.prototype, fireEventArgs = prototype.fireEventArgs; domain.monitoredClasses.push(observable); prototype.fireEventArgs = function(ev, args) { var ret = fireEventArgs.apply(this, arguments); if (ret !== false) { ret = domain.dispatch(this, ev, args); } return ret; }; }, unlisten: function(controllerId) { var bus = this.bus, controllers, ev, selector, selectors; for (ev in bus) { if (bus.hasOwnProperty(ev) && (selectors = bus[ev])) { for (selector in selectors) { controllers = selectors[selector]; delete controllers[controllerId]; } } } } }); Ext.define('Ext.app.domain.Component', { extend: Ext.app.EventDomain , singleton: true, type: 'component', constructor: function() { var me = this; me.callParent(); me.monitor(Ext.Component); }, match: function(target, selector) { return target.is(selector); } }); Ext.define('Ext.app.EventBus', { singleton: true, constructor: function() { var me = this, domains = Ext.app.EventDomain.instances; me.callParent(); me.domains = domains; me.bus = domains.component.bus; }, control: function(selectors, controller) { return this.domains.component.listen(selectors, controller); }, listen: function(to, controller) { var domains = this.domains, domain; for (domain in to) { if (to.hasOwnProperty(domain)) { domains[domain].listen(to[domain], controller); } } }, unlisten: function(controllerId) { var domains = Ext.app.EventDomain.instances, domain; for (domain in domains) { domains[domain].unlisten(controllerId); } } }); Ext.define('Ext.data.StoreManager', { extend: Ext.util.MixedCollection , alternateClassName: ['Ext.StoreMgr', 'Ext.data.StoreMgr', 'Ext.StoreManager'], singleton: true, register : function() { for (var i = 0, s; (s = arguments[i]); i++) { this.add(s); } }, unregister : function() { for (var i = 0, s; (s = arguments[i]); i++) { this.remove(this.lookup(s)); } }, lookup : function(store) { if (Ext.isArray(store)) { var fields = ['field1'], expand = !Ext.isArray(store[0]), data = store, i, len; if(expand){ data = []; for (i = 0, len = store.length; i < len; ++i) { data.push([store[i]]); } } else { for(i = 2, len = store[0].length; i <= len; ++i){ fields.push('field' + i); } } return new Ext.data.ArrayStore({ data : data, fields: fields, autoDestroy: true, autoCreated: true, expanded: expand }); } if (Ext.isString(store)) { return this.get(store); } else { return Ext.data.AbstractStore.create(store); } }, getKey : function(o) { return o.storeId; } }, function() { Ext.regStore = function(name, config) { var store; if (Ext.isObject(name)) { config = name; } else { config.storeId = name; } if (config instanceof Ext.data.Store) { store = config; } else { store = new Ext.data.Store(config); } return Ext.data.StoreManager.register(store); }; Ext.getStore = function(name) { return Ext.data.StoreManager.lookup(name); }; }); Ext.define('Ext.app.domain.Global', { extend: Ext.app.EventDomain , singleton: true, type: 'global', constructor: function() { var me = this; me.callParent(); me.monitor(Ext.globalEvents); }, listen: function(listeners, controller) { this.callParent([{ global: listeners }, controller]); }, match: function() { return true; } }); Ext.define('Ext.data.ResultSet', { loaded: true, count: 0, total: 0, success: false, constructor: function(config) { Ext.apply(this, config); this.totalRecords = this.total; if (config.count === undefined) { this.count = this.records.length; } } }); Ext.define('Ext.data.reader.Reader', { alternateClassName: ['Ext.data.Reader', 'Ext.data.DataReader'], mixins: { observable: Ext.util.Observable }, totalProperty: 'total', successProperty: 'success', root: '', implicitIncludes: true, readRecordsOnFailure: true, isReader: true, applyDefaults: true, lastFieldGeneration: null, constructor: function(config) { var me = this; me.mixins.observable.constructor.call(me, config); me.model = Ext.ModelManager.getModel(me.model); if (me.model && me.model.prototype.fields) { me.buildExtractors(); } this.addEvents( 'exception' ); }, setModel: function(model, setOnProxy) { var me = this, oldModel = me.model, force = true; model = me.model = Ext.ModelManager.getModel(model); if (model && oldModel === model) { force = me.lastFieldGeneration !== model.prototype.fields.generation; } if (model) { me.buildExtractors(force); } if (setOnProxy && me.proxy) { me.proxy.setModel(model, true); } }, read: function(response) { var data; if (response) { data = response.responseText ? this.getResponseData(response) : this.readRecords(response); } return data || this.nullResultSet; }, readRecords: function(data) { var me = this, success, recordCount, records, root, total, value, message; if (me.lastFieldGeneration !== me.model.prototype.fields.generation) { me.buildExtractors(true); } me.rawData = data; data = me.getData(data); success = true; recordCount = 0; records = []; if (me.successProperty) { value = me.getSuccess(data); if (value === false || value === 'false') { success = false; } } if (me.messageProperty) { message = me.getMessage(data); } if (me.readRecordsOnFailure || success) { root = Ext.isArray(data) ? data : me.getRoot(data); if (root) { total = root.length; } if (me.totalProperty) { value = parseInt(me.getTotal(data), 10); if (!isNaN(value)) { total = value; } } if (root) { records = me.extractData(root); recordCount = records.length; } } return new Ext.data.ResultSet({ total : total || recordCount, count : recordCount, records: records, success: success, message: message }); }, extractData : function(root) { var me = this, Model = me.model, length = root.length, records = new Array(length), convertedValues, node, record, i; if (!root.length && Ext.isObject(root)) { root = [root]; length = 1; } for (i = 0; i < length; i++) { node = root[i]; if (node.isModel) { records[i] = node; } else { records[i] = record = new Model(undefined, me.getId(node), node, convertedValues = {}); record.phantom = false; me.convertRecordData(convertedValues, node, record); if (me.implicitIncludes && record.associations.length) { me.readAssociated(record, node); } } } return records; }, readAssociated: function(record, data) { var associations = record.associations.items, i = 0, length = associations.length, association, associationData, proxy, reader; for (; i < length; i++) { association = associations[i]; associationData = this.getAssociatedDataRoot(data, association.associationKeyFunction || association.associationKey || association.name); if (associationData) { reader = association.getReader(); if (!reader) { proxy = association.associatedModel.getProxy(); if (proxy) { reader = proxy.getReader(); } else { reader = new this.constructor({ model: association.associatedName }); } } association.read(record, reader, associationData); } } }, getAssociatedDataRoot: function(data, associationName) { if (Ext.isFunction(associationName)) { return associationName(data); } return data[associationName]; }, getFields: function() { return this.model.prototype.fields.items; }, getData: Ext.identityFn, getRoot: Ext.identityFn, getResponseData: function(response) { }, onMetaChange : function(meta) { var me = this, fields = meta.fields || me.getFields(), newModel, clientIdProperty; me.metaData = meta; me.root = meta.root || me.root; me.idProperty = meta.idProperty || me.idProperty; me.totalProperty = meta.totalProperty || me.totalProperty; me.successProperty = meta.successProperty || me.successProperty; me.messageProperty = meta.messageProperty || me.messageProperty; clientIdProperty = meta.clientIdProperty; if (me.model) { me.model.setFields(fields, me.idProperty, clientIdProperty); me.setModel(me.model, true); } else { newModel = Ext.define("Ext.data.reader.Json-Model" + Ext.id(), { extend: 'Ext.data.Model', fields: fields, clientIdProperty: clientIdProperty }); if (me.idProperty) { newModel.idProperty = me.idProperty; } me.setModel(newModel, true); } }, getIdProperty: function() { var idField = this.model.prototype.idField, idProperty = this.idProperty; if (!idProperty && idField && (idProperty = idField.mapping) == null) { idProperty = idField.name; } return idProperty; }, buildExtractors: function(force) { var me = this, idProp = me.getIdProperty(), totalProp = me.totalProperty, successProp = me.successProperty, messageProp = me.messageProperty, accessor; if (force === true) { delete me.convertRecordData; } if (me.convertRecordData) { return; } if (totalProp) { me.getTotal = me.createAccessor(totalProp); } if (successProp) { me.getSuccess = me.createAccessor(successProp); } if (messageProp) { me.getMessage = me.createAccessor(messageProp); } if (idProp) { accessor = me.createAccessor(idProp); me.getId = function(record) { var id = accessor.call(me, record); return (id === undefined || id === '') ? null : id; }; } else { me.getId = function() { return null; }; } me.convertRecordData = me.buildRecordDataExtractor(); me.lastFieldGeneration = me.model.prototype.fields.generation; }, recordDataExtractorTemplate : [ 'var me = this\n', ' ,fields = me.model.prototype.fields\n', ' ,value\n', ' ,internalId\n', '', ' ,__field{#} = fields.map["{name}"]\n', '', ';\n', 'return function(dest, source, record) {\n', '', '{% var fieldAccessExpression = this.createFieldAccessExpression(values, "__field" + xindex, "source");', ' if (fieldAccessExpression) { %}', ' value = {[ this.createFieldAccessExpression(values, "__field" + xindex, "source") ]};\n', '', ' dest["{name}"] = value === undefined ? __field{#}.convert(__field{#}.defaultValue, record) : __field{#}.convert(value, record);\n', '', ' if (value === undefined) {\n', ' if (me.applyDefaults) {\n', '', ' dest["{name}"] = __field{#}.convert(__field{#}.defaultValue, record);\n', '', ' dest["{name}"] = __field{#}.defaultValue\n', '', ' };\n', ' } else {\n', '', ' dest["{name}"] = __field{#}.convert(value, record);\n', '', ' dest["{name}"] = value;\n', '', ' };\n', '', ' if (value !== undefined) {\n', '', ' dest["{name}"] = __field{#}.convert(value, record);\n', '', ' dest["{name}"] = value;\n', '', ' }\n', '', '{% } else { %}', '', '', ' dest["{name}"] = __field{#}.convert(__field{#}.defaultValue, record);\n', '', ' dest["{name}"] = __field{#}.defaultValue\n', '', '', '{% } %}', '', '', ' if (record && (internalId = {[ this.createFieldAccessExpression(\{mapping: values.clientIdProp\}, null, "source") ]})) {\n', ' record.{["internalId"]} = internalId;\n', ' }\n', '', '};' ], buildRecordDataExtractor: function() { var me = this, modelProto = me.model.prototype, templateData = { clientIdProp: modelProto.clientIdProperty, fields: modelProto.fields.items }; me.recordDataExtractorTemplate.createFieldAccessExpression = function() { return me.createFieldAccessExpression.apply(me,arguments); }; return Ext.functionFactory(me.recordDataExtractorTemplate.apply(templateData)).call(me); }, destroyReader: function() { var me = this; delete me.proxy; delete me.model; delete me.convertRecordData; delete me.getId; delete me.getTotal; delete me.getSuccess; delete me.getMessage; } }, function() { var proto = this.prototype; Ext.apply(proto, { nullResultSet: new Ext.data.ResultSet({ total : 0, count : 0, records: [], success: true, message: '' }), recordDataExtractorTemplate: new Ext.XTemplate(proto.recordDataExtractorTemplate) }); }); Ext.define('Ext.data.reader.Json', { extend: Ext.data.reader.Reader , alternateClassName: 'Ext.data.JsonReader', alias : 'reader.json', root: '', metaProperty: 'metaData', useSimpleAccessors: false, readRecords: function(data) { var me = this, meta; if (me.getMeta) { meta = me.getMeta(data); if (meta) { me.onMetaChange(meta); } } else if (data.metaData) { me.onMetaChange(data.metaData); } me.jsonData = data; return me.callParent([data]); }, getResponseData: function(response) { var data, error; try { data = Ext.decode(response.responseText); return this.readRecords(data); } catch (ex) { error = new Ext.data.ResultSet({ total : 0, count : 0, records: [], success: false, message: ex.message }); this.fireEvent('exception', this, response, error); Ext.Logger.warn('Unable to parse the JSON returned by the server'); return error; } }, buildExtractors : function() { var me = this, metaProp = me.metaProperty; me.callParent(arguments); if (me.root) { me.getRoot = me.createAccessor(me.root); } else { me.getRoot = Ext.identityFn; } if (metaProp) { me.getMeta = me.createAccessor(metaProp); } }, extractData: function(root) { var recordName = this.record, data = [], length, i; if (recordName) { length = root.length; if (!length && Ext.isObject(root)) { length = 1; root = [root]; } for (i = 0; i < length; i++) { data[i] = root[i][recordName]; } } else { data = root; } return this.callParent([data]); }, createAccessor: (function() { var re = /[\[\.]/; return function(expr) { if (Ext.isEmpty(expr)) { return Ext.emptyFn; } if (Ext.isFunction(expr)) { return expr; } if (this.useSimpleAccessors !== true) { var i = String(expr).search(re); if (i >= 0) { return Ext.functionFactory('obj', 'return obj' + (i > 0 ? '.' : '') + expr); } } return function(obj) { return obj[expr]; }; }; }()), createFieldAccessExpression: (function() { var re = /[\[\.]/; return function(field, fieldVarName, dataName) { var mapping = field.mapping, hasMap = mapping || mapping === 0, map = hasMap ? mapping : field.name, result, operatorIndex; if (mapping === false) { return; } if (typeof map === 'function') { result = fieldVarName + '.mapping(' + dataName + ', this)'; } else if (this.useSimpleAccessors === true || ((operatorIndex = String(map).search(re)) < 0)) { if (!hasMap || isNaN(map)) { map = '"' + map + '"'; } result = dataName + "[" + map + "]"; } else if (operatorIndex === 0) { result = dataName + map; } else { var parts = map.split('.'), len = parts.length, i = 1, tempResult = dataName + '.' + parts[0], buffer = [tempResult]; for (; i < len; i++) { tempResult += '.' + parts[i]; buffer.push(tempResult); } result = buffer.join(' && '); } return result; }; }()) }); Ext.define('Ext.data.writer.Writer', { alias: 'writer.base', alternateClassName: ['Ext.data.DataWriter', 'Ext.data.Writer'], writeAllFields: true, nameProperty: 'name', writeRecordId: true, isWriter: true, constructor: function(config) { Ext.apply(this, config); }, write: function(request) { var operation = request.operation, records = operation.records || [], len = records.length, i = 0, data = []; for (; i < len; i++) { data.push(this.getRecordData(records[i], operation)); } return this.writeRecords(request, data); }, getRecordData: function(record, operation) { var isPhantom = record.phantom === true, writeAll = this.writeAllFields || isPhantom, fields = record.fields, fieldItems = fields.items, data = {}, clientIdProperty = record.clientIdProperty, changes, field, key, mappedIdProperty, f, fLen; if (writeAll) { fLen = fieldItems.length; for (f = 0; f < fLen; f++) { field = fieldItems[f]; if (field.persist) { this.writeValue(data, field, record); } } } else if (operation.action === 'destroy') { this.writeValue(data, record.idField, record); } else { changes = record.getChanges(); for (key in changes) { if (changes.hasOwnProperty(key)) { field = fields.get(key); if (field.persist) { this.writeValue(data, field, record); } } } } if (isPhantom) { if (clientIdProperty && operation && operation.records.length > 1) { data[clientIdProperty] = record.internalId; } } else if (this.writeRecordId) { mappedIdProperty = fields.get(record.idProperty)[this.nameProperty] || record.idProperty; data[mappedIdProperty] = record.getId(); } return data; }, writeValue: function(data, field, record){ var name = field[this.nameProperty], dateFormat = this.dateFormat || field.dateWriteFormat || field.dateFormat, value = record.get(field.name); if (name == null) { name = field.name; } if (field.serialize) { data[name] = field.serialize(value, record); } else if (field.type === Ext.data.Types.DATE && dateFormat && Ext.isDate(value)) { data[name] = Ext.Date.format(value, dateFormat); } else { data[name] = value; } } }); Ext.define('Ext.data.writer.Json', { extend: Ext.data.writer.Writer , alternateClassName: 'Ext.data.JsonWriter', alias: 'writer.json', root: undefined, encode: false, allowSingle: true, expandData: false, getExpandedData: function(data) { var dataLength = data.length, i = 0, item, prop, nameParts, j, tempObj, toObject = function(name, value) { var o = {}; o[name] = value; return o; }; for (; i < dataLength; i++) { item = data[i]; for (prop in item) { if (item.hasOwnProperty(prop)) { nameParts = prop.split('.'); j = nameParts.length - 1; if (j > 0) { tempObj = item[prop]; for (; j > 0; j--) { tempObj = toObject(nameParts[j], tempObj); } item[nameParts[0]] = item[nameParts[0]] || {}; Ext.Object.merge(item[nameParts[0]], tempObj); delete item[prop]; } } } } return data; }, writeRecords: function(request, data) { var root = this.root; if (this.expandData) { data = this.getExpandedData(data); } if (this.allowSingle && data.length === 1) { data = data[0]; } if (this.encode) { if (root) { request.params[root] = Ext.encode(data); } else { } } else { request.jsonData = request.jsonData || {}; if (root) { request.jsonData[root] = data; } else { request.jsonData = data; } } return request; } }); Ext.define('Ext.data.proxy.Proxy', { alias: 'proxy.proxy', alternateClassName: ['Ext.data.DataProxy', 'Ext.data.Proxy'], mixins: { observable: Ext.util.Observable }, batchOrder: 'create,update,destroy', batchActions: true, defaultReaderType: 'json', defaultWriterType: 'json', isProxy: true, isSynchronous: false, constructor: function(config) { var me = this; config = config || {}; me.proxyConfig = config; me.mixins.observable.constructor.call(me, config); if (me.model !== undefined && !(me.model instanceof Ext.data.Model)) { me.setModel(me.model); } else { if (me.reader) { me.setReader(me.reader); } if (me.writer) { me.setWriter(me.writer); } } }, setModel: function(model, setOnStore) { var me = this; me.model = Ext.ModelManager.getModel(model); me.setReader(this.reader); me.setWriter(this.writer); if (setOnStore && me.store) { me.store.setModel(me.model); } }, getModel: function() { return this.model; }, setReader: function(reader) { var me = this, needsCopy = true, current = me.reader; if (reader === undefined || typeof reader == 'string') { reader = { type: reader }; needsCopy = false; } if (reader.isReader) { reader.setModel(me.model); } else { if (needsCopy) { reader = Ext.apply({}, reader); } Ext.applyIf(reader, { proxy: me, model: me.model, type : me.defaultReaderType }); reader = Ext.createByAlias('reader.' + reader.type, reader); } if (reader !== current && reader.onMetaChange) { reader.onMetaChange = Ext.Function.createSequence(reader.onMetaChange, this.onMetaChange, this); } me.reader = reader; return me.reader; }, getReader: function() { return this.reader; }, onMetaChange: function(meta) { this.fireEvent('metachange', this, meta); }, setWriter: function(writer) { var me = this, needsCopy = true; if (writer === undefined || typeof writer == 'string') { writer = { type: writer }; needsCopy = false; } if (!writer.isWriter) { if (needsCopy) { writer = Ext.apply({}, writer); } Ext.applyIf(writer, { model: me.model, type : me.defaultWriterType }); writer = Ext.createByAlias('writer.' + writer.type, writer); } me.writer = writer; return me.writer; }, getWriter: function() { return this.writer; }, create: Ext.emptyFn, read: Ext.emptyFn, update: Ext.emptyFn, destroy: Ext.emptyFn, batch: function(options, listeners) { var me = this, useBatch = me.batchActions, batch, records, actions, aLen, action, a, r, rLen, record; if (options.operations === undefined) { options = { operations: options, listeners: listeners }; } if (options.batch) { if (Ext.isDefined(options.batch.runOperation)) { batch = Ext.applyIf(options.batch, { proxy: me, listeners: {} }); } } else { options.batch = { proxy: me, listeners: options.listeners || {} }; } if (!batch) { batch = new Ext.data.Batch(options.batch); } batch.on('complete', Ext.bind(me.onBatchComplete, me, [options], 0)); actions = me.batchOrder.split(','); aLen = actions.length; for (a = 0; a < aLen; a++) { action = actions[a]; records = options.operations[action]; if (records) { if (useBatch) { batch.add(new Ext.data.Operation({ action : action, records : records })); } else { rLen = records.length; for (r = 0; r < rLen; r++) { record = records[r]; batch.add(new Ext.data.Operation({ action : action, records : [record] })); } } } } batch.start(); return batch; }, onBatchComplete: function(batchOptions, batch) { var scope = batchOptions.scope || this; if (batch.hasException) { if (Ext.isFunction(batchOptions.failure)) { Ext.callback(batchOptions.failure, scope, [batch, batchOptions]); } } else if (Ext.isFunction(batchOptions.success)) { Ext.callback(batchOptions.success, scope, [batch, batchOptions]); } if (Ext.isFunction(batchOptions.callback)) { Ext.callback(batchOptions.callback, scope, [batch, batchOptions]); } }, clone: function() { return new this.self(this.proxyConfig); } }); Ext.define('Ext.data.Operation', { synchronous: true, action: undefined, filters: undefined, sorters: undefined, groupers: undefined, start: undefined, limit: undefined, batch: undefined, callback: undefined, scope: undefined, started: false, running: false, complete: false, success: undefined, exception: false, error: undefined, actionCommitRecordsRe: /^(?:create|update)$/i, actionSkipSyncRe: /^destroy$/i, constructor: function(config) { Ext.apply(this, config || {}); }, commitRecords: function(serverRecords) { var me = this, commitRecords = me.actionCommitRecordsRe.test(me.action), mc, index, clientRecords, serverRec, clientRec, i, len, modifiedFields, recordModifiedFields; if (!me.actionSkipSyncRe.test(me.action)) { clientRecords = me.records; if (clientRecords && clientRecords.length) { if (commitRecords) { recordModifiedFields = []; } if (clientRecords.length > 1) { if (me.action == 'update' || clientRecords[0].clientIdProperty) { mc = new Ext.util.MixedCollection(); mc.addAll(serverRecords); for (index = clientRecords.length; index--; ) { clientRec = clientRecords[index]; serverRec = mc.findBy(me.matchClientRec, clientRec); modifiedFields = clientRec.copyFrom(serverRec); if (commitRecords) { recordModifiedFields.push(modifiedFields); } } } else { for (i = 0, len = clientRecords.length; i < len; ++i) { clientRec = clientRecords[i]; serverRec = serverRecords[i]; if (clientRec && serverRec) { modifiedFields = me.updateRecord(clientRec, serverRec); if (commitRecords) { recordModifiedFields.push(modifiedFields); } } } } } else { modifiedFields = me.updateRecord(clientRecords[0], serverRecords[0]); if (commitRecords) { recordModifiedFields[0] = modifiedFields; } } if (commitRecords) { for (index = clientRecords.length; index--; ) { clientRecords[index].commit(false, recordModifiedFields[index]); } } } } }, updateRecord: function(clientRec, serverRec) { if (serverRec && (clientRec.phantom || clientRec.getId() === serverRec.getId())) { return clientRec.copyFrom(serverRec); } return []; }, matchClientRec: function(record) { var clientRec = this, clientRecordId = clientRec.getId(); if(clientRecordId && record.getId() === clientRecordId) { return true; } return record.internalId === clientRec.internalId; }, setStarted: function() { this.started = true; this.running = true; }, setCompleted: function() { this.complete = true; this.running = false; }, setSuccessful: function() { this.success = true; }, setException: function(error) { this.exception = true; this.success = false; this.running = false; this.error = error; }, hasException: function() { return this.exception === true; }, getError: function() { return this.error; }, getRecords: function() { var resultSet = this.getResultSet(); return this.records || (resultSet ? resultSet.records : null); }, getResultSet: function() { return this.resultSet; }, isStarted: function() { return this.started === true; }, isRunning: function() { return this.running === true; }, isComplete: function() { return this.complete === true; }, wasSuccessful: function() { return this.isComplete() && this.success === true; }, setBatch: function(batch) { this.batch = batch; }, allowWrite: function() { return this.action != 'read'; } }); Ext.define('Ext.data.AbstractStore', { mixins: { observable: Ext.util.Observable , sortable: Ext.util.Sortable }, statics: { create: function(store) { if (!store.isStore) { if (!store.type) { store.type = 'store'; } store = Ext.createByAlias('store.' + store.type, store); } return store; } }, onClassExtended: function(cls, data, hooks) { var model = data.model, onBeforeClassCreated; if (typeof model == 'string') { onBeforeClassCreated = hooks.onBeforeCreated; hooks.onBeforeCreated = function() { var me = this, args = arguments; Ext.require(model, function() { onBeforeClassCreated.apply(me, args); }); }; } }, remoteSort : false, remoteFilter: false, autoLoad: undefined, autoSync: false, batchUpdateMode: 'operation', filterOnLoad: true, sortOnLoad: true, implicitModel: false, defaultProxyType: 'memory', isDestroyed: false, isStore: true, sortRoot: 'data', constructor: function(config) { var me = this, filters; Ext.apply(me, config); me.removed = []; me.mixins.observable.constructor.apply(me, arguments); me.model = Ext.ModelManager.getModel(me.model); Ext.applyIf(me, { modelDefaults: null }); if (!me.model && me.fields) { me.model = Ext.define('Ext.data.Store.ImplicitModel-' + (me.storeId || Ext.id()), { extend: 'Ext.data.Model', fields: me.fields, proxy: me.proxy || me.defaultProxyType }); delete me.fields; me.implicitModel = true; } me.setProxy(me.proxy || me.model.getProxy()); if (me.id && !me.storeId) { me.storeId = me.id; delete me.id; } if (me.storeId) { Ext.data.StoreManager.register(me); } me.mixins.sortable.initSortable.call(me); filters = me.decodeFilters(me.filters); me.filters = new Ext.util.MixedCollection(); me.filters.addAll(filters); }, setProxy: function(proxy) { var me = this, model = me.model; if (proxy instanceof Ext.data.proxy.Proxy) { proxy.setModel(model); } else { if (Ext.isString(proxy)) { proxy = { type: proxy, model: model }; } else if (!proxy.model) { proxy = Ext.apply({ model: model }, proxy) } proxy = Ext.createByAlias('proxy.' + proxy.type, proxy); } if (!me.disableMetaChangeEvent) { proxy.on('metachange', me.onMetaChange, me); } me.proxy = proxy; return me.proxy; }, getProxy: function() { return this.proxy; }, onMetaChange: function(proxy, meta) { this.fireEvent('metachange', this, meta); }, create: function(data, options) { var me = this, instance = Ext.ModelManager.create(Ext.applyIf(data, me.modelDefaults), me.model.modelName), operation; options = options || {}; Ext.applyIf(options, { action : 'create', records: [instance] }); operation = new Ext.data.Operation(options); me.proxy.create(operation, me.onProxyWrite, me); return instance; }, read: function() { return this.load.apply(this, arguments); }, update: function(options) { var me = this, operation; options = options || {}; Ext.applyIf(options, { action : 'update', records: me.getUpdatedRecords() }); operation = new Ext.data.Operation(options); return me.proxy.update(operation, me.onProxyWrite, me); }, onProxyWrite: function(operation) { var me = this, success = operation.wasSuccessful(), records = operation.getRecords(); switch (operation.action) { case 'create': me.onCreateRecords(records, operation, success); break; case 'update': me.onUpdateRecords(records, operation, success); break; case 'destroy': me.onDestroyRecords(records, operation, success); break; } if (success) { me.fireEvent('write', me, operation); me.fireEvent('datachanged', me); me.fireEvent('refresh', me); } Ext.callback(operation.callback, operation.scope || me, [records, operation, success]); }, onCreateRecords: Ext.emptyFn, onUpdateRecords: Ext.emptyFn, onDestroyRecords: function(records, operation, success) { if (success) { this.removed = []; } }, destroy: function(options) { var me = this, operation; options = options || {}; Ext.applyIf(options, { action : 'destroy', records: me.getRemovedRecords() }); operation = new Ext.data.Operation(options); return me.proxy.destroy(operation, me.onProxyWrite, me); }, onBatchOperationComplete: function(batch, operation) { return this.onProxyWrite(operation); }, onBatchComplete: function(batch, operation) { var me = this, operations = batch.operations, length = operations.length, i; me.suspendEvents(); for (i = 0; i < length; i++) { me.onProxyWrite(operations[i]); } me.resumeEvents(); me.fireEvent('datachanged', me); me.fireEvent('refresh', me); }, onBatchException: function(batch, operation) { }, filterNew: function(item) { return item.phantom === true && item.isValid(); }, getNewRecords: function() { return []; }, getUpdatedRecords: function() { return []; }, getModifiedRecords : function(){ return [].concat(this.getNewRecords(), this.getUpdatedRecords()); }, filterUpdated: function(item) { return item.dirty === true && item.phantom !== true && item.isValid(); }, getRemovedRecords: function() { return this.removed; }, filter: function(filters, value) { }, decodeFilters: function(filters) { if (!Ext.isArray(filters)) { if (filters === undefined) { filters = []; } else { filters = [filters]; } } var length = filters.length, Filter = Ext.util.Filter, config, i; for (i = 0; i < length; i++) { config = filters[i]; if (!(config instanceof Filter)) { Ext.apply(config, { root: 'data' }); if (config.fn) { config.filterFn = config.fn; } if (typeof config == 'function') { config = { filterFn: config }; } filters[i] = new Filter(config); } } return filters; }, clearFilter: function(supressEvent) { }, isFiltered: function() { }, filterBy: function(fn, scope) { }, sync: function(options) { var me = this, operations = {}, toCreate = me.getNewRecords(), toUpdate = me.getUpdatedRecords(), toDestroy = me.getRemovedRecords(), needsSync = false; if (toCreate.length > 0) { operations.create = toCreate; needsSync = true; } if (toUpdate.length > 0) { operations.update = toUpdate; needsSync = true; } if (toDestroy.length > 0) { operations.destroy = toDestroy; needsSync = true; } if (needsSync && me.fireEvent('beforesync', operations) !== false) { options = options || {}; me.proxy.batch(Ext.apply(options, { operations: operations, listeners: me.getBatchListeners() })); } return me; }, getBatchListeners: function() { var me = this, listeners = { scope: me, exception: me.onBatchException }; if (me.batchUpdateMode == 'operation') { listeners.operationcomplete = me.onBatchOperationComplete; } else { listeners.complete = me.onBatchComplete; } return listeners; }, save: function() { return this.sync.apply(this, arguments); }, load: function(options) { var me = this, operation = { action: 'read' }; if (me.remoteFilter) { operation.filters = me.filters.items; } if (me.remoteSort) { operation.sorters = me.getSorters(); } Ext.apply(operation, options); me.lastOptions = operation; operation = new Ext.data.Operation(operation); if (me.fireEvent('beforeload', me, operation) !== false) { me.loading = true; me.proxy.read(operation, me.onProxyLoad, me); } return me; }, reload: function(options) { var o = Ext.apply({}, options, this.lastOptions); return this.load(o); }, afterEdit : function(record, modifiedFieldNames) { var me = this, i, shouldSync; if (me.autoSync && !me.autoSyncSuspended) { for (i = modifiedFieldNames.length; i--;) { if (record.fields.get(modifiedFieldNames[i]).persist) { shouldSync = true; break; } } if (shouldSync) { me.sync(); } } me.onUpdate(record, Ext.data.Model.EDIT, modifiedFieldNames); me.fireEvent('update', me, record, Ext.data.Model.EDIT, modifiedFieldNames); }, afterReject : function(record) { this.onUpdate(record, Ext.data.Model.REJECT, null); this.fireEvent('update', this, record, Ext.data.Model.REJECT, null); }, afterCommit : function(record, modifiedFieldNames) { if (!modifiedFieldNames) { modifiedFieldNames = null; } this.onUpdate(record, Ext.data.Model.COMMIT, modifiedFieldNames); this.fireEvent('update', this, record, Ext.data.Model.COMMIT, modifiedFieldNames); }, onUpdate: Ext.emptyFn, onIdChanged: function(model, oldId, newId, oldInternalId){ this.fireEvent('idchanged', this, model, oldId, newId, oldInternalId); }, destroyStore: function() { var implicitModelName, me = this; if (!me.isDestroyed) { me.clearListeners(); if (me.storeId) { Ext.data.StoreManager.unregister(me); } me.clearData(); me.data = me.tree = me.sorters = me.filters = me.groupers = null; if (me.reader) { me.reader.destroyReader(); } me.proxy = me.reader = me.writer = null; me.isDestroyed = true; if (me.implicitModel) { implicitModelName = Ext.getClassName(me.model); Ext.undefine(implicitModelName); Ext.ModelManager.unregisterType(implicitModelName); } else { me.model = null; } } }, getState: function() { var me = this, hasState, result, hasGroupers = !!me.groupers, groupers = [], sorters = [], filters = []; if (hasGroupers) { me.groupers.each(function(g) { groupers[groupers.length] = g.serialize(); hasState = true; }); } if (me.sorters) { me.sorters.each(function(s) { if (hasGroupers && !me.groupers.contains(s)) { sorters[sorters.length] = s.serialize(); hasState = true; } }); } if (me.filters && me.statefulFilters) { me.filters.each(function(f) { filters[filters.length] = f.serialize(); hasState = true; }); } if (hasState) { result = {}; if (groupers.length) { result.groupers = groupers; } if (sorters.length) { result.sorters = sorters; } if (filters.length) { result.filters = filters; } return result; } }, applyState: function(state) { var me = this, hasSorters = !!me.sorters, hasGroupers = !!me.groupers, hasFilters = !!me.filters, locallySorted; if (hasGroupers && state.groupers) { me.groupers.clear(); me.groupers.addAll(me.decodeGroupers(state.groupers)); } if (hasSorters && state.sorters) { me.sorters.clear(); me.sorters.addAll(me.decodeSorters(state.sorters)); } if (hasFilters && state.filters) { me.filters.clear(); me.filters.addAll(me.decodeFilters(state.filters)); } if (hasSorters && hasGroupers) { me.sorters.insert(0, me.groupers.getRange()); } if (me.autoLoad && (me.remoteSort || me.remoteGroup || me.remoteFilter)) { if (me.autoLoad === true) { me.reload(); } else { me.reload(me.autoLoad); } } if (hasFilters && me.filters.length && !me.remoteFilter) { me.filter(); locallySorted = me.sortOnFilter; } if (hasSorters && me.sorters.length && !me.remoteSort && !locallySorted) { me.sort(); } }, doSort: function(sorterFn) { var me = this; if (me.remoteSort) { me.load(); } else { me.data.sortBy(sorterFn); me.fireEvent('datachanged', me); me.fireEvent('refresh', me); } me.fireEvent('sort', me, me.sorters.getRange()); }, clearData: Ext.emptyFn, getCount: Ext.emptyFn, getById: Ext.emptyFn, removeAll: Ext.emptyFn, isLoading: function() { return !!this.loading; }, suspendAutoSync: function() { this.autoSyncSuspended = true; }, resumeAutoSync: function() { this.autoSyncSuspended = false; } }); Ext.define('Ext.app.domain.Store', { extend: Ext.app.EventDomain , singleton: true, type: 'store', idProperty: 'storeId', constructor: function() { var me = this; me.callParent(); me.monitor(Ext.data.AbstractStore); } }); Ext.define('Ext.app.Controller', { mixins: { observable: Ext.util.Observable }, statics: { strings: { model: { getter: 'getModel', upper: 'Model' }, view: { getter: 'getView', upper: 'View' }, controller: { getter: 'getController', upper: 'Controller' }, store: { getter: 'getStore', upper: 'Store' } }, controllerRegex: /^(.*)\.controller\./, createGetter: function(baseGetter, name) { return function () { return this[baseGetter](name); }; }, getGetterName: function(name, kindUpper) { var fn = 'get', parts = name.split('.'), numParts = parts.length, index; for (index = 0; index < numParts; index++) { fn += Ext.String.capitalize(parts[index]); } fn += kindUpper; return fn; }, processDependencies: function(cls, requires, namespace, kind, names) { if (!names || !names.length) { return; } var me = this, strings = me.strings[kind], o, absoluteName, shortName, name, j, subLn, getterName, getter; if (!Ext.isArray(names)) { names = [names]; } for (j = 0, subLn = names.length; j < subLn; j++) { name = names[j]; o = me.getFullName(name, kind, namespace); absoluteName = o.absoluteName; shortName = o.shortName; requires.push(absoluteName); getterName = me.getGetterName(shortName, strings.upper); cls[getterName] = getter = me.createGetter(strings.getter, name); if (kind !== 'controller') { getter['Ext.app.getter'] = true; } } }, getFullName: function(name, kind, namespace) { var shortName = name, sep, absoluteName; if ((sep = name.indexOf('@')) > 0) { shortName = name.substring(0, sep); absoluteName = name.substring(sep + 1) + '.' + shortName; } else if (name.indexOf('.') > 0 && (Ext.ClassManager.isCreated(name) || Ext.Loader.isAClassNameWithAKnownPrefix(name))) { absoluteName = name; } else { if (namespace) { absoluteName = namespace + '.' + kind + '.' + name; shortName = name; } else { absoluteName = name; } } return { absoluteName: absoluteName, shortName: shortName }; } }, application: null, onClassExtended: function(cls, data, hooks) { var onBeforeClassCreated = hooks.onBeforeCreated; hooks.onBeforeCreated = function(cls, data) { var Controller = Ext.app.Controller, ctrlRegex = Controller.controllerRegex, requires = [], className, namespace, requires, proto, match; proto = cls.prototype; className = Ext.getClassName(cls); namespace = data.$namespace || Ext.app.getNamespace(className) || ((match = ctrlRegex.exec(className)) && match[1]); if (namespace) { proto.$namespace = namespace; } Controller.processDependencies(proto, requires, namespace, 'model', data.models); Controller.processDependencies(proto, requires, namespace, 'view', data.views); Controller.processDependencies(proto, requires, namespace, 'store', data.stores); Controller.processDependencies(proto, requires, namespace, 'controller', data.controllers); Ext.require(requires, Ext.Function.pass(onBeforeClassCreated, arguments, this)); }; }, constructor: function (config) { var me = this; me.mixins.observable.constructor.call(me, config); if (me.refs) { me.ref(me.refs); } me.eventbus = Ext.app.EventBus; me.initAutoGetters(); }, initAutoGetters: function() { var proto = this.self.prototype, prop, fn; for (prop in proto) { fn = proto[prop]; if (fn && fn['Ext.app.getter']) { fn.call(this); } } }, doInit: function(app) { var me = this; if (!me._initialized) { me.init(app); me._initialized = true; } }, finishInit: function(app) { var me = this, controllers = me.controllers, controller, i, l; if (me._initialized && controllers && controllers.length) { for (i = 0, l = controllers.length; i < l; i++) { controller = me.getController(controllers[i]); controller.finishInit(app); } } }, init: Ext.emptyFn, onLaunch: Ext.emptyFn, ref: function(refs) { var me = this, i = 0, length = refs.length, info, ref, fn; refs = Ext.Array.from(refs); me.references = me.references || []; for (; i < length; i++) { info = refs[i]; ref = info.ref; fn = 'get' + Ext.String.capitalize(ref); if (!me[fn]) { me[fn] = Ext.Function.pass(me.getRef, [ref, info], me); } me.references.push(ref.toLowerCase()); } }, addRef: function(refs) { this.ref(refs); }, getRef: function(ref, info, config) { var me = this, refCache = me.refCache || (me.refCache = {}), cached = refCache[ref]; info = info || {}; config = config || {}; Ext.apply(info, config); if (info.forceCreate) { return Ext.ComponentManager.create(info, 'component'); } if (!cached) { if (info.selector) { refCache[ref] = cached = Ext.ComponentQuery.query(info.selector)[0]; } if (!cached && info.autoCreate) { refCache[ref] = cached = Ext.ComponentManager.create(info, 'component'); } if (cached) { cached.on('beforedestroy', function() { refCache[ref] = null; }); } } return cached; }, hasRef: function(ref) { var references = this.references; return references && Ext.Array.indexOf(references, ref.toLowerCase()) !== -1; }, control: function(selectors, listeners, controller) { var me = this, ctrl = controller, obj; if (Ext.isString(selectors)) { obj = {}; obj[selectors] = listeners; } else { obj = selectors; ctrl = listeners; } me.eventbus.control(obj, ctrl || me); }, listen: function (to, controller) { this.eventbus.listen(to, controller || this); }, getController: function(id) { var me = this, app = me.application; if (id === me.id) { return me; } return app && app.getController(id); }, getStore: function(name) { var storeId, store; storeId = (name.indexOf('@') == -1) ? name : name.split('@')[0]; store = Ext.StoreManager.get(storeId); if (!store) { name = Ext.app.Controller.getFullName(name, 'store', this.$namespace); if (name) { store = Ext.create(name.absoluteName, { storeId: storeId }); } } return store; }, getModel: function(model) { var name = Ext.app.Controller.getFullName(model, 'model', this.$namespace); return name && Ext.ModelManager.getModel(name.absoluteName); }, getView: function(view) { var name = Ext.app.Controller.getFullName(view, 'view', this.$namespace); return name && Ext.ClassManager.get(name.absoluteName); }, getApplication: function() { return this.application; } }); Ext.define('Ext.container.DockingContainer', { isDockingContainer: true, defaultDockWeights: { top: { render: 1, visual: 1 }, left: { render: 3, visual: 5 }, right: { render: 5, visual: 7 }, bottom: { render: 7, visual: 3 } }, dockOrder: { top: -1, left: -1, right: 1, bottom: 1 }, horizontalDocks: 0, addDocked : function(items, pos) { var me = this, i = 0, item, length; items = me.prepareItems(items); length = items.length; for (; i < length; i++) { item = items[i]; item.dock = item.dock || 'top'; if (item.dock === 'left' || item.dock === 'right') { me.horizontalDocks++; } if (pos !== undefined) { i += pos; me.dockedItems.insert(i, item); } else { me.dockedItems.add(item); } item.onAdded(me, i); if (me.hasListeners.dockedadd) { me.fireEvent('dockedadd', me, item, i); } if (me.onDockedAdd !== Ext.emptyFn) { me.onDockedAdd(item); } } if (me.rendered && !me.suspendLayout) { me.updateLayout(); } return items; }, destroyDockedItems: function(){ var dockedItems = this.dockedItems, c; if (dockedItems) { while ((c = dockedItems.first())) { this.removeDocked(c, true); } } }, doRenderDockedItems: function (out, renderData, after) { var me = renderData.$comp, layout = me.componentLayout, items, tree; if (layout.getDockedItems && !renderData.$skipDockedItems) { items = layout.getDockedItems('render', !after); tree = items && layout.getItemsRenderTree(items); if (tree) { Ext.DomHelper.generateMarkup(tree, out); } } }, getDockedComponent: function(comp) { if (Ext.isObject(comp)) { comp = comp.getItemId(); } return this.dockedItems.get(comp); }, getDockedItems : function(selector, beforeBody) { var dockedItems = this.getComponentLayout().getDockedItems('render', beforeBody); if (selector && dockedItems.length) { dockedItems = Ext.ComponentQuery.query(selector, dockedItems); } return dockedItems; }, getDockingRefItems: function(deep, containerItems) { var selector = deep && '*,* *', dockedItems = this.getDockedItems(selector, true), items; dockedItems.push.apply(dockedItems, containerItems); items = this.getDockedItems(selector, false); dockedItems.push.apply(dockedItems, items); return dockedItems; }, initDockingItems: function() { var me = this, items = me.dockedItems; me.dockedItems = new Ext.util.AbstractMixedCollection(false, me.getComponentId); if (items) { me.addDocked(items); } }, insertDocked : function(pos, items) { this.addDocked(items, pos); }, onDockedAdd : Ext.emptyFn, onDockedRemove : Ext.emptyFn, removeDocked : function(item, autoDestroy) { var me = this, layout, hasLayout; autoDestroy = autoDestroy === true || (autoDestroy !== false && me.autoDestroy); if (!me.dockedItems.contains(item)) { return item; } if (item.dock === 'left' || item.dock === 'right') { me.horizontalDocks--; } layout = me.componentLayout; hasLayout = layout && me.rendered; if (hasLayout) { layout.onRemove(item); } me.dockedItems.remove(item); item.onRemoved(item.destroying || autoDestroy); me.onDockedRemove(item); if (autoDestroy) { item.destroy(); } else if (hasLayout) { layout.afterRemove(item); } if (me.hasListeners.dockedremove) { me.fireEvent('dockedremove', me, item); } if (!me.destroying && !me.suspendLayout) { me.updateLayout(); } return item; }, setupDockingRenderTpl: function (renderTpl) { renderTpl.renderDockedItems = this.doRenderDockedItems; } }); Ext.define('Ext.toolbar.Fill', { extend: Ext.Component , alias: 'widget.tbfill', alternateClassName: 'Ext.Toolbar.Fill', ariaRole: 'presentation', isFill : true, flex: 1 }); Ext.define('Ext.layout.container.boxOverflow.None', { alternateClassName: 'Ext.layout.boxOverflow.None', constructor: function(layout, config) { this.layout = layout; Ext.apply(this, config); }, handleOverflow: Ext.emptyFn, clearOverflow: Ext.emptyFn, beginLayout: Ext.emptyFn, beginLayoutCycle: Ext.emptyFn, calculate: function(ownerContext) { var me = this, plan = ownerContext.state.boxPlan, overflow; if (plan && plan.tooNarrow) { overflow = me.handleOverflow(ownerContext); if (overflow) { if (overflow.reservedSpace) { me.layout.publishInnerCtSize(ownerContext, overflow.reservedSpace); } } } else { me.clearOverflow(); } }, completeLayout: Ext.emptyFn, finishedLayout: function (ownerContext) { var me = this, owner = me.layout.owner, hiddens, hiddenCount; if (owner.hasListeners.overflowchange) { hiddens = owner.query('>[hidden]'); hiddenCount = hiddens.length; if (hiddenCount !== me.lastHiddenCount) { owner.fireEvent('overflowchange', me.lastHiddenCount, hiddenCount, hiddens); me.lastHiddenCount = hiddenCount; } } }, onRemove: Ext.emptyFn, getItem: function(item) { return this.layout.owner.getComponent(item); }, getOwnerType: function(owner){ var type; if (owner.isToolbar) { type = 'toolbar'; } else if (owner.isTabBar) { type = 'tabbar'; } else if (owner.isMenu) { type = 'menu'; } else { type = owner.getXType(); } return type; }, getPrefixConfig: Ext.emptyFn, getSuffixConfig: Ext.emptyFn, getOverflowCls: function() { return ''; } }); Ext.define('Ext.toolbar.Item', { extend: Ext.Component , alias: 'widget.tbitem', alternateClassName: 'Ext.Toolbar.Item', enable:Ext.emptyFn, disable:Ext.emptyFn, focus:Ext.emptyFn }); Ext.define('Ext.toolbar.Separator', { extend: Ext.toolbar.Item , alias: 'widget.tbseparator', alternateClassName: 'Ext.Toolbar.Separator', baseCls: Ext.baseCSSPrefix + 'toolbar-separator', focusable: false, ariaRole: 'separator' }); Ext.define('Ext.button.Manager', { singleton: true, alternateClassName: 'Ext.ButtonToggleManager', groups: {}, pressedButton: null, buttonSelector: '.' + Ext.baseCSSPrefix + 'btn', init: function() { var me = this; if (!me.initialized) { Ext.getDoc().on({ keydown: me.onDocumentKeyDown, mouseup: me.onDocumentMouseUp, scope: me }); me.initialized = true; } }, onDocumentKeyDown: function(e) { var k = e.getKey(), btn; if (k === e.SPACE || k === e.ENTER) { btn = e.getTarget(this.buttonSelector); if (btn) { Ext.getCmp(btn.id).onClick(e); } } }, onButtonMousedown: function(button, e) { var pressed = this.pressedButton; if (pressed) { pressed.onMouseUp(e); } this.pressedButton = button; }, onDocumentMouseUp: function(e) { var pressed = this.pressedButton; if (pressed) { pressed.onMouseUp(e); this.pressedButton = null; } }, toggleGroup: function(btn, state) { if (state) { var g = this.groups[btn.toggleGroup], length = g.length, i; for (i = 0; i < length; i++) { if (g[i] !== btn) { g[i].toggle(false); } } } }, register: function(btn) { var me = this, groups = this.groups, group = groups[btn.toggleGroup]; me.init(); if (!btn.toggleGroup) { return; } if (!group) { group = groups[btn.toggleGroup] = []; } group.push(btn); btn.on('toggle', me.toggleGroup, me); }, unregister: function(btn) { if (!btn.toggleGroup) { return; } var me = this, group = me.groups[btn.toggleGroup]; if (group) { Ext.Array.remove(group, btn); btn.un('toggle', me.toggleGroup, me); } }, getPressed: function(group) { var g = this.groups[group], i = 0, len; if (g) { for (len = g.length; i < len; i++) { if (g[i].pressed === true) { return g[i]; } } } return null; } }); Ext.define('Ext.menu.Manager', { singleton: true, alternateClassName: 'Ext.menu.MenuMgr', menuSelector: '.' + Ext.baseCSSPrefix + 'menu', menus: {}, groups: {}, attached: false, lastShow: new Date(), init: function() { var me = this; me.active = new Ext.util.MixedCollection(); Ext.getDoc().addKeyListener(27, function() { if (me.active.length > 0) { me.hideAll(); } }, me); }, hideAll: function() { var active = this.active, menus, m, mLen; if (active && active.length > 0) { menus = Ext.Array.slice(active.items); mLen = menus.length; for (m = 0; m < mLen; m++) { menus[m].hide(); } return true; } return false; }, onHide: function(m) { var me = this, active = me.active; active.remove(m); if (active.length < 1) { Ext.getDoc().un('mousedown', me.onMouseDown, me); me.attached = false; } }, onShow: function(m) { var me = this, active = me.active, attached = me.attached; me.lastShow = new Date(); active.add(m); if (!attached) { Ext.getDoc().on('mousedown', me.onMouseDown, me, { buffer: Ext.isIE9m ? 10 : undefined }); me.attached = true; } m.toFront(); }, onBeforeHide: function(m) { if (m.activeChild) { m.activeChild.hide(); } if (m.autoHideTimer) { clearTimeout(m.autoHideTimer); delete m.autoHideTimer; } }, onBeforeShow: function(m) { var active = this.active, parentMenu = m.parentMenu; active.remove(m); if (!parentMenu && !m.allowOtherMenus) { this.hideAll(); } else if (parentMenu && parentMenu.activeChild && m != parentMenu.activeChild) { parentMenu.activeChild.hide(); } }, onMouseDown: function(e) { var me = this, active = me.active, lastShow = me.lastShow, doHide = true; if (Ext.Date.getElapsed(lastShow) > 50 && active.length > 0 && !e.getTarget(me.menuSelector)) { if (Ext.isIE9m && !Ext.getDoc().contains(e.target)) { doHide = false; } if (doHide) { me.hideAll(); } } }, register: function(menu) { var me = this; if (!me.active) { me.init(); } if (menu.floating) { me.menus[menu.id] = menu; menu.on({ beforehide: me.onBeforeHide, hide: me.onHide, beforeshow: me.onBeforeShow, show: me.onShow, scope: me }); } }, get: function(menu) { var menus = this.menus; if (typeof menu == 'string') { if (!menus) { return null; } return menus[menu]; } else if (menu.isMenu) { return menu; } else if (Ext.isArray(menu)) { return new Ext.menu.Menu({items:menu}); } else { return Ext.ComponentManager.create(menu, 'menu'); } }, unregister: function(menu) { var me = this, menus = me.menus, active = me.active; delete menus[menu.id]; active.remove(menu); menu.un({ beforehide: me.onBeforeHide, hide: me.onHide, beforeshow: me.onBeforeShow, show: me.onShow, scope: me }); }, registerCheckable: function(menuItem) { var groups = this.groups, groupId = menuItem.group; if (groupId) { if (!groups[groupId]) { groups[groupId] = []; } groups[groupId].push(menuItem); } }, unregisterCheckable: function(menuItem) { var groups = this.groups, groupId = menuItem.group; if (groupId) { Ext.Array.remove(groups[groupId], menuItem); } }, onCheckChange: function(menuItem, state) { var groups = this.groups, groupId = menuItem.group, i = 0, group, ln, curr; if (groupId && state) { group = groups[groupId]; ln = group.length; for (; i < ln; i++) { curr = group[i]; if (curr != menuItem) { curr.setChecked(false); } } } } }); Ext.define('Ext.util.ClickRepeater', { extend: Ext.util.Observable , constructor : function(el, config){ var me = this; me.el = Ext.get(el); me.el.unselectable(); Ext.apply(me, config); me.callParent(); me.addEvents( "mousedown", "click", "mouseup" ); if(!me.disabled){ me.disabled = true; me.enable(); } if(me.handler){ me.on("click", me.handler, me.scope || me); } }, interval : 20, delay: 250, preventDefault : true, stopDefault : false, timer : 0, enable: function(){ if(this.disabled){ this.el.on('mousedown', this.handleMouseDown, this); if (Ext.isIE && !(Ext.isIE10p || (Ext.isStrict && Ext.isIE9))){ this.el.on('dblclick', this.handleDblClick, this); } if(this.preventDefault || this.stopDefault){ this.el.on('click', this.eventOptions, this); } } this.disabled = false; }, disable: function( force){ if(force || !this.disabled){ clearTimeout(this.timer); if(this.pressedCls){ this.el.removeCls(this.pressedCls); } Ext.getDoc().un('mouseup', this.handleMouseUp, this); this.el.removeAllListeners(); } this.disabled = true; }, setDisabled: function(disabled){ this[disabled ? 'disable' : 'enable'](); }, eventOptions: function(e){ if(this.preventDefault){ e.preventDefault(); } if(this.stopDefault){ e.stopEvent(); } }, destroy : function() { this.disable(true); Ext.destroy(this.el); this.clearListeners(); }, handleDblClick : function(e){ clearTimeout(this.timer); this.el.blur(); this.fireEvent("mousedown", this, e); this.fireEvent("click", this, e); }, handleMouseDown : function(e){ clearTimeout(this.timer); this.el.blur(); if(this.pressedCls){ this.el.addCls(this.pressedCls); } this.mousedownTime = new Date(); Ext.getDoc().on("mouseup", this.handleMouseUp, this); this.el.on("mouseout", this.handleMouseOut, this); this.fireEvent("mousedown", this, e); this.fireEvent("click", this, e); if (this.accelerate) { this.delay = 400; } e = new Ext.EventObjectImpl(e); this.timer = Ext.defer(this.click, this.delay || this.interval, this, [e]); }, click : function(e){ this.fireEvent("click", this, e); this.timer = Ext.defer(this.click, this.accelerate ? this.easeOutExpo(Ext.Date.getElapsed(this.mousedownTime), 400, -390, 12000) : this.interval, this, [e]); }, easeOutExpo : function (t, b, c, d) { return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b; }, handleMouseOut : function(){ clearTimeout(this.timer); if(this.pressedCls){ this.el.removeCls(this.pressedCls); } this.el.on("mouseover", this.handleMouseReturn, this); }, handleMouseReturn : function(){ this.el.un("mouseover", this.handleMouseReturn, this); if(this.pressedCls){ this.el.addCls(this.pressedCls); } this.click(); }, handleMouseUp : function(e){ clearTimeout(this.timer); this.el.un("mouseover", this.handleMouseReturn, this); this.el.un("mouseout", this.handleMouseOut, this); Ext.getDoc().un("mouseup", this.handleMouseUp, this); if(this.pressedCls){ this.el.removeCls(this.pressedCls); } this.fireEvent("mouseup", this, e); } }); Ext.define('Ext.layout.component.Button', { alias: ['layout.button'], extend: Ext.layout.component.Auto , type: 'button', htmlRE: /<.*>/, beginLayout: function(ownerContext) { var me = this, owner = me.owner, text = owner.text; me.callParent(arguments); ownerContext.btnWrapContext = ownerContext.getEl('btnWrap'); ownerContext.btnElContext = ownerContext.getEl('btnEl'); ownerContext.btnInnerElContext = ownerContext.getEl('btnInnerEl'); ownerContext.btnIconElContext = ownerContext.getEl('btnIconEl'); if (text && me.htmlRE.test(text)) { ownerContext.isHtmlText = true; owner.btnInnerEl.setStyle('line-height', 'normal'); owner.btnInnerEl.setStyle('padding-top', ''); } }, beginLayoutCycle: function(ownerContext) { var owner = this.owner, lastWidthModel = this.lastWidthModel; this.callParent(arguments); if (lastWidthModel && !this.lastWidthModel.shrinkWrap && ownerContext.widthModel.shrinkWrap) { owner.btnWrap.setStyle('height', ''); owner.btnEl.setStyle('height', ''); owner.btnInnerEl.setStyle('line-height', ''); } }, calculate: function(ownerContext) { var me = this, owner = me.owner, btnElContext = ownerContext.btnElContext, btnInnerElContext = ownerContext.btnInnerElContext, btnWrapContext = ownerContext.btnWrapContext, mmax = Math.max, ownerHeight, contentHeight, btnElHeight, innerElHeight; me.callParent(arguments); if (ownerContext.heightModel.shrinkWrap) { btnElHeight = owner.btnEl.getHeight(); if (ownerContext.isHtmlText) { me.centerInnerEl( ownerContext, btnElHeight ); me.ieCenterIcon(ownerContext, btnElHeight); } } else { ownerHeight = ownerContext.getProp('height'); if (ownerHeight) { contentHeight = ownerHeight - ownerContext.getFrameInfo().height - ownerContext.getPaddingInfo().height; btnElHeight = contentHeight; if ((owner.menu || owner.split) && owner.arrowAlign === 'bottom') { btnElHeight -= btnWrapContext.getPaddingInfo().bottom; } innerElHeight = btnElHeight; if ((owner.icon || owner.iconCls || owner.glyph) && (owner.iconAlign === 'top' || owner.iconAlign === 'bottom')) { innerElHeight -= btnInnerElContext.getPaddingInfo().height; } btnWrapContext.setProp('height', mmax(0, contentHeight)); btnElContext.setProp('height', mmax(0, btnElHeight)); if (ownerContext.isHtmlText) { me.centerInnerEl(ownerContext, btnElHeight); } else { btnInnerElContext.setProp('line-height', mmax(0, innerElHeight) + 'px'); } me.ieCenterIcon(ownerContext, btnElHeight); } else if (ownerHeight !== 0) { me.done = false; } } }, centerInnerEl: function(ownerContext, btnElHeight) { var me = this, btnInnerElContext = ownerContext.btnInnerElContext, innerElHeight = me.owner.btnInnerEl.getHeight(); if (ownerContext.heightModel.shrinkWrap && (btnElHeight < innerElHeight)) { ownerContext.btnElContext.setHeight(innerElHeight); } else if (btnElHeight > innerElHeight) { btnInnerElContext.setProp( 'padding-top', Math.round((btnElHeight - innerElHeight) / 2) + btnInnerElContext.getPaddingInfo().top ); } }, ieCenterIcon: function(ownerContext, btnElHeight) { var iconAlign = this.owner.iconAlign; if ((Ext.isIEQuirks || Ext.isIE6) && (iconAlign === 'left' || iconAlign === 'right')) { ownerContext.btnIconElContext.setHeight(btnElHeight); } }, publishInnerWidth: function(ownerContext, width) { if (this.owner.getFrameInfo().table) { ownerContext.btnInnerElContext.setWidth( width - ownerContext.getFrameInfo().width - ownerContext.getPaddingInfo().width - ownerContext.btnWrapContext.getPaddingInfo().width ); } } }); Ext.define('Ext.util.TextMetrics', { statics: { shared: null, measure: function(el, text, fixedWidth){ var me = this, shared = me.shared; if(!shared){ shared = me.shared = new me(el, fixedWidth); } shared.bind(el); shared.setFixedWidth(fixedWidth || 'auto'); return shared.getSize(text); }, destroy: function(){ var me = this; Ext.destroy(me.shared); me.shared = null; } }, constructor: function(bindTo, fixedWidth){ var me = this, measure = Ext.getBody().createChild({ role: 'presentation', cls: Ext.baseCSSPrefix + 'textmetrics' }); me.measure = measure; if (bindTo) { me.bind(bindTo); } measure.position('absolute'); measure.setLocalXY(-1000, -1000); measure.hide(); if (fixedWidth) { measure.setWidth(fixedWidth); } }, getSize: function(text){ var measure = this.measure, size; measure.update(text); size = measure.getSize(); measure.update(''); return size; }, bind: function(el){ var me = this; me.el = Ext.get(el); me.measure.setStyle( me.el.getStyles('font-size','font-style', 'font-weight', 'font-family','line-height', 'text-transform', 'letter-spacing') ); }, setFixedWidth : function(width){ this.measure.setWidth(width); }, getWidth : function(text){ this.measure.dom.style.width = 'auto'; return this.getSize(text).width; }, getHeight : function(text){ return this.getSize(text).height; }, destroy: function(){ var me = this; me.measure.remove(); delete me.el; delete me.measure; } }, function(){ Ext.Element.addMethods({ getTextWidth : function(text, min, max){ return Ext.Number.constrain(Ext.util.TextMetrics.measure(this.dom, Ext.value(text, this.dom.innerHTML, true)).width, min || 0, max || 1000000); } }); }); Ext.define('Ext.button.Button', { alias: 'widget.button', extend: Ext.Component , mixins: { queryable: Ext.Queryable }, alternateClassName: 'Ext.Button', isButton: true, componentLayout: 'button', hidden: false, disabled: false, pressed: false, tabIndex: 0, enableToggle: false, menuAlign: 'tl-bl?', showEmptyMenu: false, textAlign: 'center', clickEvent: 'click', preventDefault: true, handleMouseEvents: true, tooltipType: 'qtip', baseCls: Ext.baseCSSPrefix + 'btn', pressedCls: 'pressed', overCls: 'over', focusCls: 'focus', menuActiveCls: 'menu-active', hrefTarget: '_blank', ariaRole: 'button', childEls: [ 'btnEl', 'btnWrap', 'btnInnerEl', 'btnIconEl' ], renderTpl: [ ' {splitCls}', '{childElCls}" unselectable="on">', '', '', '{text}', '', 'background-image:url({iconUrl});', 'font-family:{glyphFontFamily};">', '&#{glyph}; ', '', '', '', '', '', ' title="{closeText}" aria-label="{closeText}"', '', '>', '', '' ], scale: 'small', allowedScales: ['small', 'medium', 'large'], iconAlign: 'left', arrowAlign: 'right', arrowCls: 'arrow', maskOnDisable: false, shrinkWrap: 3, frame: true, hasFrameTable: function () { return this.href && this.frameTable; }, frameTableListener: function () { if (!this.disabled) { this.doNavigate(); } }, doNavigate: function () { if (this.hrefTarget === '_blank') { window.open(this.href, this.hrefTarget); } else { location.href = this.href; } }, _triggerRegion: {}, initComponent: function() { var me = this; me.autoEl = { tag: 'a', hidefocus: 'on', unselectable: 'on' }; me.addCls(Ext.baseCSSPrefix + 'unselectable'); me.callParent(arguments); me.addEvents( 'click', 'toggle', 'mouseover', 'mouseout', 'menushow', 'menuhide', 'menutriggerover', 'menutriggerout', 'textchange', 'iconchange', 'glyphchange' ); if (me.menu) { me.split = true; me.menu = Ext.menu.Manager.get(me.menu); me.menu.ownerButton = me; } if (me.url) { me.href = me.url; } if (me.href && !me.hasOwnProperty('preventDefault')) { me.preventDefault = false; } if (Ext.isString(me.toggleGroup) && me.toggleGroup !== '') { me.enableToggle = true; } if (me.html && !me.text) { me.text = me.html; delete me.html; } me.glyphCls = me.baseCls + '-glyph'; }, getActionEl: function() { return this.el; }, getFocusEl: function() { return this.el; }, onDisable: function(){ this.callParent(arguments); }, setComponentCls: function() { var me = this, cls = me.getComponentCls(); if (!Ext.isEmpty(me.oldCls)) { me.removeClsWithUI(me.oldCls); me.removeClsWithUI(me.pressedCls); } me.oldCls = cls; me.addClsWithUI(cls); }, getComponentCls: function() { var me = this, cls; if (me.iconCls || me.icon || me.glyph) { cls = [me.text ? 'icon-text-' + me.iconAlign : 'icon']; } else if (me.text) { cls = ['noicon']; } else { cls = []; } if (me.pressed) { cls[cls.length] = me.pressedCls; } return cls; }, beforeRender: function () { var me = this, autoEl = me.autoEl, href = me.getHref(), hrefTarget = me.hrefTarget; if (!me.disabled) { autoEl.tabIndex = me.tabIndex; } if (href) { autoEl.href = href; if (hrefTarget) { autoEl.target = hrefTarget; } } me.callParent(); me.oldCls = me.getComponentCls(); me.addClsWithUI(me.oldCls); Ext.applyIf(me.renderData, me.getTemplateArgs()); }, onRender: function() { var me = this, addOnclick, btn, btnListeners; me.doc = Ext.getDoc(); me.callParent(arguments); btn = me.el; if (me.tooltip) { me.setTooltip(me.tooltip, true); } if (me.handleMouseEvents) { btnListeners = { scope: me, mouseover: me.onMouseOver, mouseout: me.onMouseOut, mousedown: me.onMouseDown }; if (me.split) { btnListeners.mousemove = me.onMouseMove; } } else { btnListeners = { scope: me }; } if (me.menu) { me.mon(me.menu, { scope: me, show: me.onMenuShow, hide: me.onMenuHide }); me.keyMap = new Ext.util.KeyMap({ target: me.el, key: Ext.EventObject.DOWN, handler: me.onDownKey, scope: me }); } if (me.repeat) { me.mon(new Ext.util.ClickRepeater(btn, Ext.isObject(me.repeat) ? me.repeat: {}), 'click', me.onRepeatClick, me); } else { if (btnListeners[me.clickEvent]) { addOnclick = true; } else { btnListeners[me.clickEvent] = me.onClick; } } me.mon(btn, btnListeners); if (me.hasFrameTable()) { me.mon(me.frameTable, 'click', me.frameTableListener, me); } if (addOnclick) { me.mon(btn, me.clickEvent, me.onClick, me); } Ext.button.Manager.register(me); }, getTemplateArgs: function() { var me = this, glyph = me.glyph, glyphFontFamily = Ext._glyphFontFamily, glyphParts; if (typeof glyph === 'string') { glyphParts = glyph.split('@'); glyph = glyphParts[0]; glyphFontFamily = glyphParts[1]; } return { innerCls : me.getInnerCls(), splitCls : me.getSplitCls(), iconUrl : me.icon, iconCls : me.iconCls, glyph: glyph, glyphCls: glyph ? me.glyphCls : '', glyphFontFamily: glyphFontFamily, text : me.text || ' ', closeText: me.closeText }; }, setHref: function(href) { this.href = href; this.el.dom.href = this.getHref(); }, getHref: function() { var me = this, href = me.href; return href ? Ext.urlAppend(href, Ext.Object.toQueryString(Ext.apply({}, me.params, me.baseParams))) : false; }, setParams: function(params) { this.params = params; this.el.dom.href = this.getHref(); }, getSplitCls: function() { var me = this; return me.split ? (me.baseCls + '-' + me.arrowCls) + ' ' + (me.baseCls + '-' + me.arrowCls + '-' + me.arrowAlign) : ''; }, getInnerCls: function() { return this.textAlign ? this.baseCls + '-inner-' + this.textAlign : ''; }, setIcon: function(icon) { icon = icon || ''; var me = this, btnIconEl = me.btnIconEl, oldIcon = me.icon || ''; me.icon = icon; if (icon != oldIcon) { if (btnIconEl) { btnIconEl.setStyle('background-image', icon ? 'url(' + icon + ')': ''); me.setComponentCls(); if (me.didIconStateChange(oldIcon, icon)) { me.updateLayout(); } } me.fireEvent('iconchange', me, oldIcon, icon); } return me; }, setIconCls: function(cls) { cls = cls || ''; var me = this, btnIconEl = me.btnIconEl, oldCls = me.iconCls || ''; me.iconCls = cls; if (oldCls != cls) { if (btnIconEl) { btnIconEl.removeCls(oldCls); btnIconEl.addCls(cls); me.setComponentCls(); if (me.didIconStateChange(oldCls, cls)) { me.updateLayout(); } } me.fireEvent('iconchange', me, oldCls, cls); } return me; }, setGlyph: function(glyph) { glyph = glyph || 0; var me = this, btnIconEl = me.btnIconEl, oldGlyph = me.glyph, fontFamily, glyphParts; me.glyph = glyph; if (btnIconEl) { if (typeof glyph === 'string') { glyphParts = glyph.split('@'); glyph = glyphParts[0]; fontFamily = glyphParts[1] || Ext._glyphFontFamily; } if (!glyph) { btnIconEl.dom.innerHTML = ''; } else if (oldGlyph != glyph) { btnIconEl.dom.innerHTML = '&#' + glyph + ';'; } if (fontFamily) { btnIconEl.setStyle('font-family', fontFamily); } } me.fireEvent('glyphchange', me, me.glyph, oldGlyph); return me; }, setTooltip: function(tooltip, initial) { var me = this; if (me.rendered) { if (!initial || !tooltip) { me.clearTip(); } if (tooltip) { if (Ext.quickTipsActive && Ext.isObject(tooltip)) { Ext.tip.QuickTipManager.register(Ext.apply({ target: me.el.id }, tooltip)); me.tooltip = tooltip; } else { me.el.dom.setAttribute(me.getTipAttr(), tooltip); } } } else { me.tooltip = tooltip; } return me; }, setTextAlign: function(align) { var me = this, btnEl = me.btnEl; if (btnEl) { btnEl.removeCls(me.baseCls + '-inner-' + me.textAlign); btnEl.addCls(me.baseCls + '-inner-' + align); } me.textAlign = align; return me; }, getTipAttr: function(){ return this.tooltipType == 'qtip' ? 'data-qtip' : 'title'; }, getRefItems: function(deep){ var menu = this.menu, items; if (menu) { items = menu.getRefItems(deep); items.unshift(menu); } return items || []; }, clearTip: function() { var me = this, el = me.el; if (Ext.quickTipsActive && Ext.isObject(me.tooltip)) { Ext.tip.QuickTipManager.unregister(el); } else { el.dom.removeAttribute(me.getTipAttr()); } }, beforeDestroy: function() { var me = this; if (me.rendered) { me.clearTip(); } if (me.menu && me.destroyMenu !== false) { Ext.destroy(me.menu); } Ext.destroy(me.btnInnerEl, me.repeater); me.callParent(); }, onDestroy: function() { var me = this; if (me.rendered) { me.doc.un('mouseover', me.monitorMouseOver, me); delete me.doc; Ext.destroy(me.keyMap); delete me.keyMap; } Ext.button.Manager.unregister(me); me.callParent(); }, setHandler: function(handler, scope) { this.handler = handler; this.scope = scope; return this; }, setText: function(text) { text = text || ''; var me = this, oldText = me.text || ''; if (text != oldText) { me.text = text; if (me.rendered) { me.btnInnerEl.update(text || ' '); me.setComponentCls(); if (Ext.isStrict && Ext.isIE8) { me.el.repaint(); } me.updateLayout(); } me.fireEvent('textchange', me, oldText, text); } return me; }, didIconStateChange: function(old, current) { var currentEmpty = Ext.isEmpty(current); return Ext.isEmpty(old) ? !currentEmpty : currentEmpty; }, getText: function() { return this.text; }, toggle: function(state, suppressEvent) { var me = this; state = state === undefined ? !me.pressed: !!state; if (state !== me.pressed) { if (me.rendered) { me[state ? 'addClsWithUI': 'removeClsWithUI'](me.pressedCls); } me.pressed = state; if (!suppressEvent) { me.fireEvent('toggle', me, state); Ext.callback(me.toggleHandler, me.scope || me, [me, state]); } } return me; }, maybeShowMenu: function(){ var me = this; if (me.menu && !me.hasVisibleMenu() && !me.ignoreNextClick) { me.showMenu(true); } }, showMenu: function( fromEvent) { var me = this, menu = me.menu; if (me.rendered) { if (me.tooltip && Ext.quickTipsActive && me.getTipAttr() != 'title') { Ext.tip.QuickTipManager.getQuickTip().cancelShow(me.el); } if (menu.isVisible()) { menu.hide(); } if (!fromEvent || me.showEmptyMenu || menu.items.getCount() > 0) { menu.showBy(me.el, me.menuAlign); } } return me; }, hideMenu: function() { if (this.hasVisibleMenu()) { this.menu.hide(); } return this; }, hasVisibleMenu: function() { var menu = this.menu; return menu && menu.rendered && menu.isVisible(); }, onRepeatClick: function(repeat, e) { this.onClick(e); }, onClick: function(e) { var me = this; me.doPreventDefault(e); if (e.type !== 'keydown' && e.button !== 0) { return; } if (!me.disabled) { me.doToggle(); me.maybeShowMenu(); me.fireHandler(e); } }, doPreventDefault: function(e) { if (this.preventDefault || (this.disabled && this.getHref()) && e) { e.preventDefault(); } }, fireHandler: function(e) { var me = this, handler = me.handler; if (me.fireEvent('click', me, e) !== false) { if (handler) { handler.call(me.scope || me, me, e); } } }, doToggle: function() { var me = this; if (me.enableToggle && (me.allowDepress !== false || !me.pressed)) { me.toggle(); } }, onMouseOver: function(e) { var me = this; if (!me.disabled && !e.within(me.el, true, true)) { me.onMouseEnter(e); } }, onMouseOut: function(e) { var me = this; if (!e.within(me.el, true, true)) { if (me.overMenuTrigger) { me.onMenuTriggerOut(e); } me.onMouseLeave(e); } }, onMouseMove: function(e) { var me = this, el = me.el, over = me.overMenuTrigger, overPosition, triggerRegion; if (me.split) { overPosition = (me.arrowAlign === 'right') ? e.getX() - me.getX() : e.getY() - el.getY(); triggerRegion = me.getTriggerRegion(); if (overPosition > triggerRegion.begin && overPosition < triggerRegion.end) { if (!over) { me.onMenuTriggerOver(e); } } else { if (over) { me.onMenuTriggerOut(e); } } } }, getTriggerRegion: function() { var me = this, region = me._triggerRegion, triggerSize = me.getTriggerSize(), btnSize = me.arrowAlign === 'right' ? me.getWidth() : me.getHeight(); region.begin = btnSize - triggerSize; region.end = btnSize; return region; }, getTriggerSize: function() { var me = this, size = me.triggerSize, side, sideFirstLetter; if (size == null) { side = me.arrowAlign; sideFirstLetter = side.charAt(0); size = me.triggerSize = me.el.getFrameWidth(sideFirstLetter) + me.getBtnWrapFrameWidth(sideFirstLetter) if (me.frameSize) { size = me.triggerSize += me.frameSize[side]; } } return size; }, getBtnWrapFrameWidth: function(side) { return this.btnWrap.getFrameWidth(side); }, addOverCls: function() { if (!this.disabled) { this.addClsWithUI(this.overCls); } }, removeOverCls: function() { this.removeClsWithUI(this.overCls); }, onMouseEnter: function(e) { this.fireEvent('mouseover', this, e); }, onMouseLeave: function(e) { this.fireEvent('mouseout', this, e); }, onMenuTriggerOver: function(e) { var me = this, arrowTip = me.arrowTooltip; me.overMenuTrigger = true; if (me.split && arrowTip) { me.btnWrap.dom.setAttribute(me.getTipAttr(), arrowTip); } me.fireEvent('menutriggerover', me, me.menu, e); }, onMenuTriggerOut: function(e) { var me = this; delete me.overMenuTrigger; if (me.split && me.arrowTooltip) { me.btnWrap.dom.setAttribute(me.getTipAttr(), ''); } me.fireEvent('menutriggerout', me, me.menu, e); }, enable: function(silent) { var me = this; me.callParent(arguments); me.removeClsWithUI('disabled'); if (me.rendered) { me.el.dom.setAttribute('tabIndex', me.tabIndex); } return me; }, disable: function(silent) { var me = this; me.callParent(arguments); me.addClsWithUI('disabled'); me.removeClsWithUI(me.overCls); if (me.rendered) { me.el.dom.removeAttribute('tabIndex'); } if (me.btnInnerEl && Ext.isIE7m) { me.btnInnerEl.repaint(); } return me; }, setScale: function(scale) { var me = this, ui = me.ui.replace('-' + me.scale, ''); if (!Ext.Array.contains(me.allowedScales, scale)) { throw('#setScale: scale must be an allowed scale (' + me.allowedScales.join(', ') + ')'); } me.scale = scale; me.setUI(ui); }, setUI: function(ui) { var me = this; if (me.scale && !ui.match(me.scale)) { ui = ui + '-' + me.scale; } me.callParent([ui]); }, onMouseDown: function(e) { var me = this; if (Ext.isIE) { me.getFocusEl().focus(); } if (!me.disabled && e.button === 0) { Ext.button.Manager.onButtonMousedown(me, e); me.addClsWithUI(me.pressedCls); } }, onMouseUp: function(e) { var me = this; if (!me.isDestroyed && e.button === 0) { if (!me.pressed) { me.removeClsWithUI(me.pressedCls); } } }, onMenuShow: function(e) { var me = this; me.ignoreNextClick = 0; me.addClsWithUI(me.menuActiveCls); me.fireEvent('menushow', me, me.menu); }, onMenuHide: function(e) { var me = this; me.removeClsWithUI(me.menuActiveCls); me.ignoreNextClick = Ext.defer(me.restoreClick, 250, me); me.fireEvent('menuhide', me, me.menu); me.focus(); }, restoreClick: function() { this.ignoreNextClick = 0; }, onDownKey: function(k, e) { var me = this; if (me.menu && !me.disabled) { me.showMenu(); e.stopEvent(); return false; } } }); Ext.define('Ext.layout.container.boxOverflow.Menu', { extend: Ext.layout.container.boxOverflow.None , alternateClassName: 'Ext.layout.boxOverflow.Menu', noItemsMenuText : '', constructor: function(layout) { var me = this; me.callParent(arguments); me.triggerButtonCls = me.triggerButtonCls || Ext.baseCSSPrefix + 'box-menu-after'; me.menuItems = []; }, beginLayout: function (ownerContext) { this.callParent(arguments); this.clearOverflow(ownerContext); }, beginLayoutCycle: function (ownerContext, firstCycle) { this.callParent(arguments); if (!firstCycle) { this.clearOverflow(ownerContext); this.layout.cacheChildItems(ownerContext); } }, onRemove: function(comp){ Ext.Array.remove(this.menuItems, comp); }, getSuffixConfig: function() { var me = this, layout = me.layout, owner = layout.owner, oid = owner.id; me.menu = new Ext.menu.Menu({ listeners: { scope: me, beforeshow: me.beforeMenuShow } }); me.menuTrigger = new Ext.button.Button({ id: oid + '-menu-trigger', cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.triggerButtonCls + ' ' + Ext.baseCSSPrefix + 'toolbar-item', plain: owner.usePlainButtons, ownerCt: owner, ownerLayout: layout, iconCls: Ext.baseCSSPrefix + me.getOwnerType(owner) + '-more-icon', ui: owner instanceof Ext.toolbar.Toolbar ? 'default-toolbar' : 'default', menu: me.menu, showEmptyMenu: true, getSplitCls: function() { return '';} }); return me.menuTrigger.getRenderTree(); }, getOverflowCls: function() { return Ext.baseCSSPrefix + this.layout.direction + '-box-overflow-body'; }, handleOverflow: function(ownerContext) { var me = this, layout = me.layout, names = layout.names, plan = ownerContext.state.boxPlan, posArgs = [null, null]; me.showTrigger(ownerContext); if (me.layout.direction !== 'vertical') { posArgs[names.heightIndex] = (plan.maxSize - me.menuTrigger[names.getHeight]()) / 2; me.menuTrigger.setPosition.apply(me.menuTrigger, posArgs); } return { reservedSpace: me.triggerTotalWidth }; }, captureChildElements: function() { var me = this, menuTrigger = me.menuTrigger, names = me.layout.names; if (menuTrigger.rendering) { menuTrigger.finishRender(); me.triggerTotalWidth = menuTrigger[names.getWidth]() + menuTrigger.el.getMargin(names.parallelMargins); } }, _asLayoutRoot: { isRoot: true }, clearOverflow: function(ownerContext) { var me = this, items = me.menuItems, item, i = 0, length = items.length, owner = me.layout.owner, asLayoutRoot = me._asLayoutRoot; owner.suspendLayouts(); me.captureChildElements(); me.hideTrigger(); owner.resumeLayouts(); for (; i < length; i++) { item = items[i]; item.suspendLayouts(); item.show(); item.resumeLayouts(asLayoutRoot); } items.length = 0; }, showTrigger: function(ownerContext) { var me = this, layout = me.layout, owner = layout.owner, names = layout.names, startProp = names.x, sizeProp = names.width, plan = ownerContext.state.boxPlan, available = plan.targetSize[sizeProp], childItems = ownerContext.childItems, len = childItems.length, menuTrigger = me.menuTrigger, childContext, comp, i, props; menuTrigger.suspendLayouts(); menuTrigger.show(); menuTrigger.resumeLayouts(me._asLayoutRoot); available -= me.triggerTotalWidth; owner.suspendLayouts(); me.menuItems.length = 0; for (i = 0; i < len; i++) { childContext = childItems[i]; props = childContext.props; if (props[startProp] + props[sizeProp] > available) { comp = childContext.target; me.menuItems.push(comp); comp.hide(); } } owner.resumeLayouts(); }, hideTrigger: function() { var menuTrigger = this.menuTrigger; if (menuTrigger) { menuTrigger.hide(); } }, beforeMenuShow: function(menu) { var me = this, items = me.menuItems, i = 0, len = items.length, item, prev, needsSep = function(group, prev){ return group.isXType('buttongroup') && !(prev instanceof Ext.toolbar.Separator); }; menu.suspendLayouts(); me.clearMenu(); menu.removeAll(); for (; i < len; i++) { item = items[i]; if (!i && (item instanceof Ext.toolbar.Separator)) { continue; } if (prev && (needsSep(item, prev) || needsSep(prev, item))) { menu.add('-'); } me.addComponentToMenu(menu, item); prev = item; } if (menu.items.length < 1) { menu.add(me.noItemsMenuText); } menu.resumeLayouts(); }, createMenuConfig : function(component, hideOnClick) { var me = this, config = Ext.apply({}, component.initialConfig), group = component.toggleGroup; Ext.copyTo(config, component, [ 'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu', 'tabIndex' ]); Ext.apply(config, { text : component.overflowText || component.text, hideOnClick: hideOnClick, destroyMenu: false, listeners : {} }); if (component.isFormField) { config.value = component.getValue(); config.listeners.change = function(c, newVal, oldVal) { component.setValue(newVal); } } else if (group || component.enableToggle) { Ext.apply(config, { hideOnClick: false, group : group, checked: component.pressed, handler: function(item, e) { component.onClick(e); } }); } if (component.isButton && !component.changeListenersAdded) { component.on({ textchange: me.onButtonAttrChange, iconchange: me.onButtonAttrChange, toggle: me.onButtonToggle }); component.changeListenersAdded = true; } delete config.margin; delete config.ownerCt; delete config.xtype; delete config.id; delete config.itemId; return config; }, onButtonAttrChange: function(btn) { var clone = btn.overflowClone; clone.suspendLayouts(); clone.setText(btn.text); clone.setIcon(btn.icon); clone.setIconCls(btn.iconCls); clone.resumeLayouts(true); }, onButtonToggle: function(btn, state) { if (btn.overflowClone.checked !== state) { btn.overflowClone.setChecked(state); } }, addComponentToMenu : function(menu, component) { var me = this, i, items, iLen; if (component instanceof Ext.toolbar.Separator) { menu.add('-'); } else if (component.isComponent) { if (component.isXType('splitbutton')) { component.overflowClone = menu.add(me.createMenuConfig(component, true)); } else if (component.isXType('button')) { component.overflowClone = menu.add(me.createMenuConfig(component, !component.menu)); } else if (component.isXType('buttongroup')) { items = component.items.items; iLen = items.length; for (i = 0; i < iLen; i++) { me.addComponentToMenu(menu, items[i]); } } else { component.overflowClone = menu.add(Ext.create(Ext.getClassName(component), me.createMenuConfig(component))); } } }, clearMenu : function() { var menu = this.menu, items, i, iLen, item; if (menu && menu.items) { items = menu.items.items; iLen = items.length; for (i = 0; i < iLen; i++) { item = items[i]; if (item.setMenu) { item.setMenu(null); } } } }, destroy: function() { var trigger = this.menuTrigger; if (trigger && !this.layout.owner.items.contains(trigger)) { delete trigger.ownerCt; } Ext.destroy(this.menu, trigger); } }); Ext.define('Ext.layout.container.boxOverflow.Scroller', { extend: Ext.layout.container.boxOverflow.None , alternateClassName: 'Ext.layout.boxOverflow.Scroller', mixins: { observable: Ext.util.Observable }, animateScroll: false, scrollIncrement: 20, wheelIncrement: 10, scrollRepeatInterval: 60, scrollDuration: 400, scrollerCls: Ext.baseCSSPrefix + 'box-scroller', constructor: function(layout, config) { var me = this; me.layout = layout; Ext.apply(me, config || {}); me.mixins.observable.constructor.call(me); me.addEvents( 'scroll' ); me.scrollPosition = 0; me.scrollSize = 0; }, getPrefixConfig: function() { var me = this, layout = me.layout, owner = layout.owner, cls; me.initCSSClasses(); cls = Ext.layout.container.Box.prototype.innerCls + ' ' + me.beforeCtCls; if (owner.plain) { cls += ' ' + me.scrollerCls + '-plain'; } return { role: 'presentation', cls: cls, cn : { role: 'presentation', id : owner.id + layout.names.beforeScrollerSuffix, cls: me.scrollerCls + ' ' + me.beforeScrollerCls, style: 'display:none' } }; }, getSuffixConfig: function() { var me = this, layout = me.layout, owner = layout.owner, cls = Ext.layout.container.Box.prototype.innerCls + ' ' + me.afterCtCls; if (owner.plain) { cls += ' ' + me.scrollerCls + '-plain'; } return { role: 'presentation', cls: cls, cn : { role: 'presentation', id : owner.id + layout.names.afterScrollerSuffix, cls: me.scrollerCls + ' ' + me.afterScrollerCls, style: 'display:none' } }; }, getOverflowCls: function() { return Ext.baseCSSPrefix + this.layout.direction + '-box-overflow-body'; }, initCSSClasses: function() { var me = this, prefix = Ext.baseCSSPrefix, layout = me.layout, names = layout.names, beforeXName = names.beforeX, afterXName = names.afterX, type = me.getOwnerType(layout.owner); me.beforeCtCls = me.beforeCtCls || prefix + 'box-scroller-' + beforeXName; me.afterCtCls = me.afterCtCls || prefix + 'box-scroller-' + afterXName; me.beforeScrollerCls = me.beforeScrollerCls || prefix + type + '-scroll-' + beforeXName; me.afterScrollerCls = me.afterScrollerCls || prefix + type + '-scroll-' + afterXName; }, beginLayout: function (ownerContext) { var layout = this.layout; ownerContext.innerCtScrollPos = this.getScrollPosition(); this.callParent(arguments); }, completeLayout: function(ownerContext) { var me = this, plan = ownerContext.state.boxPlan, names = me.layout.names, last; if (plan && plan.tooNarrow) { last = ownerContext.childItems[ownerContext.childItems.length - 1]; me.scrollSize = last.props[names.x] + last.props[names.width]; me.updateScrollButtons(); } this.callParent(arguments); }, finishedLayout: function(ownerContext) { var me = this, layout = me.layout, scrollPos = Math.min(me.getMaxScrollPosition(), ownerContext.innerCtScrollPos); layout.innerCt[layout.names.setScrollLeft](scrollPos); }, handleOverflow: function(ownerContext) { var me = this, methodName = me.layout.names.getWidth; me.showScrollers(); return { reservedSpace: me.beforeCt[methodName]() + me.afterCt[methodName]() }; }, captureChildElements: function() { var me = this, el = me.layout.owner.el, before, after, hoverCls, pressedSuffix, pressedCls, hoverSuffix; if (!me.beforeCt) { hoverSuffix = '-hover'; pressedSuffix = '-pressed'; hoverCls = me.scrollerCls + hoverSuffix; pressedCls = me.scrollerCls + pressedSuffix; before = me.beforeScroller = el.getById(me.layout.owner.id + '-before-scroller'); after = me.afterScroller = el.getById(me.layout.owner.id + '-after-scroller'); me.beforeCt = before.up(''); me.afterCt = after.up(''); me.createWheelListener(); before.addClsOnOver(hoverCls); before.addClsOnOver(me.beforeScrollerCls + hoverSuffix); before.addClsOnClick(pressedCls); before.addClsOnClick(me.beforeScrollerCls + pressedSuffix); after.addClsOnOver(hoverCls); after.addClsOnOver(me.afterScrollerCls + hoverSuffix); after.addClsOnClick(pressedCls); after.addClsOnClick(me.afterScrollerCls + pressedSuffix); before.setVisibilityMode(Ext.Element.DISPLAY); after.setVisibilityMode(Ext.Element.DISPLAY); me.beforeRepeater = new Ext.util.ClickRepeater(before, { interval: me.scrollRepeatInterval, handler : me.scrollLeft, scope : me }); me.afterRepeater = new Ext.util.ClickRepeater(after, { interval: me.scrollRepeatInterval, handler : me.scrollRight, scope : me }); } }, createWheelListener: function() { var me = this; me.layout.innerCt.on({ mousewheel: function(e) { me.scrollBy(me.getWheelDelta(e) * me.wheelIncrement * -1, false); }, stopEvent: true }); }, getWheelDelta: function (e) { return e.getWheelDelta(); }, clearOverflow: function () { this.hideScrollers(); }, showScrollers: function() { var me = this; me.captureChildElements(); me.beforeScroller.show(); me.afterScroller.show(); me.layout.owner.addClsWithUI(me.layout.direction === 'vertical' ? 'vertical-scroller' : 'scroller'); }, hideScrollers: function() { var me = this; if (me.beforeScroller !== undefined) { me.beforeScroller.hide(); me.afterScroller.hide(); me.layout.owner.removeClsWithUI(me.layout.direction === 'vertical' ? 'vertical-scroller' : 'scroller'); } }, destroy: function() { var me = this; Ext.destroy(me.beforeRepeater, me.afterRepeater, me.beforeScroller, me.afterScroller, me.beforeCt, me.afterCt); }, scrollBy: function(delta, animate) { this.scrollTo(this.getScrollPosition() + delta, animate); }, getScrollAnim: function() { return { duration: this.scrollDuration, callback: this.updateScrollButtons, scope : this }; }, updateScrollButtons: function() { var me = this, beforeMeth, afterMeth, beforeCls, afterCls, disabledCls, suffix = '-disabled'; if (me.beforeScroller == null || me.afterScroller == null) { return; } beforeMeth = me.atExtremeBefore() ? 'addCls' : 'removeCls'; afterMeth = me.atExtremeAfter() ? 'addCls' : 'removeCls'; disabledCls = me.scrollerCls + suffix; beforeCls = [disabledCls, me.beforeScrollerCls + suffix]; afterCls = [disabledCls, me.afterScrollerCls + suffix]; me.beforeScroller[beforeMeth](beforeCls); me.afterScroller[afterMeth](afterCls); me.scrolling = false; }, scrollLeft: function() { this.scrollBy(-this.scrollIncrement, false); }, scrollRight: function() { this.scrollBy(this.scrollIncrement, false); }, getScrollPosition: function(){ var me = this, layout = me.layout, result; if (isNaN(me.scrollPosition)) { result = layout.innerCt[layout.names.getScrollLeft](); } else { result = me.scrollPosition; } return result; }, getMaxScrollPosition: function() { var me = this, layout = me.layout, maxScrollPos = me.scrollSize - layout.innerCt[layout.names.getWidth](); return (maxScrollPos < 0) ? 0 : maxScrollPos; }, atExtremeBefore: function() { return !this.getScrollPosition(); }, atExtremeAfter: function() { return this.getScrollPosition() >= this.getMaxScrollPosition(); }, scrollTo: function(position, animate) { var me = this, layout = me.layout, names = layout.names, oldPosition = me.getScrollPosition(), newPosition = Ext.Number.constrain(position, 0, me.getMaxScrollPosition()); if (newPosition != oldPosition && !me.scrolling) { me.scrollPosition = NaN; if (animate === undefined) { animate = me.animateScroll; } layout.innerCt[names.scrollTo](names.beforeScrollX, newPosition, animate ? me.getScrollAnim() : false); if (animate) { me.scrolling = true; } else { me.updateScrollButtons(); } me.fireEvent('scroll', me, newPosition, animate ? me.getScrollAnim() : false); } }, scrollToItem: function(item, animate) { var me = this, layout = me.layout, owner = layout.owner, names = layout.names, visibility, box, newPos; item = me.getItem(item); if (item !== undefined) { if (item == owner.items.first()) { newPos = 0 } else if (item === owner.items.last()) { newPos = me.getMaxScrollPosition(); } else { visibility = me.getItemVisibility(item); if (!visibility.fullyVisible) { box = item.getBox(false, true); newPos = box[names.x]; if (visibility.hiddenEnd) { newPos -= (me.layout.innerCt[names.getWidth]() - box[names.width]); } } } if (newPos !== undefined) { me.scrollTo(newPos, animate); } } }, getItemVisibility: function(item) { var me = this, box = me.getItem(item).getBox(true, true), layout = me.layout, names = layout.names, itemStart = box[names.x], itemEnd = itemStart + box[names.width], scrollStart = me.getScrollPosition(), scrollEnd = scrollStart + layout.innerCt[names.getWidth](); return { hiddenStart : itemStart < scrollStart, hiddenEnd : itemEnd > scrollEnd, fullyVisible: itemStart > scrollStart && itemEnd < scrollEnd }; } }); Ext.define('Ext.util.Offset', { statics: { fromObject: function(obj) { return new this(obj.x, obj.y); } }, constructor: function(x, y) { this.x = (x != null && !isNaN(x)) ? x : 0; this.y = (y != null && !isNaN(y)) ? y : 0; return this; }, copy: function() { return new Ext.util.Offset(this.x, this.y); }, copyFrom: function(p) { this.x = p.x; this.y = p.y; }, toString: function() { return "Offset[" + this.x + "," + this.y + "]"; }, equals: function(offset) { return (this.x == offset.x && this.y == offset.y); }, round: function(to) { if (!isNaN(to)) { var factor = Math.pow(10, to); this.x = Math.round(this.x * factor) / factor; this.y = Math.round(this.y * factor) / factor; } else { this.x = Math.round(this.x); this.y = Math.round(this.y); } }, isZero: function() { return this.x == 0 && this.y == 0; } }); Ext.define('Ext.util.Region', { statics: { getRegion: function(el) { return Ext.fly(el).getRegion(); }, from: function(o) { return new this(o.top, o.right, o.bottom, o.left); } }, constructor : function(t, r, b, l) { var me = this; me.y = me.top = me[1] = t; me.right = r; me.bottom = b; me.x = me.left = me[0] = l; }, contains : function(region) { var me = this; return (region.x >= me.x && region.right <= me.right && region.y >= me.y && region.bottom <= me.bottom); }, intersect : function(region) { var me = this, t = Math.max(me.y, region.y), r = Math.min(me.right, region.right), b = Math.min(me.bottom, region.bottom), l = Math.max(me.x, region.x); if (b > t && r > l) { return new this.self(t, r, b, l); } else { return false; } }, union : function(region) { var me = this, t = Math.min(me.y, region.y), r = Math.max(me.right, region.right), b = Math.max(me.bottom, region.bottom), l = Math.min(me.x, region.x); return new this.self(t, r, b, l); }, constrainTo : function(r) { var me = this, constrain = Ext.Number.constrain; me.top = me.y = constrain(me.top, r.y, r.bottom); me.bottom = constrain(me.bottom, r.y, r.bottom); me.left = me.x = constrain(me.left, r.x, r.right); me.right = constrain(me.right, r.x, r.right); return me; }, adjust : function(t, r, b, l) { var me = this; me.top = me.y += t; me.left = me.x += l; me.right += r; me.bottom += b; return me; }, getOutOfBoundOffset: function(axis, p) { if (!Ext.isObject(axis)) { if (axis == 'x') { return this.getOutOfBoundOffsetX(p); } else { return this.getOutOfBoundOffsetY(p); } } else { p = axis; var d = new Ext.util.Offset(); d.x = this.getOutOfBoundOffsetX(p.x); d.y = this.getOutOfBoundOffsetY(p.y); return d; } }, getOutOfBoundOffsetX: function(p) { if (p <= this.x) { return this.x - p; } else if (p >= this.right) { return this.right - p; } return 0; }, getOutOfBoundOffsetY: function(p) { if (p <= this.y) { return this.y - p; } else if (p >= this.bottom) { return this.bottom - p; } return 0; }, isOutOfBound: function(axis, p) { if (!Ext.isObject(axis)) { if (axis == 'x') { return this.isOutOfBoundX(p); } else { return this.isOutOfBoundY(p); } } else { p = axis; return (this.isOutOfBoundX(p.x) || this.isOutOfBoundY(p.y)); } }, isOutOfBoundX: function(p) { return (p < this.x || p > this.right); }, isOutOfBoundY: function(p) { return (p < this.y || p > this.bottom); }, restrict: function(axis, p, factor) { if (Ext.isObject(axis)) { var newP; factor = p; p = axis; if (p.copy) { newP = p.copy(); } else { newP = { x: p.x, y: p.y }; } newP.x = this.restrictX(p.x, factor); newP.y = this.restrictY(p.y, factor); return newP; } else { if (axis == 'x') { return this.restrictX(p, factor); } else { return this.restrictY(p, factor); } } }, restrictX : function(p, factor) { if (!factor) { factor = 1; } if (p <= this.x) { p -= (p - this.x) * factor; } else if (p >= this.right) { p -= (p - this.right) * factor; } return p; }, restrictY : function(p, factor) { if (!factor) { factor = 1; } if (p <= this.y) { p -= (p - this.y) * factor; } else if (p >= this.bottom) { p -= (p - this.bottom) * factor; } return p; }, getSize: function() { return { width: this.right - this.x, height: this.bottom - this.y }; }, copy: function() { return new this.self(this.y, this.right, this.bottom, this.x); }, copyFrom: function(p) { var me = this; me.top = me.y = me[1] = p.y; me.right = p.right; me.bottom = p.bottom; me.left = me.x = me[0] = p.x; return this; }, toString: function() { return "Region[" + this.top + "," + this.right + "," + this.bottom + "," + this.left + "]"; }, translateBy: function(x, y) { if (arguments.length == 1) { y = x.y; x = x.x; } var me = this; me.top = me.y += y; me.right += x; me.bottom += y; me.left = me.x += x; return me; }, round: function() { var me = this; me.top = me.y = Math.round(me.y); me.right = Math.round(me.right); me.bottom = Math.round(me.bottom); me.left = me.x = Math.round(me.x); return me; }, equals: function(region) { return (this.top == region.top && this.right == region.right && this.bottom == region.bottom && this.left == region.left); } }); Ext.define('Ext.dd.DragDropManager', { singleton: true, alternateClassName: ['Ext.dd.DragDropMgr', 'Ext.dd.DDM'], ids: {}, handleIds: {}, dragCurrent: null, dragOvers: {}, deltaX: 0, deltaY: 0, preventDefault: true, stopPropagation: true, initialized: false, locked: false, init: function() { this.initialized = true; }, POINT: 0, INTERSECT: 1, mode: 0, notifyOccluded: false, dragCls: Ext.baseCSSPrefix + 'dd-drag-current', _execOnAll: function(sMethod, args) { var ids = this.ids, i, j, oDD, item; for (i in ids) { if (ids.hasOwnProperty(i)) { item = ids[i]; for (j in item) { if (item.hasOwnProperty(j)) { oDD = item[j]; if (! this.isTypeOfDD(oDD)) { continue; } oDD[sMethod].apply(oDD, args); } } } } }, _onLoad: function() { this.init(); var Event = Ext.EventManager; Event.on(document, "mouseup", this.handleMouseUp, this, true); Event.on(document, "mousemove", this.handleMouseMove, this, true); Event.on(window, "unload", this._onUnload, this, true); Event.on(window, "resize", this._onResize, this, true); }, _onResize: function(e) { this._execOnAll("resetConstraints", []); }, lock: function() { this.locked = true; }, unlock: function() { this.locked = false; }, isLocked: function() { return this.locked; }, locationCache: {}, useCache: true, clickPixelThresh: 3, clickTimeThresh: 350, dragThreshMet: false, clickTimeout: null, startX: 0, startY: 0, regDragDrop: function(oDD, sGroup) { if (!this.initialized) { this.init(); } if (!this.ids[sGroup]) { this.ids[sGroup] = {}; } this.ids[sGroup][oDD.id] = oDD; }, removeDDFromGroup: function(oDD, sGroup) { if (!this.ids[sGroup]) { this.ids[sGroup] = {}; } var obj = this.ids[sGroup]; if (obj && obj[oDD.id]) { delete obj[oDD.id]; } }, _remove: function(oDD, clearGroup) { if (this.clearingAll) { return; } var ids = this.ids, groups = oDD.groups, g; for (g in groups) { if (groups.hasOwnProperty(g)) { if (clearGroup) { delete ids[g]; } else if (ids[g]) { delete ids[g][oDD.id]; } } } delete this.handleIds[oDD.id]; }, regHandle: function(sDDId, sHandleId) { if (!this.handleIds[sDDId]) { this.handleIds[sDDId] = {}; } this.handleIds[sDDId][sHandleId] = sHandleId; }, isDragDrop: function(id) { return ( this.getDDById(id) ) ? true : false; }, getRelated: function(p_oDD, bTargetsOnly) { var oDDs = [], i, j, dd; for (i in p_oDD.groups) { for (j in this.ids[i]) { dd = this.ids[i][j]; if (! this.isTypeOfDD(dd)) { continue; } if (!bTargetsOnly || dd.isTarget) { oDDs[oDDs.length] = dd; } } } return oDDs; }, isLegalTarget: function (oDD, oTargetDD) { var targets = this.getRelated(oDD, true), i, len; for (i=0, len=targets.length;i me.clickPixelThresh || diffY > me.clickPixelThresh) { me.startDrag(me.startX, me.startY); } } if (me.dragThreshMet) { current.b4Drag(e); current.onDrag(e); if (!current.moveOnly) { me.fireEvents(e, false); } } me.stopEvent(e); return true; }, fireEvents: function(e, isDrop) { var me = this, dragCurrent = me.dragCurrent, dragEl, oldDragElTop, mousePoint = e.getPoint(), overTarget, overTargetEl, allTargets = [], oldOvers = [], outEvts = [], overEvts = [], dropEvts = [], enterEvts = [], xy, needsSort, i, len, sGroup; if (!dragCurrent || dragCurrent.isLocked()) { return; } if (!me.notifyOccluded && (!Ext.supports.PointerEvents || Ext.isIE10m || Ext.isOpera) && !(dragCurrent.deltaX < 0 || dragCurrent.deltaY < 0)) { dragEl = dragCurrent.getDragEl(); oldDragElTop = dragEl.style.top; dragEl.style.top = '-10000px'; xy = e.getXY(); e.target = document.elementFromPoint(xy[0], xy[1]); dragEl.style.top = oldDragElTop; } for (i in me.dragOvers) { overTarget = me.dragOvers[i]; if (!me.isTypeOfDD(overTarget)) { continue; } if (me.notifyOccluded) { if (!this.isOverTarget(mousePoint, overTarget, me.mode)) { outEvts.push(overTarget); } } else { if (!e.within(overTarget.getEl())) { outEvts.push(overTarget); } } oldOvers[i] = true; delete me.dragOvers[i]; } for (sGroup in dragCurrent.groups) { if ("string" != typeof sGroup) { continue; } for (i in me.ids[sGroup]) { overTarget = me.ids[sGroup][i]; if (me.isTypeOfDD(overTarget) && (overTargetEl = overTarget.getEl()) && (overTarget.isTarget) && (!overTarget.isLocked()) && (Ext.fly(overTargetEl).isVisible(true)) && ((overTarget != dragCurrent) || (dragCurrent.ignoreSelf === false))) { if (me.notifyOccluded) { if ((overTarget.zIndex = me.getZIndex(overTargetEl)) !== -1) { needsSort = true; } allTargets.push(overTarget); } else { if (e.within(overTarget.getEl())) { allTargets.push(overTarget); break; } } } } } if (needsSort) { Ext.Array.sort(allTargets, me.byZIndex); } for (i = 0, len = allTargets.length; i < len; i++) { overTarget = allTargets[i]; if (me.isOverTarget(mousePoint, overTarget, me.mode)) { if (isDrop) { dropEvts.push( overTarget ); } else { if (!oldOvers[overTarget.id]) { enterEvts.push( overTarget ); } else { overEvts.push( overTarget ); } me.dragOvers[overTarget.id] = overTarget; } if (!me.notifyOccluded) { break; } } } if (me.mode) { if (outEvts.length) { dragCurrent.b4DragOut(e, outEvts); dragCurrent.onDragOut(e, outEvts); } if (enterEvts.length) { dragCurrent.onDragEnter(e, enterEvts); } if (overEvts.length) { dragCurrent.b4DragOver(e, overEvts); dragCurrent.onDragOver(e, overEvts); } if (dropEvts.length) { dragCurrent.b4DragDrop(e, dropEvts); dragCurrent.onDragDrop(e, dropEvts); } } else { for (i=0, len=outEvts.length; i', '', '', '{%if (oh.getSuffixConfig!==Ext.emptyFn) {', 'if(oc=oh.getSuffixConfig())dh.generateMarkup(oc, out)', '}%}', { disableFormats: true, definitions: 'var dh=Ext.DomHelper;' } ], constructor: function(config) { var me = this, type; me.callParent(arguments); me.flexSortFn = Ext.Function.bind(me.flexSort, me); me.initOverflowHandler(); type = typeof me.padding; if (type == 'string' || type == 'number') { me.padding = Ext.util.Format.parseBox(me.padding); me.padding.height = me.padding.top + me.padding.bottom; me.padding.width = me.padding.left + me.padding.right; } }, _percentageRe: /^\s*(\d+(?:\.\d*)?)\s*[%]\s*$/, getItemSizePolicy: function (item, ownerSizeModel) { var me = this, policy = me.sizePolicy, align = me.align, flex = item.flex, key = align, names = me.names, width = item[names.width], height = item[names.height], percentageRe = me._percentageRe, percentageWidth = percentageRe.test(width), isStretch = (align == 'stretch'), isStretchMax = (align == 'stretchmax'), constrain = me.constrainAlign; if (!ownerSizeModel && (isStretch || flex || percentageWidth || (constrain && !isStretchMax))) { ownerSizeModel = me.owner.getSizeModel(); } if (isStretch) { if (!percentageRe.test(height) && ownerSizeModel[names.height].shrinkWrap) { key = 'stretchmax'; } } else if (!isStretchMax) { if (percentageRe.test(height)) { key = 'stretch'; } else if (constrain && !ownerSizeModel[names.height].shrinkWrap) { key = 'stretchmax'; } else { key = ''; } } if (flex || percentageWidth) { if (!ownerSizeModel[names.width].shrinkWrap) { policy = policy.flex; } } return policy[key]; }, flexSort: function (a, b) { var maxWidthName = this.names.maxWidth, minWidthName = this.names.minWidth, infiniteValue = Infinity, aTarget = a.target, bTarget = b.target, result = 0, aMin, bMin, aMax, bMax, hasMin, hasMax; aMax = aTarget[maxWidthName] || infiniteValue; bMax = bTarget[maxWidthName] || infiniteValue; aMin = aTarget[minWidthName] || 0; bMin = bTarget[minWidthName] || 0; hasMin = isFinite(aMin) || isFinite(bMin); hasMax = isFinite(aMax) || isFinite(bMax); if (hasMin || hasMax) { if (hasMax) { result = aMax - bMax; } if (result === 0 && hasMin) { result = bMin - aMin; } } return result; }, isItemBoxParent: function (itemContext) { return true; }, isItemShrinkWrap: function (item) { return true; }, roundFlex: function(width) { return Math.ceil(width); }, beginCollapse: function(child) { var me = this; if (me.direction === 'vertical' && child.collapsedVertical()) { child.collapseMemento.capture(['flex']); delete child.flex; } else if (me.direction === 'horizontal' && child.collapsedHorizontal()) { child.collapseMemento.capture(['flex']); delete child.flex; } }, beginExpand: function(child) { child.collapseMemento.restore(['flex']); }, beginLayout: function (ownerContext) { var me = this, owner = me.owner, smp = owner.stretchMaxPartner, style = me.innerCt.dom.style, names = me.names; ownerContext.boxNames = names; me.overflowHandler.beginLayout(ownerContext); if (typeof smp === 'string') { smp = Ext.getCmp(smp) || owner.query(smp)[0]; } ownerContext.stretchMaxPartner = smp && ownerContext.context.getCmp(smp); me.callParent(arguments); ownerContext.innerCtContext = ownerContext.getEl('innerCt', me); me.scrollParallel = owner.scrollFlags[names.x]; me.scrollPerpendicular = owner.scrollFlags[names.y]; if (me.scrollParallel) { me.scrollPos = owner.getTargetEl().dom[names.scrollLeft]; } style.width = ''; style.height = ''; }, beginLayoutCycle: function (ownerContext, firstCycle) { var me = this, align = me.align, names = ownerContext.boxNames, pack = me.pack, heightModelName = names.heightModel; me.overflowHandler.beginLayoutCycle(ownerContext, firstCycle); me.callParent(arguments); ownerContext.parallelSizeModel = ownerContext[names.widthModel]; ownerContext.perpendicularSizeModel = ownerContext[heightModelName]; ownerContext.boxOptions = { align: align = { stretch: align == 'stretch', stretchmax: align == 'stretchmax', center: align == names.center, bottom: align == names.afterY }, pack: pack = { center: pack == 'center', end: pack == 'end' } }; if (align.stretch && ownerContext.perpendicularSizeModel.shrinkWrap) { align.stretchmax = true; align.stretch = false; } align.nostretch = !(align.stretch || align.stretchmax); if (ownerContext.parallelSizeModel.shrinkWrap) { pack.center = pack.end = false; } me.cacheFlexes(ownerContext); me.targetEl.setWidth(20000); }, cacheFlexes: function (ownerContext) { var me = this, names = ownerContext.boxNames, widthModelName = names.widthModel, heightModelName = names.heightModel, nostretch = ownerContext.boxOptions.align.nostretch, totalFlex = 0, childItems = ownerContext.childItems, i = childItems.length, flexedItems = [], minWidth = 0, minWidthName = names.minWidth, percentageRe = me._percentageRe, percentageWidths = 0, percentageHeights = 0, child, childContext, flex, match; while (i--) { childContext = childItems[i]; child = childContext.target; if (childContext[widthModelName].calculated) { childContext.flex = flex = child.flex; if (flex) { totalFlex += flex; flexedItems.push(childContext); minWidth += child[minWidthName] || 0; } else { match = percentageRe.exec(child[names.width]); childContext.percentageParallel = parseFloat(match[1]) / 100; ++percentageWidths; } } if (nostretch && childContext[heightModelName].calculated) { match = percentageRe.exec(child[names.height]); childContext.percentagePerpendicular = parseFloat(match[1]) / 100; ++percentageHeights; } } ownerContext.flexedItems = flexedItems; ownerContext.flexedMinSize = minWidth; ownerContext.totalFlex = totalFlex; ownerContext.percentageWidths = percentageWidths; ownerContext.percentageHeights = percentageHeights; Ext.Array.sort(flexedItems, me.flexSortFn); }, calculate: function(ownerContext) { var me = this, targetSize = me.getContainerSize(ownerContext), names = ownerContext.boxNames, state = ownerContext.state, plan = state.boxPlan || (state.boxPlan = {}), targetContext = ownerContext.targetContext; plan.targetSize = targetSize; if (!state.parallelDone) { state.parallelDone = me.calculateParallel(ownerContext, names, plan); } if (!state.perpendicularDone) { state.perpendicularDone = me.calculatePerpendicular(ownerContext, names, plan); } if (state.parallelDone && state.perpendicularDone) { if (me.owner.dock && (Ext.isIE7m || Ext.isIEQuirks) && !me.owner.width && !me.horizontal) { plan.isIEVerticalDock = true; plan.calculatedWidth = plan.maxSize + ownerContext.getPaddingInfo().width + ownerContext.getFrameInfo().width; if (targetContext !== ownerContext) { plan.calculatedWidth += targetContext.getPaddingInfo().width; } } me.publishInnerCtSize(ownerContext, me.reserveOffset ? me.availableSpaceOffset : 0); if (me.done && ownerContext.boxOptions.align.stretchmax && !state.stretchMaxDone) { me.calculateStretchMax(ownerContext, names, plan); state.stretchMaxDone = true; } me.overflowHandler.calculate(ownerContext); } else { me.done = false; } }, calculateParallel: function(ownerContext, names, plan) { var me = this, widthName = names.width, childItems = ownerContext.childItems, beforeXName = names.beforeX, afterXName = names.afterX, setWidthName = names.setWidth, childItemsLength = childItems.length, flexedItems = ownerContext.flexedItems, flexedItemsLength = flexedItems.length, pack = ownerContext.boxOptions.pack, padding = me.padding, targetSize = plan.targetSize, containerWidth = targetSize[widthName], totalMargin = 0, left = padding[beforeXName], nonFlexWidth = left + padding[afterXName] + me.scrollOffset + (me.reserveOffset ? me.availableSpaceOffset : 0), scrollbarWidth = Ext.getScrollbarSize()[names.width], i, childMargins, remainingWidth, remainingFlex, childContext, flex, flexedWidth, contentWidth, mayNeedScrollbarAdjust, childWidth, percentageSpace; if (!ownerContext.parallelSizeModel.shrinkWrap && !targetSize[names.gotWidth]) { return false; } if (scrollbarWidth && me.scrollPerpendicular && ownerContext.parallelSizeModel.shrinkWrap && !ownerContext.boxOptions.align.stretch && !ownerContext.perpendicularSizeModel.shrinkWrap) { if (!ownerContext.state.perpendicularDone) { return false; } mayNeedScrollbarAdjust = true; } for (i = 0; i < childItemsLength; ++i) { childContext = childItems[i]; childMargins = childContext.marginInfo || childContext.getMarginInfo(); totalMargin += childMargins[widthName]; if (!childContext[names.widthModel].calculated) { childWidth = childContext.getProp(widthName); nonFlexWidth += childWidth; if (isNaN(nonFlexWidth)) { return false; } } } nonFlexWidth += totalMargin; if (ownerContext.percentageWidths) { percentageSpace = containerWidth - totalMargin; if (isNaN(percentageSpace)) { return false; } for (i = 0; i < childItemsLength; ++i) { childContext = childItems[i]; if (childContext.percentageParallel) { childWidth = Math.ceil(percentageSpace * childContext.percentageParallel); childWidth = childContext.setWidth(childWidth); nonFlexWidth += childWidth; } } } if (ownerContext.parallelSizeModel.shrinkWrap) { plan.availableSpace = 0; plan.tooNarrow = false; } else { plan.availableSpace = containerWidth - nonFlexWidth; plan.tooNarrow = plan.availableSpace < ownerContext.flexedMinSize; if (plan.tooNarrow && Ext.getScrollbarSize()[names.height] && me.scrollParallel && ownerContext.state.perpendicularDone) { ownerContext.state.perpendicularDone = false; for (i = 0; i < childItemsLength; ++i) { childItems[i].invalidate(); } } } contentWidth = nonFlexWidth; remainingWidth = plan.availableSpace; remainingFlex = ownerContext.totalFlex; for (i = 0; i < flexedItemsLength; i++) { childContext = flexedItems[i]; flex = childContext.flex; flexedWidth = me.roundFlex((flex / remainingFlex) * remainingWidth); flexedWidth = childContext[setWidthName](flexedWidth); contentWidth += flexedWidth; remainingWidth = Math.max(0, remainingWidth - flexedWidth); remainingFlex -= flex; } if (pack.center) { left += remainingWidth / 2; if (left < 0) { left = 0; } } else if (pack.end) { left += remainingWidth; } for (i = 0; i < childItemsLength; ++i) { childContext = childItems[i]; childMargins = childContext.marginInfo; left += childMargins[beforeXName]; childContext.setProp(names.x, left); left += childMargins[afterXName] + childContext.props[widthName]; } contentWidth += ownerContext.targetContext.getPaddingInfo()[widthName]; ownerContext.state.contentWidth = contentWidth; if (mayNeedScrollbarAdjust && (ownerContext.peek(names.contentHeight) > plan.targetSize[names.height])) { contentWidth += scrollbarWidth; ownerContext[names.hasOverflowY] = true; ownerContext.target.componentLayout[names.setWidthInDom] = true; ownerContext[names.invalidateScrollY] = Ext.isStrict && Ext.isIE8; } ownerContext[names.setContentWidth](contentWidth); return true; }, calculatePerpendicular: function(ownerContext, names, plan) { var me = this, heightShrinkWrap = ownerContext.perpendicularSizeModel.shrinkWrap, targetSize = plan.targetSize, childItems = ownerContext.childItems, childItemsLength = childItems.length, mmax = Math.max, heightName = names.height, setHeightName = names.setHeight, beforeYName = names.beforeY, topPositionName = names.y, padding = me.padding, top = padding[beforeYName], availHeight = targetSize[heightName] - top - padding[names.afterY], align = ownerContext.boxOptions.align, isStretch = align.stretch, isStretchMax = align.stretchmax, isCenter = align.center, isBottom = align.bottom, constrain = me.constrainAlign, maxHeight = 0, hasPercentageSizes = 0, onBeforeInvalidateChild = me.onBeforeConstrainInvalidateChild, onAfterInvalidateChild = me.onAfterConstrainInvalidateChild, scrollbarHeight = Ext.getScrollbarSize().height, childTop, i, childHeight, childMargins, diff, height, childContext, stretchMaxPartner, stretchMaxChildren, shrinkWrapParallelOverflow, percentagePerpendicular; if (isStretch || ((isCenter || isBottom) && !heightShrinkWrap)) { if (isNaN(availHeight)) { return false; } } if (!isStretch && !ownerContext.parallelSizeModel.shrinkWrap && !ownerContext.state.parallelDone && me.scrollParallel) { return false; } if (me.scrollParallel && plan.tooNarrow) { if (heightShrinkWrap) { shrinkWrapParallelOverflow = true; } else { availHeight -= scrollbarHeight; plan.targetSize[heightName] -= scrollbarHeight; } } if (isStretch) { height = availHeight; } else { for (i = 0; i < childItemsLength; i++) { childContext = childItems[i]; childMargins = (childContext.marginInfo || childContext.getMarginInfo())[heightName]; if (!(percentagePerpendicular = childContext.percentagePerpendicular)) { childHeight = childContext.getProp(heightName); } else { ++hasPercentageSizes; if (heightShrinkWrap) { continue; } else { childHeight = percentagePerpendicular * availHeight - childMargins; childHeight = childContext[names.setHeight](childHeight); } } if (!heightShrinkWrap && constrain && childContext[names.heightModel].shrinkWrap && childHeight > availHeight) { childContext.invalidate({ before: onBeforeInvalidateChild, after: onAfterInvalidateChild, layout: me, childHeight: availHeight, names: names }); ownerContext.state.parallelDone = false; } if (isNaN(maxHeight = mmax(maxHeight, childHeight + childMargins, childContext.target[names.minHeight] || 0))) { return false; } } if (shrinkWrapParallelOverflow) { maxHeight += scrollbarHeight; ownerContext[names.hasOverflowX] = true; ownerContext.target.componentLayout[names.setHeightInDom] = true; ownerContext[names.invalidateScrollX] = Ext.isStrict && Ext.isIE8; } stretchMaxPartner = ownerContext.stretchMaxPartner; if (stretchMaxPartner) { ownerContext.setProp('maxChildHeight', maxHeight); stretchMaxChildren = stretchMaxPartner.childItems; if (stretchMaxChildren && stretchMaxChildren.length) { maxHeight = mmax(maxHeight, stretchMaxPartner.getProp('maxChildHeight')); if (isNaN(maxHeight)) { return false; } } } ownerContext[names.setContentHeight](maxHeight + me.padding[heightName] + ownerContext.targetContext.getPaddingInfo()[heightName]); if (shrinkWrapParallelOverflow) { maxHeight -= scrollbarHeight; } plan.maxSize = maxHeight; if (isStretchMax) { height = maxHeight; } else if (isCenter || isBottom || hasPercentageSizes) { if (constrain) { height = heightShrinkWrap ? maxHeight : availHeight; } else { height = heightShrinkWrap ? maxHeight : mmax(availHeight, maxHeight); } height -= ownerContext.innerCtContext.getBorderInfo()[heightName]; } } for (i = 0; i < childItemsLength; i++) { childContext = childItems[i]; childMargins = childContext.marginInfo || childContext.getMarginInfo(); childTop = top + childMargins[beforeYName]; if (isStretch) { childContext[setHeightName](height - childMargins[heightName]); } else { percentagePerpendicular = childContext.percentagePerpendicular; if (heightShrinkWrap && percentagePerpendicular) { childMargins = childContext.marginInfo || childContext.getMarginInfo(); childHeight = percentagePerpendicular * height - childMargins[heightName]; childHeight = childContext.setHeight(childHeight); } if (isCenter) { diff = height - childContext.props[heightName]; if (diff > 0) { childTop = top + Math[me.alignRoundingMethod](diff / 2); } } else if (isBottom) { childTop = mmax(0, height - childTop - childContext.props[heightName]); } } childContext.setProp(topPositionName, childTop); } return true; }, onBeforeConstrainInvalidateChild: function(childContext, options){ var heightModelName = options.names.heightModel; if (!childContext[heightModelName].constrainedMin) { childContext[heightModelName] = Ext.layout.SizeModel.calculated; } }, onAfterConstrainInvalidateChild: function(childContext, options){ var names = options.names; childContext.setProp(names.beforeY, 0); if (childContext[names.heightModel].calculated) { childContext[names.setHeight](options.childHeight); } }, calculateStretchMax: function (ownerContext, names, plan) { var me = this, heightName = names.height, widthName = names.width, childItems = ownerContext.childItems, length = childItems.length, height = plan.maxSize, onBeforeStretchMaxInvalidateChild = me.onBeforeStretchMaxInvalidateChild, onAfterStretchMaxInvalidateChild = me.onAfterStretchMaxInvalidateChild, childContext, props, i, childHeight; for (i = 0; i < length; ++i) { childContext = childItems[i]; props = childContext.props; childHeight = height - childContext.getMarginInfo()[heightName]; if (childHeight != props[heightName] || childContext[names.heightModel].constrained) { childContext.invalidate({ before: onBeforeStretchMaxInvalidateChild, after: onAfterStretchMaxInvalidateChild, layout: me, childWidth: props[widthName], childHeight: childHeight, childX: props.x, childY: props.y, names: names }); } } }, onBeforeStretchMaxInvalidateChild: function (childContext, options) { var heightModelName = options.names.heightModel; if (!childContext[heightModelName].constrainedMax) { childContext[heightModelName] = Ext.layout.SizeModel.calculated; } }, onAfterStretchMaxInvalidateChild: function (childContext, options) { var names = options.names, childHeight = options.childHeight, childWidth = options.childWidth; childContext.setProp('x', options.childX); childContext.setProp('y', options.childY); if (childContext[names.heightModel].calculated) { childContext[names.setHeight](childHeight); } if (childContext[names.widthModel].calculated) { childContext[names.setWidth](childWidth); } }, completeLayout: function(ownerContext) { var me = this, names = ownerContext.boxNames, invalidateScrollX = ownerContext.invalidateScrollX, invalidateScrollY = ownerContext.invalidateScrollY, dom, el, overflowX, overflowY, styles; me.overflowHandler.completeLayout(ownerContext); if (invalidateScrollX || invalidateScrollY) { el = me.getTarget(); dom = el.dom; styles = dom.style; if (invalidateScrollX) { overflowX = el.getStyle('overflowX'); if (overflowX == 'auto') { overflowX = styles.overflowX; styles.overflowX = 'scroll'; } else { invalidateScrollX = false; } } if (invalidateScrollY) { overflowY = el.getStyle('overflowY'); if (overflowY == 'auto') { overflowY = styles.overflowY; styles.overflowY = 'scroll'; } else { invalidateScrollY = false; } } if (invalidateScrollX || invalidateScrollY) { dom.scrollWidth; if (invalidateScrollX) { styles.overflowX = overflowX; } if (invalidateScrollY) { styles.overflowY = overflowY; } } } if (me.scrollParallel) { me.owner.getTargetEl().dom[names.scrollLeft] = me.scrollPos; } }, finishedLayout: function(ownerContext) { this.overflowHandler.finishedLayout(ownerContext); this.callParent(arguments); this.targetEl.setWidth(ownerContext.innerCtContext.props.width); }, publishInnerCtSize: function(ownerContext, reservedSpace) { var me = this, names = ownerContext.boxNames, heightName = names.height, widthName = names.width, align = ownerContext.boxOptions.align, dock = me.owner.dock, padding = me.padding, plan = ownerContext.state.boxPlan, targetSize = plan.targetSize, height = targetSize[heightName], innerCtContext = ownerContext.innerCtContext, innerCtWidth = (ownerContext.parallelSizeModel.shrinkWrap || (plan.tooNarrow && me.scrollParallel) ? ownerContext.state.contentWidth - ownerContext.targetContext.getPaddingInfo()[widthName] : targetSize[widthName]) - (reservedSpace || 0), innerCtHeight; if (align.stretch) { innerCtHeight = height; } else { innerCtHeight = plan.maxSize + padding[names.beforeY] + padding[names.afterY] + innerCtContext.getBorderInfo()[heightName]; if (!ownerContext.perpendicularSizeModel.shrinkWrap && (align.center || align.bottom)) { innerCtHeight = Math.max(height, innerCtHeight); } } innerCtContext[names.setWidth](innerCtWidth); innerCtContext[names.setHeight](innerCtHeight); if (isNaN(innerCtWidth + innerCtHeight)) { me.done = false; } if (plan.calculatedWidth && (dock == 'left' || dock == 'right')) { ownerContext.setWidth(plan.calculatedWidth, true, true); } }, onRemove: function(comp, isDestroying){ var me = this, names = me.names, el; me.callParent(arguments); if (me.overflowHandler) { me.overflowHandler.onRemove(comp); } if (comp.layoutMarginCap == me.id) { delete comp.layoutMarginCap; } if (!me.owner.destroying && !isDestroying && comp.rendered) { el = comp.getEl(); el.setStyle(names.beforeY, ''); el.setStyle(names.beforeX, ''); } }, initOverflowHandler: function() { var me = this, handler = me.overflowHandler, handlerType, constructor; if (typeof handler == 'string') { handler = { type: handler }; } handlerType = 'None'; if (handler && handler.type !== undefined) { handlerType = handler.type; } constructor = Ext.layout.container.boxOverflow[handlerType]; if (constructor[me.type]) { constructor = constructor[me.type]; } me.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.' + handlerType, me, handler); }, getRenderTarget: function() { return this.targetEl; }, getElementTarget: function() { return this.innerCt; }, destroy: function() { var me = this; Ext.destroy(me.innerCt, me.overflowHandler); me.flexSortFn = me.innerCt = null; me.callParent(arguments); }, getRenderData: function() { var data = this.callParent(); data.targetElCls = this.targetElCls; return data; } }); Ext.define('Ext.layout.container.HBox', { alias: ['layout.hbox'], extend: Ext.layout.container.Box , alternateClassName: 'Ext.layout.HBoxLayout', align: 'top', constrainAlign: false, type : 'hbox', direction: 'horizontal', horizontal: true, names: { beforeX: 'left', beforeScrollX: 'left', beforeScrollerSuffix: '-before-scroller', afterScrollerSuffix: '-after-scroller', leftCap: 'Left', afterX: 'right', width: 'width', contentWidth: 'contentWidth', minWidth: 'minWidth', maxWidth: 'maxWidth', widthCap: 'Width', widthModel: 'widthModel', widthIndex: 0, x: 'x', scrollLeft: 'scrollLeft', overflowX: 'overflowX', hasOverflowX: 'hasOverflowX', invalidateScrollX: 'invalidateScrollX', parallelMargins: 'lr', center: 'middle', beforeY: 'top', afterY: 'bottom', height: 'height', contentHeight: 'contentHeight', minHeight: 'minHeight', maxHeight: 'maxHeight', heightCap: 'Height', heightModel: 'heightModel', heightIndex: 1, y: 'y', overflowY: 'overflowY', hasOverflowY: 'hasOverflowY', invalidateScrollY: 'invalidateScrollY', perpendicularMargins: 'tb', getWidth: 'getWidth', getHeight: 'getHeight', setWidth: 'setWidth', setHeight: 'setHeight', gotWidth: 'gotWidth', gotHeight: 'gotHeight', setContentWidth: 'setContentWidth', setContentHeight: 'setContentHeight', setWidthInDom: 'setWidthInDom', setHeightInDom: 'setHeightInDom', getScrollLeft: 'getScrollLeft', setScrollLeft: 'setScrollLeft', scrollTo: 'scrollTo' }, sizePolicy: { flex: { '': { readsWidth : 0, readsHeight: 1, setsWidth : 1, setsHeight : 0 }, stretch: { readsWidth : 0, readsHeight: 0, setsWidth : 1, setsHeight : 1 }, stretchmax: { readsWidth : 0, readsHeight: 1, setsWidth : 1, setsHeight : 1 } }, '': { readsWidth : 1, readsHeight: 1, setsWidth : 0, setsHeight : 0 }, stretch: { readsWidth : 1, readsHeight: 0, setsWidth : 0, setsHeight : 1 }, stretchmax: { readsWidth : 1, readsHeight: 1, setsWidth : 0, setsHeight : 1 } } }); Ext.define('Ext.layout.container.VBox', { alias: ['layout.vbox'], extend: Ext.layout.container.Box , alternateClassName: 'Ext.layout.VBoxLayout', align : 'left', constrainAlign: false, type: 'vbox', direction: 'vertical', horizontal: false, names: { beforeX: 'top', beforeScrollX: 'top', beforeScrollerSuffix: '-before-scroller', afterScrollerSuffix: '-after-scroller', leftCap: 'Top', afterX: 'bottom', width: 'height', contentWidth: 'contentHeight', minWidth: 'minHeight', maxWidth: 'maxHeight', widthCap: 'Height', widthModel: 'heightModel', widthIndex: 1, x: 'y', scrollLeft: 'scrollTop', overflowX: 'overflowY', hasOverflowX: 'hasOverflowY', invalidateScrollX: 'invalidateScrollY', parallelMargins: 'tb', center: 'center', beforeY: 'left', afterY: 'right', height: 'width', contentHeight: 'contentWidth', minHeight: 'minWidth', maxHeight: 'maxWidth', heightCap: 'Width', heightModel: 'widthModel', heightIndex: 0, y: 'x', overflowY: 'overflowX', hasOverflowY: 'hasOverflowX', invalidateScrollY: 'invalidateScrollX', perpendicularMargins: 'lr', getWidth: 'getHeight', getHeight: 'getWidth', setWidth: 'setHeight', setHeight: 'setWidth', gotWidth: 'gotHeight', gotHeight: 'gotWidth', setContentWidth: 'setContentHeight', setContentHeight: 'setContentWidth', setWidthInDom: 'setHeightInDom', setHeightInDom: 'setWidthInDom', getScrollLeft: 'getScrollTop', setScrollLeft: 'setScrollTop', scrollTo: 'scrollTo' }, sizePolicy: { flex: { '': { readsWidth : 1, readsHeight: 0, setsWidth : 0, setsHeight : 1 }, stretch: { readsWidth : 0, readsHeight: 0, setsWidth : 1, setsHeight : 1 }, stretchmax: { readsWidth : 1, readsHeight: 0, setsWidth : 1, setsHeight : 1 } }, '': { readsWidth : 1, readsHeight: 1, setsWidth : 0, setsHeight : 0 }, stretch: { readsWidth : 0, readsHeight: 1, setsWidth : 1, setsHeight : 0 }, stretchmax: { readsWidth : 1, readsHeight: 1, setsWidth : 1, setsHeight : 0 } } }); Ext.define('Ext.toolbar.Toolbar', { extend: Ext.container.Container , alias: 'widget.toolbar', alternateClassName: 'Ext.Toolbar', isToolbar: true, baseCls : Ext.baseCSSPrefix + 'toolbar', ariaRole : 'toolbar', defaultType: 'button', vertical: false, enableOverflow: false, menuTriggerCls: Ext.baseCSSPrefix + 'toolbar-more-icon', trackMenus: true, itemCls: Ext.baseCSSPrefix + 'toolbar-item', statics: { shortcuts: { '-' : 'tbseparator', ' ' : 'tbspacer' }, shortcutsHV: { 0: { '->': { xtype: 'tbfill', height: 0 } }, 1: { '->': { xtype: 'tbfill', width: 0 } } } }, initComponent: function() { var me = this; if (!me.layout && me.enableOverflow) { me.layout = { overflowHandler: 'Menu' }; } if (me.dock === 'right' || me.dock === 'left') { me.vertical = true; } me.layout = Ext.applyIf(Ext.isString(me.layout) ? { type: me.layout } : me.layout || {}, { type: me.vertical ? 'vbox' : 'hbox', align: me.vertical ? 'stretchmax' : 'middle' }); if (me.vertical) { me.addClsWithUI('vertical'); } if (me.ui === 'footer') { me.ignoreBorderManagement = true; } me.callParent(); me.addEvents('overflowchange'); }, getRefItems: function(deep) { var me = this, items = me.callParent(arguments), layout = me.layout, handler; if (deep && me.enableOverflow) { handler = layout.overflowHandler; if (handler && handler.menu) { items = items.concat(handler.menu.getRefItems(deep)); } } return items; }, lookupComponent: function(c) { var args = arguments; if (typeof c == 'string') { var T = Ext.toolbar.Toolbar, shortcut = T.shortcutsHV[this.vertical ? 1 : 0][c] || T.shortcuts[c]; if (typeof shortcut == 'string') { c = { xtype: shortcut }; } else if (shortcut) { c = Ext.apply({}, shortcut); } else { c = { xtype: 'tbtext', text: c }; } this.applyDefaults(c); args = [c]; } return this.callParent(args); }, applyDefaults: function(c) { if (!Ext.isString(c)) { c = this.callParent(arguments); } return c; }, trackMenu: function(item, remove) { if (this.trackMenus && item.menu) { var method = remove ? 'mun' : 'mon', me = this; me[method](item, 'mouseover', me.onButtonOver, me); me[method](item, 'menushow', me.onButtonMenuShow, me); me[method](item, 'menuhide', me.onButtonMenuHide, me); } }, onBeforeAdd: function(component) { var me = this, isButton = component.isButton; if (isButton && me.defaultButtonUI && component.ui === 'default' && !component.hasOwnProperty('ui')) { component.ui = me.defaultButtonUI; } else if ((isButton || component.isFormField) && me.ui !== 'footer') { component.ui = component.ui + '-toolbar'; component.addCls(component.baseCls + '-toolbar'); } if (component instanceof Ext.toolbar.Separator) { component.setUI((me.vertical) ? 'vertical' : 'horizontal'); } me.callParent(arguments); }, onAdd: function(component) { this.callParent(arguments); this.trackMenu(component); }, onRemove: function(c) { this.callParent(arguments); this.trackMenu(c, true); }, getChildItemsToDisable: function() { return this.items.getRange(); }, onButtonOver: function(btn){ if (this.activeMenuBtn && this.activeMenuBtn != btn) { this.activeMenuBtn.hideMenu(); btn.showMenu(); this.activeMenuBtn = btn; } }, onButtonMenuShow: function(btn) { this.activeMenuBtn = btn; }, onButtonMenuHide: function(btn) { delete this.activeMenuBtn; } }); Ext.define('Ext.layout.component.Dock', { extend: Ext.layout.component.Component , alias: 'layout.dock', alternateClassName: 'Ext.layout.component.AbstractDock', type: 'dock', horzAxisProps: { name: 'horz', oppositeName: 'vert', dockBegin: 'left', dockEnd: 'right', horizontal: true, marginBegin: 'margin-left', maxSize: 'maxWidth', minSize: 'minWidth', pos: 'x', setSize: 'setWidth', shrinkWrapDock: 'shrinkWrapDockWidth', size: 'width', sizeModel: 'widthModel' }, vertAxisProps: { name: 'vert', oppositeName: 'horz', dockBegin: 'top', dockEnd: 'bottom', horizontal: false, marginBegin: 'margin-top', maxSize: 'maxHeight', minSize: 'minHeight', pos: 'y', setSize: 'setHeight', shrinkWrapDock: 'shrinkWrapDockHeight', size: 'height', sizeModel: 'heightModel' }, initializedBorders: -1, horizontalCollapsePolicy: { width: true, x: true }, verticalCollapsePolicy: { height: true, y: true }, finishRender: function () { var me = this, target, items; me.callParent(); target = me.getRenderTarget(); items = me.getDockedItems(); me.finishRenderItems(target, items); }, isItemBoxParent: function (itemContext) { return true; }, isItemShrinkWrap: function (item) { return true; }, noBorderClasses: [ Ext.baseCSSPrefix + 'docked-noborder-top', Ext.baseCSSPrefix + 'docked-noborder-right', Ext.baseCSSPrefix + 'docked-noborder-bottom', Ext.baseCSSPrefix + 'docked-noborder-left' ], noBorderClassesSides: { top: Ext.baseCSSPrefix + 'docked-noborder-top', right: Ext.baseCSSPrefix + 'docked-noborder-right', bottom: Ext.baseCSSPrefix + 'docked-noborder-bottom', left: Ext.baseCSSPrefix + 'docked-noborder-left' }, borderWidthProps: { top: 'border-top-width', right: 'border-right-width', bottom: 'border-bottom-width', left: 'border-left-width' }, handleItemBorders: function() { var me = this, owner = me.owner, borders, docked, lastItems = me.lastDockedItems, oldBorders = me.borders, currentGeneration = owner.dockedItems.generation, noBorderClassesSides = me.noBorderClassesSides, borderWidthProps = me.borderWidthProps, i, ln, item, dock, side, collapsed = me.collapsed; if (me.initializedBorders == currentGeneration || (owner.border && !owner.manageBodyBorders)) { return; } me.initializedBorders = currentGeneration; me.collapsed = false; me.lastDockedItems = docked = me.getLayoutItems(); me.collapsed = collapsed; borders = { top: [], right: [], bottom: [], left: [] }; for (i = 0, ln = docked.length; i < ln; i++) { item = docked[i]; dock = item.dock; if (item.ignoreBorderManagement) { continue; } if (!borders[dock].satisfied) { borders[dock].push(item); borders[dock].satisfied = true; } if (!borders.top.satisfied && dock !== 'bottom') { borders.top.push(item); } if (!borders.right.satisfied && dock !== 'left') { borders.right.push(item); } if (!borders.bottom.satisfied && dock !== 'top') { borders.bottom.push(item); } if (!borders.left.satisfied && dock !== 'right') { borders.left.push(item); } } if (lastItems) { for (i = 0, ln = lastItems.length; i < ln; i++) { item = lastItems[i]; if (!item.isDestroyed && !item.ignoreBorderManagement && !owner.manageBodyBorders) { item.removeCls(me.noBorderClasses); } } } if (oldBorders) { for (side in oldBorders) { if (owner.manageBodyBorders && oldBorders[side].satisfied) { owner.setBodyStyle(borderWidthProps[side], ''); } } } for (side in borders) { ln = borders[side].length; if (!owner.manageBodyBorders) { for (i = 0; i < ln; i++) { borders[side][i].addCls(noBorderClassesSides[side]); } if ((!borders[side].satisfied && !owner.bodyBorder) || owner.bodyBorder === false) { owner.addBodyCls(noBorderClassesSides[side]); } } else if (borders[side].satisfied) { owner.setBodyStyle(borderWidthProps[side], '1px'); } } me.borders = borders; }, beforeLayoutCycle: function (ownerContext) { var me = this, owner = me.owner, shrinkWrap = me.sizeModels.shrinkWrap, shrinkWrapDock = owner.shrinkWrapDock, collapsedHorz, collapsedVert; if (owner.collapsed) { if (owner.collapsedVertical()) { collapsedVert = true; ownerContext.measureDimensions = 1; } else { collapsedHorz = true; ownerContext.measureDimensions = 2; } } ownerContext.collapsedVert = collapsedVert; ownerContext.collapsedHorz = collapsedHorz; if (collapsedVert) { ownerContext.heightModel = shrinkWrap; } else if (collapsedHorz) { ownerContext.widthModel = shrinkWrap; } shrinkWrapDock = shrinkWrapDock === true ? 3 : (shrinkWrapDock || 0); ownerContext.shrinkWrapDockHeight = (shrinkWrapDock & 1) && ownerContext.heightModel.shrinkWrap; ownerContext.shrinkWrapDockWidth = (shrinkWrapDock & 2) && ownerContext.widthModel.shrinkWrap; }, beginLayout: function(ownerContext) { var me = this, owner = me.owner, docked = me.getLayoutItems(), layoutContext = ownerContext.context, dockedItemCount = docked.length, dockedItems, i, item, itemContext, offsets, collapsed, dock; me.callParent(arguments); collapsed = owner.getCollapsed(); if (collapsed !== me.lastCollapsedState && Ext.isDefined(me.lastCollapsedState)) { if (me.owner.collapsed) { ownerContext.isCollapsingOrExpanding = 1; owner.addClsWithUI(owner.collapsedCls); } else { ownerContext.isCollapsingOrExpanding = 2; owner.removeClsWithUI(owner.collapsedCls); ownerContext.lastCollapsedState = me.lastCollapsedState; } } me.lastCollapsedState = collapsed; ownerContext.dockedItems = dockedItems = []; for (i = 0; i < dockedItemCount; i++) { item = docked[i]; if (item.rendered) { dock = item.dock; itemContext = layoutContext.getCmp(item); itemContext.dockedAt = { x: 0, y: 0 }; itemContext.offsets = offsets = Ext.Element.parseBox(item.offsets || 0); itemContext.horizontal = dock == 'top' || dock == 'bottom'; offsets.width = offsets.left + offsets.right; offsets.height = offsets.top + offsets.bottom; dockedItems.push(itemContext); } } ownerContext.bodyContext = ownerContext.getEl('body'); }, beginLayoutCycle: function(ownerContext) { var me = this, docked = ownerContext.dockedItems, len = docked.length, owner = me.owner, frameBody = owner.frameBody, lastHeightModel = me.lastHeightModel, i, item, dock; me.callParent(arguments); if (me.owner.manageHeight) { if (me.lastBodyDisplay) { owner.body.dom.style.display = me.lastBodyDisplay = ''; } } else { if (me.lastBodyDisplay !== 'inline-block') { owner.body.dom.style.display = me.lastBodyDisplay = 'inline-block'; } if (lastHeightModel && lastHeightModel.shrinkWrap && !ownerContext.heightModel.shrinkWrap) { owner.body.dom.style.marginBottom = ''; } } if (ownerContext.widthModel.auto) { if (ownerContext.widthModel.shrinkWrap) { owner.el.setWidth(null); } owner.body.setWidth(null); if (frameBody) { frameBody.setWidth(null); } } if (ownerContext.heightModel.auto) { owner.body.setHeight(null); if (frameBody) { frameBody.setHeight(null); } } if (ownerContext.collapsedVert) { ownerContext.setContentHeight(0); } else if (ownerContext.collapsedHorz) { ownerContext.setContentWidth(0); } for (i = 0; i < len; i++) { item = docked[i].target; dock = item.dock; if (dock == 'right') { item.setLocalX(0); } else if (dock != 'left') { continue; } } }, calculate: function (ownerContext) { var me = this, measure = me.measureAutoDimensions(ownerContext, ownerContext.measureDimensions), state = ownerContext.state, horzDone = state.horzDone, vertDone = state.vertDone, bodyContext = ownerContext.bodyContext, framing, horz, vert, forward, backward; ownerContext.borderInfo || ownerContext.getBorderInfo(); ownerContext.paddingInfo || ownerContext.getPaddingInfo(); ownerContext.frameInfo || ownerContext.getFrameInfo(); bodyContext.borderInfo || bodyContext.getBorderInfo(); bodyContext.paddingInfo || bodyContext.getPaddingInfo(); if (!ownerContext.frameBorder) { if (!(framing = ownerContext.framing)) { ownerContext.frameBorder = ownerContext.borderInfo; ownerContext.framePadding = ownerContext.paddingInfo; } else { ownerContext.frameBorder = framing.border; ownerContext.framePadding = framing.padding; } } horz = !horzDone && me.createAxis(ownerContext, measure.contentWidth, ownerContext.widthModel, me.horzAxisProps, ownerContext.collapsedHorz); vert = !vertDone && me.createAxis(ownerContext, measure.contentHeight, ownerContext.heightModel, me.vertAxisProps, ownerContext.collapsedVert); for (forward = 0, backward = ownerContext.dockedItems.length; backward--; ++forward) { if (horz) { me.dockChild(ownerContext, horz, backward, forward); } if (vert) { me.dockChild(ownerContext, vert, backward, forward); } } if (horz && me.finishAxis(ownerContext, horz)) { state.horzDone = horzDone = horz; } if (vert && me.finishAxis(ownerContext, vert)) { state.vertDone = vertDone = vert; } if (horzDone && vertDone && me.finishConstraints(ownerContext, horzDone, vertDone)) { me.finishPositions(ownerContext, horzDone, vertDone); } else { me.done = false; } }, createAxis: function (ownerContext, contentSize, sizeModel, axisProps, collapsedAxis) { var me = this, begin = 0, owner = me.owner, maxSize = owner[axisProps.maxSize], minSize = owner[axisProps.minSize] || 0, dockBegin = axisProps.dockBegin, dockEnd = axisProps.dockEnd, posProp = axisProps.pos, sizeProp = axisProps.size, hasMaxSize = maxSize != null, shrinkWrap = sizeModel.shrinkWrap, bodyContext, framing, padding, end; if (shrinkWrap) { if (collapsedAxis) { end = 0; } else { bodyContext = ownerContext.bodyContext; end = contentSize + bodyContext.borderInfo[sizeProp]; } } else { framing = ownerContext.frameBorder; padding = ownerContext.framePadding; begin = framing[dockBegin] + padding[dockBegin]; end = ownerContext.getProp(sizeProp) - (framing[dockEnd] + padding[dockEnd]); } return { shrinkWrap: sizeModel.shrinkWrap, sizeModel: sizeModel, initialBegin: begin, begin: begin, end: end, collapsed: collapsedAxis, horizontal: axisProps.horizontal, ignoreFrameBegin: null, ignoreFrameEnd: null, initialSize: end - begin, maxChildSize: 0, hasMinMaxConstraints: (minSize || hasMaxSize) && sizeModel.shrinkWrap, minSize: minSize, maxSize: hasMaxSize ? maxSize : 1e9, bodyPosProp: me.owner.manageHeight ? posProp : axisProps.marginBegin, dockBegin: dockBegin, dockEnd: dockEnd, posProp: posProp, sizeProp: sizeProp, setSize: axisProps.setSize, shrinkWrapDock: ownerContext[axisProps.shrinkWrapDock], sizeModelName: axisProps.sizeModel, dockedPixelsEnd: 0 }; }, dockChild: function (ownerContext, axis, backward, forward) { var me = this, itemContext = ownerContext.dockedItems[axis.shrinkWrap ? backward : forward], item = itemContext.target, dock = item.dock, sizeProp = axis.sizeProp, pos, size; if (item.ignoreParentFrame && ownerContext.isCollapsingOrExpanding) { itemContext.clearMarginCache(); } itemContext.marginInfo || itemContext.getMarginInfo(); if (dock == axis.dockBegin) { if (axis.shrinkWrap) { pos = me.dockOutwardBegin(ownerContext, itemContext, item, axis); } else { pos = me.dockInwardBegin(ownerContext, itemContext, item, axis); } } else if (dock == axis.dockEnd) { if (axis.shrinkWrap) { pos = me.dockOutwardEnd(ownerContext, itemContext, item, axis); } else { pos = me.dockInwardEnd(ownerContext, itemContext, item, axis); } } else { if (axis.shrinkWrapDock) { size = itemContext.getProp(sizeProp) + itemContext.marginInfo[sizeProp]; axis.maxChildSize = Math.max(axis.maxChildSize, size); pos = 0; } else { pos = me.dockStretch(ownerContext, itemContext, item, axis); } } itemContext.dockedAt[axis.posProp] = pos; }, dockInwardBegin: function (ownerContext, itemContext, item, axis) { var pos = axis.begin, sizeProp = axis.sizeProp, ignoreParentFrame = item.ignoreParentFrame, delta, size, dock; if (ignoreParentFrame) { axis.ignoreFrameBegin = itemContext; dock = item.dock; delta = ownerContext.frameBorder[dock]; pos -= delta + ownerContext.framePadding[dock]; } if (!item.overlay) { size = itemContext.getProp(sizeProp) + itemContext.marginInfo[sizeProp]; axis.begin += size; if (ignoreParentFrame) { axis.begin -= delta; } } return pos; }, dockInwardEnd: function (ownerContext, itemContext, item, axis) { var sizeProp = axis.sizeProp, size = itemContext.getProp(sizeProp) + itemContext.marginInfo[sizeProp], pos = axis.end - size, frameEnd; if (!item.overlay) { axis.end = pos; } if (item.ignoreParentFrame) { axis.ignoreFrameEnd = itemContext; frameEnd = ownerContext.frameBorder[item.dock]; pos += frameEnd + ownerContext.framePadding[item.dock]; axis.end += frameEnd; } return pos; }, dockOutwardBegin: function (ownerContext, itemContext, item, axis) { var pos = axis.begin, sizeProp = axis.sizeProp, size; if (axis.collapsed) { axis.ignoreFrameBegin = axis.ignoreFrameEnd = itemContext; } else if (item.ignoreParentFrame) { axis.ignoreFrameBegin = itemContext; } if (!item.overlay) { size = itemContext.getProp(sizeProp) + itemContext.marginInfo[sizeProp]; pos -= size; axis.begin = pos; } return pos; }, dockOutwardEnd: function (ownerContext, itemContext, item, axis) { var pos = axis.end, sizeProp = axis.sizeProp, size; size = itemContext.getProp(sizeProp) + itemContext.marginInfo[sizeProp]; if (axis.collapsed) { axis.ignoreFrameBegin = axis.ignoreFrameEnd = itemContext; } else if (item.ignoreParentFrame) { axis.ignoreFrameEnd = itemContext; } if (!item.overlay) { axis.end = pos + size; axis.dockedPixelsEnd += size; } return pos; }, dockStretch: function (ownerContext, itemContext, item, axis) { var dock = item.dock, sizeProp = axis.sizeProp, horizontal = dock == 'top' || dock == 'bottom', border = ownerContext.frameBorder, offsets = itemContext.offsets, padding = ownerContext.framePadding, endProp = horizontal ? 'right' : 'bottom', startProp = horizontal ? 'left' : 'top', pos = axis.begin + offsets[startProp], margin, size; if (item.stretch !== false) { size = axis.end - pos - offsets[endProp]; if (item.ignoreParentFrame) { pos -= padding[startProp] + border[startProp]; size += padding[sizeProp] + border[sizeProp]; } margin = itemContext.marginInfo; size -= margin[sizeProp]; itemContext[axis.setSize](size); } return pos; }, finishAxis: function (ownerContext, axis) { if (isNaN(axis.maxChildSize)) { return false; } var axisBegin = axis.begin, size = axis.end - axisBegin, collapsed = axis.collapsed, setSizeMethod = axis.setSize, beginName = axis.dockBegin, endName = axis.dockEnd, padding = ownerContext.framePadding, border = ownerContext.frameBorder, borderBegin = border[beginName], framing = ownerContext.framing, framingBegin = framing && framing[beginName], paddingBegin = collapsed ? 0 : padding[beginName], sizeProp = axis.sizeProp, ignoreFrameBegin = axis.ignoreFrameBegin, ignoreFrameEnd = axis.ignoreFrameEnd, bodyContext = ownerContext.bodyContext, extraPaddingBegin = Math.max(borderBegin + paddingBegin - framingBegin, 0), bodyPos, bodySize, delta, dirty; if (axis.shrinkWrap) { bodySize = axis.initialSize; if (framing) { delta = -axisBegin + borderBegin + paddingBegin; bodyPos = delta - framingBegin - extraPaddingBegin; } else { bodyPos = -axisBegin; delta = bodyPos + paddingBegin; } if (!collapsed) { size += padding[sizeProp]; } if (ignoreFrameBegin) { delta -= borderBegin; bodyPos -= borderBegin; ignoreFrameBegin.dockedAt[axis.posProp] -= paddingBegin; } else { size += borderBegin; } if (collapsed) { } else if (ignoreFrameEnd) { ignoreFrameEnd.dockedAt[axis.posProp] += padding[endName]; } else { size += border[endName]; } axis.size = size; if (!axis.horizontal && !this.owner.manageHeight) { dirty = false; } } else { if (framing) { delta = 0; bodyPos = axisBegin - framingBegin - extraPaddingBegin; } else { delta = -borderBegin; bodyPos = axisBegin - paddingBegin - borderBegin; } bodySize = size; } axis.delta = delta; bodyContext[setSizeMethod](bodySize, dirty); bodyContext.setProp(axis.bodyPosProp, bodyPos); return !isNaN(size); }, beforeInvalidateShrinkWrapDock: function(itemContext, options){ var sizeModelName = options.axis.sizeModelName; if (!itemContext[sizeModelName].constrainedMin) { itemContext[sizeModelName] = Ext.layout.SizeModel.calculated; } }, afterInvalidateShrinkWrapDock: function(itemContext, options){ var axis = options.axis, me = options.layout, pos; if (itemContext[axis.sizeModelName].calculated) { pos = me.dockStretch(options.ownerContext, itemContext, itemContext.target, axis); itemContext.setProp(axis.posProp, axis.delta + pos); } }, finishConstraints: function (ownerContext, horz, vert) { var me = this, sizeModels = me.sizeModels, publishWidth = horz.shrinkWrap, publishHeight = vert.shrinkWrap, owner = me.owner, dirty, height, width, heightModel, widthModel, size, minSize, maxSize, maxChildSize, desiredSize; if (publishWidth) { size = horz.size; minSize = horz.collapsed ? 0 : horz.minSize; maxSize = horz.maxSize; maxChildSize = horz.maxChildSize; desiredSize = Math.max(size, maxChildSize); if (desiredSize > maxSize) { widthModel = sizeModels.constrainedMax; width = maxSize; } else if (desiredSize < minSize) { widthModel = sizeModels.constrainedMin; width = minSize; } else if (size < maxChildSize) { widthModel = sizeModels.constrainedDock; owner.dockConstrainedWidth = width = maxChildSize; } else { width = size; } } if (publishHeight) { size = vert.size; minSize = vert.collapsed ? 0 : vert.minSize; maxSize = vert.maxSize; maxChildSize = vert.maxChildSize; desiredSize = Math.max(size, maxChildSize + size - vert.initialSize); if (desiredSize > maxSize) { heightModel = sizeModels.constrainedMax; height = maxSize; } else if (desiredSize < minSize) { heightModel = sizeModels.constrainedMin; height = minSize; } else if (size < maxChildSize) { heightModel = sizeModels.constrainedDock; owner.dockConstrainedHeight = height = maxChildSize; } else { if (!ownerContext.collapsedVert && !owner.manageHeight) { dirty = false; ownerContext.bodyContext.setProp('margin-bottom', vert.dockedPixelsEnd); } height = size; } } if (widthModel || heightModel) { if (widthModel && heightModel && widthModel.constrainedMax && heightModel.constrainedByMin) { ownerContext.invalidate({ widthModel: widthModel }); return false; } if (!ownerContext.widthModel.calculatedFromShrinkWrap && !ownerContext.heightModel.calculatedFromShrinkWrap) { ownerContext.invalidate({ widthModel: widthModel, heightModel: heightModel }); return false; } } else { me.invalidateAxes(ownerContext, horz, vert); } if (publishWidth) { ownerContext.setWidth(width); if (widthModel) { ownerContext.widthModel = widthModel; } } if (publishHeight) { ownerContext.setHeight(height, dirty); if (heightModel) { ownerContext.heightModel = heightModel; } } return true; }, invalidateAxes: function(ownerContext, horz, vert){ var before = this.beforeInvalidateShrinkWrapDock, after = this.afterInvalidateShrinkWrapDock, horzSize = horz.end - horz.begin, vertSize = vert.initialSize, invalidateHorz = horz.shrinkWrapDock && horz.maxChildSize <= horzSize, invalidateVert = vert.shrinkWrapDock && vert.maxChildSize <= vertSize, dockedItems, len, i, itemContext, itemSize, isHorz, axis, sizeProp; if (invalidateHorz || invalidateVert) { if (invalidateVert) { vert.begin = vert.initialBegin; vert.end = vert.begin + vert.initialSize; } dockedItems = ownerContext.dockedItems; for (i = 0, len = dockedItems.length; i < len; ++i) { itemContext = dockedItems[i]; isHorz = itemContext.horizontal; axis = null; if (invalidateHorz && isHorz) { sizeProp = horz.sizeProp; itemSize = horzSize; axis = horz; } else if (invalidateVert && !isHorz) { sizeProp = vert.sizeProp; itemSize = vertSize; axis = vert; } if (axis) { itemSize -= itemContext.getMarginInfo()[sizeProp]; if (itemSize !== itemContext.props[sizeProp]) { itemContext.invalidate({ before: before, after: after, axis: axis, ownerContext: ownerContext, layout: this }); } } } } }, finishPositions: function (ownerContext, horz, vert) { var dockedItems = ownerContext.dockedItems, length = dockedItems.length, deltaX = horz.delta, deltaY = vert.delta, index, itemContext; for (index = 0; index < length; ++index) { itemContext = dockedItems[index]; itemContext.setProp('x', deltaX + itemContext.dockedAt.x); itemContext.setProp('y', deltaY + itemContext.dockedAt.y); } }, finishedLayout: function(ownerContext) { var me = this, target = ownerContext.target; me.callParent(arguments); if (!ownerContext.animatePolicy) { if (ownerContext.isCollapsingOrExpanding === 1) { target.afterCollapse(false); } else if (ownerContext.isCollapsingOrExpanding === 2) { target.afterExpand(false); } } }, getAnimatePolicy: function(ownerContext) { var me = this, lastCollapsedState, policy; if (ownerContext.isCollapsingOrExpanding == 1) { lastCollapsedState = me.lastCollapsedState; } else if (ownerContext.isCollapsingOrExpanding == 2) { lastCollapsedState = ownerContext.lastCollapsedState; } if (lastCollapsedState == 'left' || lastCollapsedState == 'right') { policy = me.horizontalCollapsePolicy; } else if (lastCollapsedState == 'top' || lastCollapsedState == 'bottom') { policy = me.verticalCollapsePolicy; } return policy; }, getDockedItems: function(order, beforeBody) { var me = this, renderedOnly = (order === 'visual'), all = renderedOnly ? Ext.ComponentQuery.query('[rendered]', me.owner.dockedItems.items) : me.owner.dockedItems.items, sort = all && all.length && order !== false, renderOrder, dock, dockedItems, i, isBefore, length; if (beforeBody == null) { dockedItems = sort && !renderedOnly ? all.slice() : all; } else { dockedItems = []; for (i = 0, length = all.length; i < length; ++i) { dock = all[i].dock; isBefore = (dock == 'top' || dock == 'left'); if (beforeBody ? isBefore : !isBefore) { dockedItems.push(all[i]); } } sort = sort && dockedItems.length; } if (sort) { renderOrder = (order = order || 'render') == 'render'; Ext.Array.sort(dockedItems, function(a, b) { var aw, bw; if (renderOrder && ((aw = me.owner.dockOrder[a.dock]) !== (bw = me.owner.dockOrder[b.dock]))) { if (!(aw + bw)) { return aw - bw; } } aw = me.getItemWeight(a, order); bw = me.getItemWeight(b, order); if ((aw !== undefined) && (bw !== undefined)) { return aw - bw; } return 0; }); } return dockedItems || []; }, getItemWeight: function (item, order) { var weight = item.weight || this.owner.defaultDockWeights[item.dock]; return weight[order] || weight; }, getLayoutItems : function() { var me = this, items, itemCount, item, i, result; if (me.owner.collapsed) { result = me.owner.getCollapsedDockedItems(); } else { items = me.getDockedItems('visual'); itemCount = items.length; result = []; for (i = 0; i < itemCount; i++) { item = items[i]; if (!item.hidden) { result.push(item); } } } return result; }, measureContentWidth: function (ownerContext) { var bodyContext = ownerContext.bodyContext; return bodyContext.el.getWidth() - bodyContext.getBorderInfo().width; }, measureContentHeight: function (ownerContext) { var bodyContext = ownerContext.bodyContext; return bodyContext.el.getHeight() - bodyContext.getBorderInfo().height; }, redoLayout: function(ownerContext) { var me = this, owner = me.owner; if (ownerContext.isCollapsingOrExpanding == 1) { if (owner.reExpander) { owner.reExpander.el.show(); } owner.addClsWithUI(owner.collapsedCls); ownerContext.redo(true); } else if (ownerContext.isCollapsingOrExpanding == 2) { owner.removeClsWithUI(owner.collapsedCls); ownerContext.bodyContext.redo(); } }, renderChildren: function() { var me = this, items = me.getDockedItems(), target = me.getRenderTarget(); me.handleItemBorders(); me.renderItems(items, target); }, renderItems: function(items, target) { var me = this, dockedItemCount = items.length, itemIndex = 0, correctPosition = 0, staticNodeCount = 0, targetNodes = me.getRenderTarget().dom.childNodes, targetChildCount = targetNodes.length, i, j, targetChildNode, item; for (i = 0, j = 0; i < targetChildCount; i++) { targetChildNode = targetNodes[i]; if (Ext.fly(targetChildNode).hasCls(Ext.baseCSSPrefix + 'resizable-handle')) { break; } for (j = 0; j < dockedItemCount; j++) { item = items[j]; if (item.rendered && item.el.dom === targetChildNode) { break; } } if (j === dockedItemCount) { staticNodeCount++; } } for (; itemIndex < dockedItemCount; itemIndex++, correctPosition++) { item = items[itemIndex]; if (itemIndex === correctPosition && (item.dock === 'right' || item.dock === 'bottom')) { correctPosition += staticNodeCount; } if (item && !item.rendered) { me.renderItem(item, target, correctPosition); } else if (!me.isValidParent(item, target, correctPosition)) { me.moveItem(item, target, correctPosition); } } }, undoLayout: function(ownerContext) { var me = this, owner = me.owner; if (ownerContext.isCollapsingOrExpanding == 1) { if (owner.reExpander) { owner.reExpander.el.hide(); } owner.removeClsWithUI(owner.collapsedCls); ownerContext.undo(true); } else if (ownerContext.isCollapsingOrExpanding == 2) { owner.addClsWithUI(owner.collapsedCls); ownerContext.bodyContext.undo(); } }, sizePolicy: { nostretch: { setsWidth: 0, setsHeight: 0 }, horz: { shrinkWrap: { setsWidth: 1, setsHeight: 0, readsWidth: 1 }, stretch: { setsWidth: 1, setsHeight: 0 } }, vert: { shrinkWrap: { setsWidth: 0, setsHeight: 1, readsHeight: 1 }, stretch: { setsWidth: 0, setsHeight: 1 } }, stretchV: { setsWidth: 0, setsHeight: 1 }, autoStretchH: { readsWidth: 1, setsWidth: 1, setsHeight: 0 }, autoStretchV: { readsHeight: 1, setsWidth: 0, setsHeight: 1 } }, getItemSizePolicy: function (item, ownerSizeModel) { var me = this, policy = me.sizePolicy, shrinkWrapDock = me.owner.shrinkWrapDock, dock, vertical; if (item.stretch === false) { return policy.nostretch; } dock = item.dock; vertical = (dock == 'left' || dock == 'right'); shrinkWrapDock = shrinkWrapDock === true ? 3 : (shrinkWrapDock || 0); if (vertical) { policy = policy.vert; shrinkWrapDock = shrinkWrapDock & 1; } else { policy = policy.horz; shrinkWrapDock = shrinkWrapDock & 2; } if (shrinkWrapDock) { if (!ownerSizeModel) { ownerSizeModel = me.owner.getSizeModel(); } if (ownerSizeModel[vertical ? 'height' : 'width'].shrinkWrap) { return policy.shrinkWrap; } } return policy.stretch; }, configureItem : function(item, pos) { this.callParent(arguments); item.addCls(Ext.baseCSSPrefix + 'docked'); item.addClsWithUI(this.getDockCls(item.dock)); }, getDockCls: function(dock) { return 'docked-' + dock; }, afterRemove : function(item) { this.callParent(arguments); if (this.itemCls) { item.el.removeCls(this.itemCls + '-' + item.dock); } var dom = item.el.dom; if (!item.destroying && dom) { dom.parentNode.removeChild(dom); } this.childrenChanged = true; }, borderCollapseMap: { }, getBorderCollapseTable: function () { var me = this, map = me.borderCollapseMap, owner = me.owner, baseCls = owner.baseCls, ui = owner.ui, table; map = map[baseCls] || (map[baseCls] = {}); table = map[ui]; if (!table) { baseCls += '-' + ui + '-outer-border-'; map[ui] = table = [ 0, baseCls + 'l', baseCls + 'b', baseCls + 'bl', baseCls + 'r', baseCls + 'rl', baseCls + 'rb', baseCls + 'rbl', baseCls + 't', baseCls + 'tl', baseCls + 'tb', baseCls + 'tbl', baseCls + 'tr', baseCls + 'trl', baseCls + 'trb', baseCls + 'trbl' ]; } return table; } }); Ext.define('Ext.panel.AbstractPanel', { extend: Ext.container.Container , mixins: { docking: Ext.container.DockingContainer }, baseCls : Ext.baseCSSPrefix + 'panel', isPanel: true, contentPaddingProperty: 'bodyPadding', shrinkWrapDock: false, componentLayout: 'dock', childEls: [ 'body' ], renderTpl: [ '{% this.renderDockedItems(out,values,0); %}', (Ext.isIE7m || Ext.isIEQuirks) ? '
 
' : '', '
{bodyCls}', ' {baseCls}-body-{ui}', ' {parent.baseCls}-body-{parent.ui}-{.}', '{childElCls}"', ' role="{bodyRole}" role="presentation"', ' style="{bodyStyle}">', '{%this.renderContainer(out,values);%}', '
', '{% this.renderDockedItems(out,values,1); %}' ], bodyPosProps: { x: 'x', y: 'y' }, border: true, emptyArray: [], initComponent : function() { this.initBorderProps(); this.callParent(); }, initBorderProps: function() { var me = this; if (me.frame && me.border && me.bodyBorder === undefined) { me.bodyBorder = false; } if (me.frame && me.border && (me.bodyBorder === false || me.bodyBorder === 0)) { me.manageBodyBorders = true; } }, beforeDestroy: function(){ this.destroyDockedItems(); this.callParent(); }, initItems : function() { this.callParent(); this.initDockingItems(); }, initRenderData: function() { var me = this, data = me.callParent(); me.initBodyStyles(); me.protoBody.writeTo(data); delete me.protoBody; return data; }, getComponent: function(comp) { var component = this.callParent(arguments); if (component === undefined && !Ext.isNumber(comp)) { component = this.getDockedComponent(comp); } return component; }, getProtoBody: function () { var me = this, body = me.protoBody; if (!body) { me.protoBody = body = new Ext.util.ProtoElement({ cls: me.bodyCls, style: me.bodyStyle, clsProp: 'bodyCls', styleProp: 'bodyStyle', styleIsText: true }); } return body; }, initBodyStyles: function() { var me = this, body = me.getProtoBody(); if (me.bodyPadding !== undefined) { if (me.layout.managePadding) { body.setStyle('padding', 0); } else { body.setStyle('padding', this.unitizeBox((me.bodyPadding === true) ? 5 : me.bodyPadding)); } } me.initBodyBorder(); }, initBodyBorder: function() { var me = this; if (me.frame && me.bodyBorder) { if (!Ext.isNumber(me.bodyBorder)) { me.bodyBorder = 1; } me.getProtoBody().setStyle('border-width', this.unitizeBox(me.bodyBorder)); } }, getCollapsedDockedItems: function () { var me = this; return me.header === false || me.collapseMode == 'placeholder' ? me.emptyArray : [ me.getReExpander() ]; }, setBodyStyle: function(style, value) { var me = this, body = me.rendered ? me.body : me.getProtoBody(); if (Ext.isFunction(style)) { style = style(); } if (arguments.length == 1) { if (Ext.isString(style)) { style = Ext.Element.parseStyles(style); } body.setStyle(style); } else { body.setStyle(style, value); } return me; }, addBodyCls: function(cls) { var me = this, body = me.rendered ? me.body : me.getProtoBody(); body.addCls(cls); return me; }, removeBodyCls: function(cls) { var me = this, body = me.rendered ? me.body : me.getProtoBody(); body.removeCls(cls); return me; }, addUIClsToElement: function(cls) { var me = this, result = me.callParent(arguments); me.addBodyCls([Ext.baseCSSPrefix + cls, me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls]); return result; }, removeUIClsFromElement: function(cls) { var me = this, result = me.callParent(arguments); me.removeBodyCls([Ext.baseCSSPrefix + cls, me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls]); return result; }, addUIToElement: function() { var me = this; me.callParent(arguments); me.addBodyCls(me.baseCls + '-body-' + me.ui); }, removeUIFromElement: function() { var me = this; me.callParent(arguments); me.removeBodyCls(me.baseCls + '-body-' + me.ui); }, getTargetEl : function() { return this.body; }, applyTargetCls: function(targetCls) { this.getProtoBody().addCls(targetCls); }, getRefItems: function(deep) { var items = this.callParent(arguments); return this.getDockingRefItems(deep, items); }, setupRenderTpl: function (renderTpl) { this.callParent(arguments); this.setupDockingRenderTpl(renderTpl); } }); Ext.define('Ext.panel.Header', { extend: Ext.container.Container , alias: 'widget.header', isHeader : true, defaultType : 'tool', indicateDrag : false, weight : -1, componentLayout: 'body', childEls: [ 'body' ], renderTpl: [ '
{parent.baseCls}-body-{parent.ui}-{.}"', ' style="{bodyStyle}" role="presentation">', '{%this.renderContainer(out,values)%}', '
' ], headingTpl: [ '', ' role="{headerRole}"', '
', '>{title}' ], shrinkWrap: 3, titlePosition: 0, headerCls: Ext.baseCSSPrefix + 'header', initComponent: function() { var me = this, hasPosition = me.hasOwnProperty('titlePosition'), items = me.items, titlePosition = hasPosition ? me.titlePosition : (items ? items.length : 0), uiClasses = [me.orientation, me.getDockName()], ownerCt = me.ownerCt; me.addEvents( 'click', 'dblclick' ); me.indicateDragCls = me.headerCls + '-draggable'; me.title = me.title || ' '; me.tools = me.tools || []; items = me.items = (items ? Ext.Array.slice(items) : []); me.orientation = me.orientation || 'horizontal'; me.dock = (me.dock) ? me.dock : (me.orientation == 'horizontal') ? 'top' : 'left'; if (ownerCt ? (ownerCt.border === false && !ownerCt.frame) : me.border === false) { uiClasses.push(me.orientation + '-noborder'); } me.addClsWithUI(uiClasses); me.addCls([me.headerCls, me.headerCls + '-' + me.orientation]); if (me.indicateDrag) { me.addCls(me.indicateDragCls); } if (me.iconCls || me.icon || me.glyph) { me.initIconCmp(); if (!hasPosition && !items.length) { ++titlePosition; } items.push(me.iconCmp); } me.titleCmp = new Ext.Component({ ariaRole : 'presentation', focusable : false, noWrap : true, flex : 1, rtl : me.rtl, id : me.id + '_hd', style : me.titleAlign ? ('text-align:' + me.titleAlign) : '', cls : me.headerCls + '-text-container ' + me.baseCls + '-text-container ' + me.baseCls + '-text-container-' + me.ui, renderTpl : me.getTpl('headingTpl'), renderData: { title: me.title, cls : me.baseCls, headerCls: me.headerCls, headerRole: me.headerRole, ui : me.ui }, childEls : ['textEl'], autoEl: { unselectable: 'on' }, listeners: { render: me.onTitleRender, scope: me } }); me.layout = (me.orientation == 'vertical') ? { type : 'vbox', align: 'center', alignRoundingMethod: 'ceil' } : { type : 'hbox', align: 'middle', alignRoundingMethod: 'floor' }; Ext.Array.push(items, me.tools); me.tools.length = 0; me.callParent(); if (items.length < titlePosition) { titlePosition = items.length; } me.titlePosition = titlePosition; me.insert(titlePosition, me.titleCmp); me.on({ dblclick: me.onDblClick, click: me.onClick, element: 'el', scope: me }); }, setTitlePosition: function(index) { var me = this; me.titlePosition = index = Math.min(index, me.items.length - 1); me.insert(index, me.titleCmp); }, initIconCmp: function() { var me = this, cls = [me.headerCls + '-icon', me.baseCls + '-icon', me.iconCls], cfg; if (me.glyph) { cls.push(me.baseCls + '-glyph'); } cfg = { focusable: false, src: Ext.BLANK_IMAGE_URL, cls: cls, baseCls: me.baseCls + '-icon', id: me.id + '-iconEl', iconCls: me.iconCls, glyph: me.glyph }; if (!Ext.isEmpty(me.icon)) { delete cfg.iconCls; cfg.src = me.icon; } me.iconCmp = new Ext.Img(cfg); }, beforeRender: function() { this.protoEl.unselectable(); this.callParent(); }, afterLayout: function() { var me = this, frameBR, frameTR, frameTL, xPos; if (me.orientation === 'vertical') { me.adjustTitlePosition(); frameTR = me.frameTR; if (frameTR) { frameBR = me.frameBR; frameTL = me.frameTL; xPos = (me.getWidth() - frameTR.getPadding('r') - ((frameTL) ? frameTL.getPadding('l') : me.el.getBorderWidth('l'))) + 'px'; frameBR.setStyle('background-position-x', xPos); frameTR.setStyle('background-position-x', xPos); } if (Ext.isIE7 && Ext.isStrict && me.frame) { me.el.repaint(); } } }, beforeLayout: function () { this.callParent(); this.syncBeforeAfterTitleClasses(); }, adjustTitlePosition: function() { var titleCmp = this.titleCmp, titleEl; if (!Ext.isIE9m && titleCmp) { titleEl = titleCmp.el; titleEl.setStyle('left', titleEl.getWidth() + 'px'); } }, onTitleRender: function() { if (this.orientation === 'vertical') { this.titleCmp.el.setVertical(90); } }, addUIClsToElement: function(cls) { var me = this, result = me.callParent(arguments), classes = [me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls], array, i; if (me.bodyCls) { array = me.bodyCls.split(' '); for (i = 0; i < classes.length; i++) { if (!Ext.Array.contains(array, classes[i])) { array.push(classes[i]); } } me.bodyCls = array.join(' '); } else { me.bodyCls = classes.join(' '); } return result; }, removeUIClsFromElement: function(cls) { var me = this, result = me.callParent(arguments), classes = [me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls], array, i; if (me.bodyCls) { array = me.bodyCls.split(' '); for (i = 0; i < classes.length; i++) { Ext.Array.remove(array, classes[i]); } me.bodyCls = array.join(' '); } return result; }, addUIToElement: function() { var me = this, array, cls; me.callParent(arguments); cls = me.baseCls + '-body-' + me.ui; if (me.rendered) { if (me.bodyCls) { me.body.addCls(me.bodyCls); } else { me.body.addCls(cls); } } else { if (me.bodyCls) { array = me.bodyCls.split(' '); if (!Ext.Array.contains(array, cls)) { array.push(cls); } me.bodyCls = array.join(' '); } else { me.bodyCls = cls; } } if (me.titleCmp && me.titleCmp.rendered) { me.titleCmp.addCls(me.baseCls + '-text-container-' + me.ui); } }, removeUIFromElement: function() { var me = this, array, cls; me.callParent(arguments); cls = me.baseCls + '-body-' + me.ui; if (me.rendered) { if (me.bodyCls) { me.body.removeCls(me.bodyCls); } else { me.body.removeCls(cls); } } else { if (me.bodyCls) { array = me.bodyCls.split(' '); Ext.Array.remove(array, cls); me.bodyCls = array.join(' '); } else { me.bodyCls = cls; } } if (me.titleCmp && me.titleCmp.rendered) { me.titleCmp.removeCls(me.baseCls + '-text-container-' + me.ui); } }, onClick: function(e) { this.fireClickEvent('click', e); }, onDblClick: function(e){ this.fireClickEvent('dblclick', e); }, fireClickEvent: function(type, e){ var toolCls = '.' + Ext.panel.Tool.prototype.baseCls; if (!e.getTarget(toolCls)) { this.fireEvent(type, this, e); } }, getFocusEl: function() { return this.el; }, getTargetEl: function() { return this.body || this.frameBody || this.el; }, applyTargetCls: function(targetCls) { this.bodyTargetCls = targetCls; }, setTitle: function(title) { var me = this, titleCmp = me.titleCmp; me.title = title; if (titleCmp.rendered) { titleCmp.textEl.update(me.title || ' '); titleCmp.updateLayout(); } else { me.titleCmp.on({ render: function() { me.setTitle(title); }, single: true }); } }, getMinWidth: function() { var me = this, textEl = me.titleCmp.textEl.dom, result, tools = me.tools, l, i; textEl.style.display = 'inline'; result = textEl.offsetWidth; textEl.style.display = ''; if (tools && (l = tools.length)) { for (i = 0; i < l; i++) { if (tools[i].el) { result += tools[i].el.dom.offsetWidth; } } } if (me.iconCmp) { result += me.iconCmp.el.dom.offsetWidth; } return result + 10; }, setIconCls: function(cls) { var me = this, isEmpty = !cls || !cls.length, iconCmp = me.iconCmp; me.iconCls = cls; if (!me.iconCmp && !isEmpty) { me.initIconCmp(); me.insert(0, me.iconCmp); } else if (iconCmp) { if (isEmpty) { me.iconCmp.destroy(); delete me.iconCmp; } else { iconCmp.removeCls(iconCmp.iconCls); iconCmp.addCls(cls); iconCmp.iconCls = cls; } } }, setIcon: function(icon) { var me = this, isEmpty = !icon || !icon.length, iconCmp = me.iconCmp; me.icon = icon; if (!me.iconCmp && !isEmpty) { me.initIconCmp(); me.insert(0, me.iconCmp); } else if (iconCmp) { if (isEmpty) { me.iconCmp.destroy(); delete me.iconCmp; } else { iconCmp.setSrc(me.icon); } } }, setGlyph: function(glyph) { var me = this, iconCmp = me.iconCmp; if (!me.iconCmp) { me.initIconCmp(); me.insert(0, me.iconCmp); } else if (iconCmp) { if (glyph) { me.iconCmp.setGlyph(glyph); } else { me.iconCmp.destroy(); delete me.iconCmp; } } }, getTools: function(){ return this.tools.slice(); }, addTool: function(tool) { this.add(Ext.ComponentManager.create(tool, 'tool')); }, syncBeforeAfterTitleClasses: function(force) { var me = this, items = me.items, childItems = items.items, titlePosition = me.titlePosition, itemCount = childItems.length, itemGeneration = items.generation, syncGen = me.syncBeforeAfterGen, afterCls, beforeCls, i, item; if (!force && (syncGen === itemGeneration)) { return; } me.syncBeforeAfterGen = itemGeneration; for (i = 0; i < itemCount; ++i) { item = childItems[i]; afterCls = item.afterTitleCls || (item.afterTitleCls = item.baseCls + '-after-title') beforeCls = item.beforeTitleCls || (item.beforeTitleCls = item.baseCls + '-before-title') if (!me.title || i < titlePosition) { if (syncGen) { item.removeCls(afterCls); } item.addCls(beforeCls); } else if (i > titlePosition) { if (syncGen) { item.removeCls(beforeCls); } item.addCls(afterCls); } } }, onAdd: function(component, index) { var tools = this.tools; this.callParent(arguments); if (component.isTool) { tools.push(component); tools[component.type] = component; } }, initRenderData: function() { return Ext.applyIf(this.callParent(), { bodyCls: this.bodyCls, bodyTargetCls: this.bodyTargetCls, headerCls: this.headerCls }); }, getDockName: function() { return this.dock; }, getFramingInfoCls: function(){ var me = this, cls = me.callParent(), owner = me.ownerCt; if (!me.expanding && owner && (owner.collapsed || me.isCollapsedExpander)) { cls += '-' + owner.collapsedCls; } return cls + '-' + me.dock; } }); Ext.define('Ext.dd.DragDrop', { constructor: function(id, sGroup, config) { if(id) { this.init(id, sGroup, config); } }, id: null, config: null, dragElId: null, handleElId: null, invalidHandleTypes: null, invalidHandleIds: null, invalidHandleClasses: null, startPageX: 0, startPageY: 0, groups: null, locked: false, lock: function() { this.locked = true; }, moveOnly: false, unlock: function() { this.locked = false; }, isTarget: true, padding: null, _domRef: null, __ygDragDrop: true, constrainX: false, constrainY: false, minX: 0, maxX: 0, minY: 0, maxY: 0, maintainOffset: false, xTicks: null, yTicks: null, primaryButtonOnly: true, available: false, hasOuterHandles: false, b4StartDrag: function(x, y) { }, startDrag: function(x, y) { }, b4Drag: function(e) { }, onDrag: function(e) { }, onDragEnter: function(e, id) { }, b4DragOver: function(e) { }, onDragOver: function(e, id) { }, b4DragOut: function(e) { }, onDragOut: function(e, id) { }, b4DragDrop: function(e) { }, onDragDrop: function(e, id) { }, onInvalidDrop: function(e) { }, b4EndDrag: function(e) { }, endDrag: function(e) { }, b4MouseDown: function(e) { }, onMouseDown: function(e) { }, onMouseUp: function(e) { }, onAvailable: function () { }, defaultPadding: { left: 0, right: 0, top: 0, bottom: 0 }, constrainTo : function(constrainTo, pad, inContent){ if(Ext.isNumber(pad)){ pad = {left: pad, right:pad, top:pad, bottom:pad}; } pad = pad || this.defaultPadding; var b = Ext.get(this.getEl()).getBox(), ce = Ext.get(constrainTo), s = ce.getScroll(), c, cd = ce.dom, xy, topSpace, leftSpace; if(cd == document.body){ c = { x: s.left, y: s.top, width: Ext.Element.getViewWidth(), height: Ext.Element.getViewHeight()}; }else{ xy = ce.getXY(); c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight}; } topSpace = b.y - c.y; leftSpace = b.x - c.x; this.resetConstraints(); this.setXConstraint(leftSpace - (pad.left||0), c.width - leftSpace - b.width - (pad.right||0), this.xTickSize ); this.setYConstraint(topSpace - (pad.top||0), c.height - topSpace - b.height - (pad.bottom||0), this.yTickSize ); }, getEl: function() { if (!this._domRef) { this._domRef = Ext.getDom(this.id); } return this._domRef; }, getDragEl: function() { return Ext.getDom(this.dragElId); }, init: function(id, sGroup, config) { this.initTarget(id, sGroup, config); Ext.EventManager.on(this.id, "mousedown", this.handleMouseDown, this); }, initTarget: function(id, sGroup, config) { this.config = config || {}; this.DDMInstance = Ext.dd.DragDropManager; this.groups = {}; if (typeof id !== "string") { id = Ext.id(id); } this.id = id; this.addToGroup((sGroup) ? sGroup : "default"); this.handleElId = id; this.setDragElId(id); this.invalidHandleTypes = { A: "A" }; this.invalidHandleIds = {}; this.invalidHandleClasses = []; this.applyConfig(); this.handleOnAvailable(); }, applyConfig: function() { this.padding = this.config.padding || [0, 0, 0, 0]; this.isTarget = (this.config.isTarget !== false); this.maintainOffset = (this.config.maintainOffset); this.primaryButtonOnly = (this.config.primaryButtonOnly !== false); }, handleOnAvailable: function() { this.available = true; this.resetConstraints(); this.onAvailable(); }, setPadding: function(iTop, iRight, iBot, iLeft) { if (!iRight && 0 !== iRight) { this.padding = [iTop, iTop, iTop, iTop]; } else if (!iBot && 0 !== iBot) { this.padding = [iTop, iRight, iTop, iRight]; } else { this.padding = [iTop, iRight, iBot, iLeft]; } }, setInitPosition: function(diffX, diffY) { var el = this.getEl(), dx, dy, p; if (!this.DDMInstance.verifyEl(el)) { return; } dx = diffX || 0; dy = diffY || 0; p = Ext.Element.getXY( el ); this.initPageX = p[0] - dx; this.initPageY = p[1] - dy; this.lastPageX = p[0]; this.lastPageY = p[1]; this.setStartPosition(p); }, setStartPosition: function(pos) { var p = pos || Ext.Element.getXY( this.getEl() ); this.deltaSetXY = null; this.startPageX = p[0]; this.startPageY = p[1]; }, addToGroup: function(sGroup) { this.groups[sGroup] = true; this.DDMInstance.regDragDrop(this, sGroup); }, removeFromGroup: function(sGroup) { if (this.groups[sGroup]) { delete this.groups[sGroup]; } this.DDMInstance.removeDDFromGroup(this, sGroup); }, setDragElId: function(id) { this.dragElId = id; }, setHandleElId: function(id) { if (typeof id !== "string") { id = Ext.id(id); } this.handleElId = id; this.DDMInstance.regHandle(this.id, id); }, setOuterHandleElId: function(id) { if (typeof id !== "string") { id = Ext.id(id); } Ext.EventManager.on(id, "mousedown", this.handleMouseDown, this); this.setHandleElId(id); this.hasOuterHandles = true; }, unreg: function() { var me = this; Ext.EventManager.un(me.id, "mousedown", me.handleMouseDown, me); me._domRef = null; me.DDMInstance._remove(me, me.autoGroup); }, destroy : function(){ this.unreg(); }, isLocked: function() { return (this.DDMInstance.isLocked() || this.locked); }, handleMouseDown: function(e, oDD){ var me = this; if ((me.primaryButtonOnly && e.button != 0) || me.isLocked()) { return; } me.DDMInstance.refreshCache(me.groups); if (me.hasOuterHandles || me.DDMInstance.isOverTarget(e.getPoint(), me)) { if (me.clickValidator(e)) { me.setStartPosition(); me.b4MouseDown(e); me.onMouseDown(e); me.DDMInstance.handleMouseDown(e, me); me.DDMInstance.stopEvent(e); } } }, clickValidator: function(e) { var target = e.getTarget(); return ( this.isValidHandleChild(target) && (this.id == this.handleElId || this.DDMInstance.handleWasClicked(target, this.id)) ); }, addInvalidHandleType: function(tagName) { var type = tagName.toUpperCase(); this.invalidHandleTypes[type] = type; }, addInvalidHandleId: function(id) { if (typeof id !== "string") { id = Ext.id(id); } this.invalidHandleIds[id] = id; }, addInvalidHandleClass: function(cssClass) { this.invalidHandleClasses.push(cssClass); }, removeInvalidHandleType: function(tagName) { var type = tagName.toUpperCase(); delete this.invalidHandleTypes[type]; }, removeInvalidHandleId: function(id) { if (typeof id !== "string") { id = Ext.id(id); } delete this.invalidHandleIds[id]; }, removeInvalidHandleClass: function(cssClass) { for (var i=0, len=this.invalidHandleClasses.length; i= this.minX; i = i - iTickSize) { if (!tickMap[i]) { this.xTicks[this.xTicks.length] = i; tickMap[i] = true; } } for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) { if (!tickMap[i]) { this.xTicks[this.xTicks.length] = i; tickMap[i] = true; } } Ext.Array.sort(this.xTicks, this.DDMInstance.numericSort); }, setYTicks: function(iStartY, iTickSize) { this.yTicks = []; this.yTickSize = iTickSize; var tickMap = {}, i; for (i = this.initPageY; i >= this.minY; i = i - iTickSize) { if (!tickMap[i]) { this.yTicks[this.yTicks.length] = i; tickMap[i] = true; } } for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) { if (!tickMap[i]) { this.yTicks[this.yTicks.length] = i; tickMap[i] = true; } } Ext.Array.sort(this.yTicks, this.DDMInstance.numericSort); }, setXConstraint: function(iLeft, iRight, iTickSize) { this.leftConstraint = iLeft; this.rightConstraint = iRight; this.minX = this.initPageX - iLeft; this.maxX = this.initPageX + iRight; if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); } this.constrainX = true; }, clearConstraints: function() { this.constrainX = false; this.constrainY = false; this.clearTicks(); }, clearTicks: function() { this.xTicks = null; this.yTicks = null; this.xTickSize = 0; this.yTickSize = 0; }, setYConstraint: function(iUp, iDown, iTickSize) { this.topConstraint = iUp; this.bottomConstraint = iDown; this.minY = this.initPageY - iUp; this.maxY = this.initPageY + iDown; if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); } this.constrainY = true; }, resetConstraints: function() { if (this.initPageX || this.initPageX === 0) { var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0, dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0; this.setInitPosition(dx, dy); } else { this.setInitPosition(); } if (this.constrainX) { this.setXConstraint( this.leftConstraint, this.rightConstraint, this.xTickSize ); } if (this.constrainY) { this.setYConstraint( this.topConstraint, this.bottomConstraint, this.yTickSize ); } }, getTick: function(val, tickArray) { if (!tickArray) { return val; } else if (tickArray[0] >= val) { return tickArray[0]; } else { var i, len, next, diff1, diff2; for (i=0, len=tickArray.length; i= val) { diff1 = val - tickArray[i]; diff2 = tickArray[next] - val; return (diff2 > diff1) ? tickArray[i] : tickArray[next]; } } return tickArray[tickArray.length - 1]; } }, toString: function() { return ("DragDrop " + this.id); } }); Ext.define('Ext.dd.DD', { extend: Ext.dd.DragDrop , constructor: function(id, sGroup, config) { if (id) { this.init(id, sGroup, config); } }, scroll: true, autoOffset: function(iPageX, iPageY) { var x = iPageX - this.startPageX, y = iPageY - this.startPageY; this.setDelta(x, y); }, setDelta: function(iDeltaX, iDeltaY) { this.deltaX = iDeltaX; this.deltaY = iDeltaY; }, setDragElPos: function(iPageX, iPageY) { var el = this.getDragEl(); this.alignElWithMouse(el, iPageX, iPageY); }, alignElWithMouse: function(el, iPageX, iPageY) { var oCoord = this.getTargetCoord(iPageX, iPageY), fly = el.dom ? el : Ext.fly(el, '_dd'), elSize = fly.getSize(), EL = Ext.Element, vpSize, aCoord, newLeft, newTop; if (!this.deltaSetXY) { vpSize = this.cachedViewportSize = { width: EL.getDocumentWidth(), height: EL.getDocumentHeight() }; aCoord = [ Math.max(0, Math.min(oCoord.x, vpSize.width - elSize.width)), Math.max(0, Math.min(oCoord.y, vpSize.height - elSize.height)) ]; fly.setXY(aCoord); newLeft = this.getLocalX(fly); newTop = fly.getLocalY(); this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y]; } else { vpSize = this.cachedViewportSize; this.setLocalXY( fly, Math.max(0, Math.min(oCoord.x + this.deltaSetXY[0], vpSize.width - elSize.width)), Math.max(0, Math.min(oCoord.y + this.deltaSetXY[1], vpSize.height - elSize.height)) ); } this.cachePosition(oCoord.x, oCoord.y); this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth); return oCoord; }, cachePosition: function(iPageX, iPageY) { if (iPageX) { this.lastPageX = iPageX; this.lastPageY = iPageY; } else { var aCoord = Ext.Element.getXY(this.getEl()); this.lastPageX = aCoord[0]; this.lastPageY = aCoord[1]; } }, autoScroll: function(x, y, h, w) { if (this.scroll) { var clientH = Ext.Element.getViewHeight(), clientW = Ext.Element.getViewWidth(), st = this.DDMInstance.getScrollTop(), sl = this.DDMInstance.getScrollLeft(), bot = h + y, right = w + x, toBot = (clientH + st - y - this.deltaY), toRight = (clientW + sl - x - this.deltaX), thresh = 40, scrAmt = (document.all) ? 80 : 30; if ( bot > clientH && toBot < thresh ) { window.scrollTo(sl, st + scrAmt); } if ( y < st && st > 0 && y - st < thresh ) { window.scrollTo(sl, st - scrAmt); } if ( right > clientW && toRight < thresh ) { window.scrollTo(sl + scrAmt, st); } if ( x < sl && sl > 0 && x - sl < thresh ) { window.scrollTo(sl - scrAmt, st); } } }, getTargetCoord: function(iPageX, iPageY) { var x = iPageX - this.deltaX, y = iPageY - this.deltaY; if (this.constrainX) { if (x < this.minX) { x = this.minX; } if (x > this.maxX) { x = this.maxX; } } if (this.constrainY) { if (y < this.minY) { y = this.minY; } if (y > this.maxY) { y = this.maxY; } } x = this.getTick(x, this.xTicks); y = this.getTick(y, this.yTicks); return {x: x, y: y}; }, applyConfig: function() { this.callParent(); this.scroll = (this.config.scroll !== false); }, b4MouseDown: function(e) { this.autoOffset(e.getPageX(), e.getPageY()); }, b4Drag: function(e) { this.setDragElPos(e.getPageX(), e.getPageY()); }, toString: function() { return ("DD " + this.id); }, getLocalX: function(el) { return el.getLocalX(); }, setLocalXY: function(el, x, y) { el.setLocalXY(x, y); } }); Ext.define('Ext.dd.DDProxy', { extend: Ext.dd.DD , statics: { dragElId: "ygddfdiv" }, constructor: function(id, sGroup, config) { if (id) { this.init(id, sGroup, config); this.initFrame(); } }, resizeFrame: true, centerFrame: false, createFrame: function() { var self = this, body = document.body, div, s; if (!body || !body.firstChild) { setTimeout( function() { self.createFrame(); }, 50 ); return; } div = this.getDragEl(); if (!div) { div = document.createElement("div"); div.id = this.dragElId; div.setAttribute('role', 'presentation'); s = div.style; s.position = "absolute"; s.visibility = "hidden"; s.cursor = "move"; s.border = "2px solid #aaa"; s.zIndex = 999; body.insertBefore(div, body.firstChild); } }, initFrame: function() { this.createFrame(); }, applyConfig: function() { this.callParent(); this.resizeFrame = (this.config.resizeFrame !== false); this.centerFrame = (this.config.centerFrame); this.setDragElId(this.config.dragElId || Ext.dd.DDProxy.dragElId); }, showFrame: function(iPageX, iPageY) { var el = this.getEl(), dragEl = this.getDragEl(), s = dragEl.style; this._resizeProxy(); if (this.centerFrame) { this.setDelta( Math.round(parseInt(s.width, 10)/2), Math.round(parseInt(s.height, 10)/2) ); } this.setDragElPos(iPageX, iPageY); Ext.fly(dragEl).show(); }, _resizeProxy: function() { if (this.resizeFrame) { var el = this.getEl(); Ext.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight); } }, b4MouseDown: function(e) { var x = e.getPageX(), y = e.getPageY(); this.autoOffset(x, y); this.setDragElPos(x, y); }, b4StartDrag: function(x, y) { this.showFrame(x, y); }, b4EndDrag: function(e) { Ext.fly(this.getDragEl()).hide(); }, endDrag: function(e) { var lel = this.getEl(), del = this.getDragEl(); del.style.visibility = ""; this.beforeMove(); lel.style.visibility = "hidden"; Ext.dd.DDM.moveToEl(lel, del); del.style.visibility = "hidden"; lel.style.visibility = ""; this.afterDrag(); }, beforeMove : function(){ }, afterDrag : function(){ }, toString: function() { return ("DDProxy " + this.id); } }); Ext.define('Ext.dd.StatusProxy', { extend: Ext.Component , animRepair: false, childEls: [ 'ghost' ], renderTpl: [ '' + '' ], repairCls: Ext.baseCSSPrefix + 'dd-drag-repair', ariaRole: 'presentation', constructor: function(config) { var me = this; config = config || {}; Ext.apply(me, { hideMode: 'visibility', hidden: true, floating: true, id: me.id || Ext.id(), cls: Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed, shadow: config.shadow || false, renderTo: Ext.getDetachedBody() }); me.callParent(arguments); this.dropStatus = this.dropNotAllowed; }, dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok', dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop', setStatus : function(cssClass){ cssClass = cssClass || this.dropNotAllowed; if (this.dropStatus != cssClass) { this.el.replaceCls(this.dropStatus, cssClass); this.dropStatus = cssClass; } }, reset : function(clearGhost){ var me = this, clsPrefix = Ext.baseCSSPrefix + 'dd-drag-proxy '; me.el.replaceCls(clsPrefix + me.dropAllowed, clsPrefix + me.dropNotAllowed); me.dropStatus = me.dropNotAllowed; if (clearGhost) { me.ghost.update(''); } }, update : function(html){ if (typeof html == "string") { this.ghost.update(html); } else { this.ghost.update(""); html.style.margin = "0"; this.ghost.dom.appendChild(html); } var el = this.ghost.dom.firstChild; if (el) { Ext.fly(el).setStyle('float', 'none'); } }, getGhost : function(){ return this.ghost; }, hide : function(clear) { this.callParent(); if (clear) { this.reset(true); } }, stop : function(){ if (this.anim && this.anim.isAnimated && this.anim.isAnimated()) { this.anim.stop(); } }, sync : function(){ this.el.sync(); }, repair : function(xy, callback, scope) { var me = this; me.callback = callback; me.scope = scope; if (xy && me.animRepair !== false) { me.el.addCls(me.repairCls); me.el.hideUnders(true); me.anim = me.el.animate({ duration: me.repairDuration || 500, easing: 'ease-out', to: { x: xy[0], y: xy[1] }, stopAnimation: true, callback: me.afterRepair, scope: me }); } else { me.afterRepair(); } }, afterRepair : function() { var me = this; me.hide(true); me.el.removeCls(me.repairCls); if (typeof me.callback == "function") { me.callback.call(me.scope || me); } delete me.callback; delete me.scope; } }); Ext.define('Ext.dd.DragSource', { extend: Ext.dd.DDProxy , dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok', dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop', animRepair: true, repairHighlightColor: 'c3daf9', constructor: function(el, config) { this.el = Ext.get(el); if(!this.dragData){ this.dragData = {}; } Ext.apply(this, config); if(!this.proxy){ this.proxy = new Ext.dd.StatusProxy({ id: this.el.id + '-drag-status-proxy', animRepair: this.animRepair }); } this.callParent([this.el.dom, this.ddGroup || this.group, {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true}]); this.dragging = false; }, getDragData : function(e){ return this.dragData; }, onDragEnter : function(e, id){ var target = Ext.dd.DragDropManager.getDDById(id), status; this.cachedTarget = target; if (this.beforeDragEnter(target, e, id) !== false) { if (target.isNotifyTarget) { status = target.notifyEnter(this, e, this.dragData); this.proxy.setStatus(status); } else { this.proxy.setStatus(this.dropAllowed); } if (this.afterDragEnter) { this.afterDragEnter(target, e, id); } } }, beforeDragEnter: function(target, e, id) { return true; }, onDragOver: function(e, id) { var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id), status; if (this.beforeDragOver(target, e, id) !== false) { if(target.isNotifyTarget){ status = target.notifyOver(this, e, this.dragData); this.proxy.setStatus(status); } if (this.afterDragOver) { this.afterDragOver(target, e, id); } } }, beforeDragOver: function(target, e, id) { return true; }, onDragOut: function(e, id) { var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id); if (this.beforeDragOut(target, e, id) !== false) { if (target.isNotifyTarget) { target.notifyOut(this, e, this.dragData); } this.proxy.reset(); if (this.afterDragOut) { this.afterDragOut(target, e, id); } } this.cachedTarget = null; }, beforeDragOut: function(target, e, id){ return true; }, onDragDrop: function(e, id){ var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id); if (this.beforeDragDrop(target, e, id) !== false) { if (target.isNotifyTarget) { if (target.notifyDrop(this, e, this.dragData) !== false) { this.onValidDrop(target, e, id); } else { this.onInvalidDrop(target, e, id); } } else { this.onValidDrop(target, e, id); } if (this.afterDragDrop) { this.afterDragDrop(target, e, id); } } delete this.cachedTarget; }, beforeDragDrop: function(target, e, id){ return true; }, onValidDrop: function(target, e, id){ this.hideProxy(); if(this.afterValidDrop){ this.afterValidDrop(target, e, id); } }, getRepairXY: function(e, data){ return this.el.getXY(); }, onInvalidDrop: function(target, e, id) { var me = this; if (!e) { e = target; target = null; id = e.getTarget().id; } if (me.beforeInvalidDrop(target, e, id) !== false) { if (me.cachedTarget) { if(me.cachedTarget.isNotifyTarget){ me.cachedTarget.notifyOut(me, e, me.dragData); } me.cacheTarget = null; } me.proxy.repair(me.getRepairXY(e, me.dragData), me.afterRepair, me); if (me.afterInvalidDrop) { me.afterInvalidDrop(e, id); } } }, afterRepair: function() { var me = this; if (Ext.enableFx) { me.el.highlight(me.repairHighlightColor); } me.dragging = false; }, beforeInvalidDrop: function(target, e, id) { return true; }, handleMouseDown: function(e) { if (this.dragging) { return; } var data = this.getDragData(e); if (data && this.onBeforeDrag(data, e) !== false) { this.dragData = data; this.proxy.stop(); this.callParent(arguments); } }, onBeforeDrag: function(data, e){ return true; }, onStartDrag: Ext.emptyFn, alignElWithMouse: function() { this.proxy.ensureAttachedToBody(true); return this.callParent(arguments); }, startDrag: function(x, y) { this.proxy.reset(); this.proxy.hidden = false; this.dragging = true; this.proxy.update(""); this.onInitDrag(x, y); this.proxy.show(); }, onInitDrag: function(x, y) { var clone = this.el.dom.cloneNode(true); clone.id = Ext.id(); this.proxy.update(clone); this.onStartDrag(x, y); return true; }, getProxy: function() { return this.proxy; }, hideProxy: function() { this.proxy.hide(); this.proxy.reset(true); this.dragging = false; }, triggerCacheRefresh: function() { Ext.dd.DDM.refreshCache(this.groups); }, b4EndDrag: function(e) { }, endDrag : function(e){ this.onEndDrag(this.dragData, e); }, onEndDrag : function(data, e){ }, autoOffset : function(x, y) { this.setDelta(-12, -20); }, destroy: function(){ this.callParent(); Ext.destroy(this.proxy); } }); Ext.define('Ext.panel.Proxy', { alternateClassName: 'Ext.dd.PanelProxy', moveOnDrag: true, constructor: function(panel, config){ var me = this; me.panel = panel; me.id = me.panel.id +'-ddproxy'; Ext.apply(me, config); }, insertProxy: true, setStatus: Ext.emptyFn, reset: Ext.emptyFn, update: Ext.emptyFn, stop: Ext.emptyFn, sync: Ext.emptyFn, getEl: function(){ return this.ghost.el; }, getGhost: function(){ return this.ghost; }, getProxy: function(){ return this.proxy; }, hide : function(){ var me = this; if (me.ghost) { if (me.proxy) { me.proxy.remove(); delete me.proxy; } me.panel.unghost(null, me.moveOnDrag); delete me.ghost; } }, show: function(){ var me = this, panelSize; if (!me.ghost) { panelSize = me.panel.getSize(); me.panel.el.setVisibilityMode(Ext.Element.DISPLAY); me.ghost = me.panel.ghost(); if (me.insertProxy) { me.proxy = me.panel.el.insertSibling({ role: 'presentation', cls: Ext.baseCSSPrefix + 'panel-dd-spacer' }); me.proxy.setSize(panelSize); } } }, repair: function(xy, callback, scope) { this.hide(); Ext.callback(callback, scope || this); }, moveProxy : function(parentNode, before){ if (this.proxy) { parentNode.insertBefore(this.proxy.dom, before); } } }); Ext.define('Ext.panel.DD', { extend: Ext.dd.DragSource , constructor : function(panel, cfg){ var me = this; me.panel = panel; me.dragData = {panel: panel}; me.panelProxy = new Ext.panel.Proxy(panel, cfg); me.proxy = me.panelProxy.proxy; me.callParent([panel.el, cfg]); me.setupEl(panel); }, setupEl: function(panel){ var me = this, header = panel.header, el = panel.body; if (header) { me.setHandleElId(header.id); el = header.el; } if (el) { el.setStyle('cursor', 'move'); me.scroll = false; } else { panel.on('boxready', me.setupEl, me, {single: true}); } }, showFrame: Ext.emptyFn, startDrag: Ext.emptyFn, b4StartDrag: function(x, y) { this.panelProxy.show(); }, b4MouseDown: function(e) { var x = e.getPageX(), y = e.getPageY(); this.autoOffset(x, y); }, onInitDrag : function(x, y){ this.onStartDrag(x, y); return true; }, createFrame : Ext.emptyFn, getDragEl : function(e){ var ghost = this.panelProxy.ghost; if (ghost) { return ghost.el.dom; } }, endDrag : function(e){ this.panelProxy.hide(); this.panel.saveState(); }, autoOffset : function(x, y) { x -= this.startPageX; y -= this.startPageY; this.setDelta(x, y); }, onInvalidDrop: function(target, e, id) { var me = this; if (me.beforeInvalidDrop(target, e, id) !== false) { if (me.cachedTarget) { if(me.cachedTarget.isNotifyTarget){ me.cachedTarget.notifyOut(me, e, me.dragData); } me.cacheTarget = null; } if (me.afterInvalidDrop) { me.afterInvalidDrop(e, id); } } } }); Ext.define('Ext.util.Memento', (function () { function captureOne (src, target, prop, prefix) { src[prefix ? prefix + prop : prop] = target[prop]; } function removeOne (src, target, prop) { delete src[prop]; } function restoreOne (src, target, prop, prefix) { var name = prefix ? prefix + prop : prop, value = src[name]; if (value || src.hasOwnProperty(name)) { restoreValue(target, prop, value); } } function restoreValue (target, prop, value) { if (Ext.isDefined(value)) { target[prop] = value; } else { delete target[prop]; } } function doMany (doOne, src, target, props, prefix) { if (src) { if (Ext.isArray(props)) { var p, pLen = props.length; for (p = 0; p < pLen; p++) { doOne(src, target, props[p], prefix); } } else { doOne(src, target, props, prefix); } } } return { data: null, target: null, constructor: function (target, props) { if (target) { this.target = target; if (props) { this.capture(props); } } }, capture: function (props, target, prefix) { var me = this; doMany(captureOne, me.data || (me.data = {}), target || me.target, props, prefix); }, remove: function (props) { doMany(removeOne, this.data, null, props); }, restore: function (props, clear, target, prefix) { doMany(restoreOne, this.data, target || this.target, props, prefix); if (clear !== false) { this.remove(props); } }, restoreAll: function (clear, target) { var me = this, t = target || this.target, data = me.data, prop; for (prop in data) { if (data.hasOwnProperty(prop)) { restoreValue(t, prop, data[prop]); } } if (clear !== false) { delete me.data; } } }; }())); Ext.define('Ext.panel.Panel', { extend: Ext.panel.AbstractPanel , alias: 'widget.panel', alternateClassName: 'Ext.Panel', collapsedCls: 'collapsed', animCollapse: Ext.enableFx, minButtonWidth: 75, collapsed: false, collapseFirst: true, hideCollapseTool: false, titleCollapse: undefined, floatable: true, collapsible: undefined, closable: false, closeAction: 'destroy', placeholderCollapseHideMode: Ext.Element.VISIBILITY, preventHeader: false, header: undefined, headerPosition: 'top', frame: false, frameHeader: true, manageHeight: true, constrain: false, constrainHeader: false, initComponent: function() { var me = this; me.addEvents( 'beforeclose', 'close', "beforeexpand", "beforecollapse", "expand", "collapse", 'titlechange', 'iconchange', 'iconclschange', 'glyphchange', 'float', 'unfloat' ); if (me.collapsible) { me.addStateEvents(['expand', 'collapse']); } if (me.unstyled) { me.setUI('plain'); } if (me.frame) { me.setUI(me.ui + '-framed'); } me.bridgeToolbars(); me.callParent(); me.collapseDirection = me.collapseDirection || me.headerPosition || Ext.Component.DIRECTION_TOP; me.hiddenOnCollapse = new Ext.dom.CompositeElement(); }, beforeDestroy: function() { var me = this; Ext.destroy( me.placeholder, me.ghostPanel, me.dd ); me.callParent(); }, getFocusEl: function() { return this.el; }, getHeader: function() { return this.header; }, setTitle: function(newTitle) { var me = this, oldTitle = me.title, header = me.header, reExpander = me.reExpander, placeholder = me.placeholder; me.title = newTitle; if (header) { if (header.isHeader) { header.setTitle(newTitle); } else { header.title = newTitle; } } else if (me.rendered) { me.updateHeader(); } if (reExpander) { reExpander.setTitle(newTitle); } if (placeholder && placeholder.setTitle) { placeholder.setTitle(newTitle); } me.fireEvent('titlechange', me, newTitle, oldTitle); }, setIconCls: function(newIconCls) { var me = this, oldIconCls = me.iconCls, header = me.header, placeholder = me.placeholder; me.iconCls = newIconCls; if (header) { if (header.isHeader) { header.setIconCls(newIconCls); } else { header.iconCls = newIconCls; } } else { me.updateHeader(); } if (placeholder && placeholder.setIconCls) { placeholder.setIconCls(newIconCls); } me.fireEvent('iconclschange', me, newIconCls, oldIconCls); }, setIcon: function(newIcon) { var me = this, oldIcon = me.icon, header = me.header, placeholder = me.placeholder; me.icon = newIcon; if (header) { if (header.isHeader) { header.setIcon(newIcon); } else { header.icon = newIcon; } } else { me.updateHeader(); } if (placeholder && placeholder.setIcon) { placeholder.setIcon(newIcon); } me.fireEvent('iconchange', me, newIcon, oldIcon); }, setGlyph: function(newGlyph) { var me = this, oldGlyph = me.glyph, header = me.header, placeholder = me.placeholder; me.glyph = newGlyph; if (header) { if (header.isHeader) { header.setGlyph(newGlyph); } else { header.glyph = newGlyph; } } else { me.updateHeader(); } if (placeholder && placeholder.setGlyph) { placeholder.setIcon(newGlyph); } me.fireEvent('glyphchange', me, newGlyph, oldGlyph); }, bridgeToolbars: function() { var me = this, docked = [], minButtonWidth = me.minButtonWidth, fbar, fbarDefaults; function initToolbar (toolbar, pos, useButtonAlign) { if (Ext.isArray(toolbar)) { toolbar = { xtype: 'toolbar', items: toolbar }; } else if (!toolbar.xtype) { toolbar.xtype = 'toolbar'; } toolbar.dock = pos; if (pos == 'left' || pos == 'right') { toolbar.vertical = true; } if (useButtonAlign) { toolbar.layout = Ext.applyIf(toolbar.layout || {}, { pack: { left:'start', center:'center' }[me.buttonAlign] || 'end' }); } return toolbar; } if (me.tbar) { docked.push(initToolbar(me.tbar, 'top')); me.tbar = null; } if (me.bbar) { docked.push(initToolbar(me.bbar, 'bottom')); me.bbar = null; } if (me.buttons) { me.fbar = me.buttons; me.buttons = null; } if (me.fbar) { fbar = initToolbar(me.fbar, 'bottom', true); fbar.ui = 'footer'; if (minButtonWidth) { fbarDefaults = fbar.defaults; fbar.defaults = function(config) { var defaults = fbarDefaults || {}, isButton = !config.xtype || config.isButton, cls; if (!isButton) { cls = Ext.ClassManager.getByAlias('widget.' + config.xtype); if (cls) { isButton = cls.prototype.isButton; } } if (isButton && !('minWidth' in defaults)) { defaults = Ext.apply({minWidth: minButtonWidth}, defaults); } return defaults; }; } docked.push(fbar); me.fbar = null; } if (me.lbar) { docked.push(initToolbar(me.lbar, 'left')); me.lbar = null; } if (me.rbar) { docked.push(initToolbar(me.rbar, 'right')); me.rbar = null; } if (me.dockedItems) { if (!Ext.isArray(me.dockedItems)) { me.dockedItems = [me.dockedItems]; } me.dockedItems = me.dockedItems.concat(docked); } else { me.dockedItems = docked; } }, isPlaceHolderCollapse: function(){ return this.collapseMode == 'placeholder'; }, onBoxReady: function(){ this.callParent(); if (this.collapsed) { this.setHiddenDocked(); } }, beforeRender: function() { var me = this, wasCollapsed; me.callParent(); me.initTools(); if (!(me.preventHeader || (me.header === false))) { me.updateHeader(); } if (me.collapsed) { if (me.isPlaceHolderCollapse()) { if (!me.hidden) { me.setHiddenState(true); me.preventCollapseFire = true; me.placeholderCollapse(); delete me.preventCollapseFire; wasCollapsed = me.collapsed; me.collapsed = false; } } else { me.beginCollapse(); me.addClsWithUI(me.collapsedCls); } } if (wasCollapsed) { me.collapsed = wasCollapsed; } }, initTools: function() { var me = this, tools = me.tools, i, tool; me.tools = []; for (i = tools && tools.length; i; ) { --i; me.tools[i] = tool = tools[i]; tool.toolOwner = me; } if (me.collapsible && !(me.hideCollapseTool || me.header === false || me.preventHeader)) { me.collapseDirection = me.collapseDirection || me.headerPosition || 'top'; me.collapseTool = me.expandTool = Ext.widget({ xtype: 'tool', handler: me.toggleCollapse, scope: me }); me.updateCollapseTool(); if (me.collapseFirst) { me.tools.unshift(me.collapseTool); } } me.addTools(); if (me.closable) { me.addClsWithUI('closable'); me.addTool(Ext.widget({ xtype : 'tool', type: 'close', handler: Ext.Function.bind(me.close, me, []) })); } if (me.collapseTool && !me.collapseFirst) { me.addTool(me.collapseTool); } }, addTools: Ext.emptyFn, updateCollapseTool: function () { var me = this, collapseTool = me.collapseTool; if (collapseTool) { if (me.collapsed && !me.isPlaceHolderCollapse()) { collapseTool.setType('expand-' + me.getOppositeDirection(me.collapseDirection)); } else { collapseTool.setType('collapse-' + me.collapseDirection); } } }, close: function() { if (this.fireEvent('beforeclose', this) !== false) { this.doClose(); } }, doClose: function() { this.fireEvent('close', this); this[this.closeAction](); }, updateHeader: function(force) { var me = this, header = me.header, title = me.title, tools = me.tools, icon = me.icon || me.iconCls, vertical = me.headerPosition === 'left' || me.headerPosition === 'right'; if (Ext.isObject(header) || (header !== false && (force || (title || icon) || (tools && tools.length) || (me.collapsible && !me.titleCollapse)))) { if (header && header.isHeader) { header.show(); } else { header = me.header = Ext.widget(Ext.apply({ xtype : 'header', title : title, titleAlign : me.titleAlign, orientation : vertical ? 'vertical' : 'horizontal', dock : me.headerPosition || 'top', textCls : me.headerTextCls, iconCls : me.iconCls, icon : me.icon, glyph : me.glyph, baseCls : me.baseCls + '-header', tools : tools, ui : me.ui, id : me.id + '_header', overCls: me.headerOverCls, indicateDrag: me.draggable, frame : (me.frame || me.alwaysFramed) && me.frameHeader, ignoreParentFrame : me.frame || me.overlapHeader, ignoreBorderManagement: me.frame || me.ignoreHeaderBorderManagement, headerRole : me.headerRole, ownerCt : me, listeners : me.collapsible && me.titleCollapse ? { click: me.toggleCollapse, scope: me } : null }, me.header)); me.addDocked(header, 0); } } else if (header) { header.hide(); } }, setUI: function(ui) { var me = this; me.callParent(arguments); if (me.header && me.header.rendered) { me.header.setUI(ui); } }, getDefaultContentTarget: function() { return this.body; }, getTargetEl: function() { var me = this; return me.body || me.protoBody || me.frameBody || me.el; }, isVisible: function(deep){ var me = this; if (me.collapsed && me.placeholder) { return me.placeholder.isVisible(deep); } return me.callParent(arguments); }, onHide: function() { var me = this, dd = me.dd; if (me.floatedFromCollapse) { me.slideOutFloatedPanel(true); } if (me.draggable && dd) { dd.endDrag(); } if (me.collapsed && me.placeholder) { me.placeholder.hide(); } else { me.callParent(arguments); } }, onShow: function() { var me = this; if (me.collapsed && me.isPlaceHolderCollapse()) { me.setHiddenState(true); me.placeholderCollapse(); } else { me.callParent(arguments); } }, onRemoved: function(destroying) { var me = this; if (me.placeholder && !destroying) { me.ownerCt.remove(me.placeholder, false); } me.callParent(arguments); }, addTool: function(tools) { if (!Ext.isArray(tools)) { tools = [tools]; } var me = this, header = me.header, t, tLen = tools.length, tool; for (t = 0; t < tLen; t++) { tool = tools[t]; tool.toolOwner = me; if (header && header.isHeader) { header.addTool(tool); } else { me.tools.push(tool); } } me.updateHeader(); }, getOppositeDirection: function(d) { var c = Ext.Component; switch (d) { case c.DIRECTION_TOP: return c.DIRECTION_BOTTOM; case c.DIRECTION_RIGHT: return c.DIRECTION_LEFT; case c.DIRECTION_BOTTOM: return c.DIRECTION_TOP; case c.DIRECTION_LEFT: return c.DIRECTION_RIGHT; } }, getWidthAuthority: function() { if (this.collapsed && this.collapsedHorizontal()) { return 1; } return this.callParent(); }, getHeightAuthority: function() { if (this.collapsed && this.collapsedVertical()) { return 1; } return this.callParent(); }, collapsedHorizontal: function () { var dir = this.getCollapsed(); return dir === 'left' || dir === 'right'; }, collapsedVertical: function () { var dir = this.getCollapsed(); return dir === 'top' || dir === 'bottom'; }, restoreDimension: function(){ var dir = this.collapseDirection; return (dir === 'top' || dir === 'bottom') ? 'height' : 'width'; }, getCollapsed: function() { var me = this; if (me.collapsed === true) { return me.collapseDirection; } return me.collapsed; }, getState: function() { var me = this, state = me.callParent(), memento; state = me.addPropertyToState(state, 'collapsed'); if (me.collapsed) { memento = me.collapseMemento; memento = memento && memento.data; if (me.collapsedVertical()) { if (state) { delete state.height; } if (memento) { state = me.addPropertyToState(state, 'height', memento.height); } } else { if (state) { delete state.width; } if (memento) { state = me.addPropertyToState(state, 'width', memento.width); } } } return state; }, findReExpander: function (direction) { var me = this, c = Ext.Component, dockedItems = me.dockedItems.items, dockedItemCount = dockedItems.length, comp, i; if (me.collapseMode === 'mini') { return; } switch (direction) { case c.DIRECTION_TOP: case c.DIRECTION_BOTTOM: for (i = 0; i < dockedItemCount; i++) { comp = dockedItems[i]; if (!comp.hidden) { if (comp.isHeader && (!comp.dock || comp.dock === 'top' || comp.dock === 'bottom')) { return comp; } } } break; case c.DIRECTION_LEFT: case c.DIRECTION_RIGHT: for (i = 0; i < dockedItemCount; i++) { comp = dockedItems[i]; if (!comp.hidden) { if (comp.isHeader && (comp.dock === 'left' || comp.dock === 'right')) { return comp; } } } break; default: throw('Panel#findReExpander must be passed a valid collapseDirection'); } }, getReExpander: function (direction) { var me = this, collapseDir = direction || me.collapseDirection, reExpander = me.reExpander || me.findReExpander(collapseDir); me.expandDirection = me.getOppositeDirection(collapseDir); if (!reExpander) { me.reExpander = reExpander = me.createReExpander(collapseDir, { dock: collapseDir, cls: Ext.baseCSSPrefix + 'docked ' + me.baseCls + '-' + me.ui + '-collapsed', isCollapsedExpander: true }); me.dockedItems.insert(0, reExpander); } return reExpander; }, createReExpander: function(direction, defaults) { var me = this, isLeft = direction === 'left', isRight = direction === 'right', isVertical = isLeft || isRight, ownerCt = me.ownerCt, result = Ext.apply({ hideMode: 'offsets', title: me.title || ' ', titleAlign: me.titleAlign, orientation: isVertical ? 'vertical' : 'horizontal', textCls: me.headerTextCls, icon: me.icon, iconCls: me.iconCls, glyph: me.glyph, baseCls: me.self.prototype.baseCls + '-header', ui: me.ui, frame: me.frame && me.frameHeader, ignoreParentFrame: me.frame || me.overlapHeader, ignoreBorderManagement: me.frame || me.ignoreHeaderBorderManagement, indicateDrag: me.draggable, collapseImmune: true, headerRole: me.headerRole, ownerCt: (ownerCt && me.collapseMode === 'placeholder') ? ownerCt : me, ownerLayout: me.componentLayout, margin: me.margin }, defaults); if (me.collapseMode === 'mini') { if (isVertical) { result.width = 1; } else { result.height = 1; } } if (!me.hideCollapseTool) { if (isLeft || (isRight && me.isPlaceHolderCollapse())) { result.titlePosition = 1; } result.tools = [{ xtype: 'tool', type: 'expand-' + me.getOppositeDirection(direction), uiCls: ['top'], handler: me.toggleCollapse, scope: me }]; } result = new Ext.panel.Header(result); result.addClsWithUI(me.getHeaderCollapsedClasses(result)); return result; }, getHeaderCollapsedClasses: function(header) { var me = this, collapsedCls = me.collapsedCls, collapsedClasses; collapsedClasses = [ collapsedCls, collapsedCls + '-' + header.getDockName()]; if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) { collapsedClasses.push(collapsedCls + '-border-' + header.getDockName()); } return collapsedClasses; }, beginCollapse: function() { var me = this, lastBox = me.lastBox, rendered = me.rendered, collapseMemento = me.collapseMemento || (me.collapseMemento = new Ext.util.Memento(me)), sizeModel = me.getSizeModel(), header = me.header, reExpander; collapseMemento.capture(['height', 'minHeight', 'width', 'minWidth']); if (lastBox) { collapseMemento.capture(me.restoreDimension(), lastBox, 'last.'); } if (me.collapsedVertical()) { if (sizeModel.width.shrinkWrap) { me.width = rendered ? me.getWidth() : me.width || me.minWidth || 100; } delete me.height; me.minHeight = 0; } else if (me.collapsedHorizontal()) { if (sizeModel.height.shrinkWrap) { me.height = rendered ? me.getHeight() : me.height || me.minHeight || 100; } delete me.width; me.minWidth = 0; } if (me.ownerCt) { me.ownerCt.getLayout().beginCollapse(me); } if (!me.isPlaceHolderCollapse() && header !== false) { if (header === (reExpander = me.getReExpander())) { header.collapseImmune = true; header.getHierarchyState().collapseImmune = true; header.addClsWithUI(me.getHeaderCollapsedClasses(header)); if (header.rendered) { header.updateFrame(); } } else if (reExpander.el) { reExpander.el.show(); reExpander.hidden = false; } } if (me.resizer) { me.resizer.disable(); } }, beginExpand: function() { var me = this, lastBox = me.lastBox, collapseMemento = me.collapseMemento, restoreDimension = me.restoreDimension(), header = me.header, reExpander; if (collapseMemento) { collapseMemento.restore(['minHeight', 'minWidth', restoreDimension]); if (lastBox) { collapseMemento.restore(restoreDimension, true, lastBox, 'last.'); } } if (me.ownerCt) { me.ownerCt.getLayout().beginExpand(me); } if (!me.isPlaceHolderCollapse() && header !== false) { if (header === (reExpander = me.getReExpander())) { delete header.collapseImmune; delete header.getHierarchyState().collapseImmune; header.removeClsWithUI(me.getHeaderCollapsedClasses(header)); if (header.rendered) { header.expanding = true; header.updateFrame(); delete header.expanding; } } else { reExpander.hidden = true; reExpander.el.hide(); } } if (me.resizer) { me.resizer.enable(); } }, collapse: function(direction, animate) { var me = this, collapseDir = direction || me.collapseDirection, ownerCt = me.ownerCt, layout = me.ownerLayout; if (me.isCollapsingOrExpanding) { return me; } if (arguments.length < 2) { animate = me.animCollapse; } if (me.collapsed || me.fireEvent('beforecollapse', me, direction, animate) === false) { return me; } if (layout && layout.onBeforeComponentCollapse) { if (layout.onBeforeComponentCollapse(me) === false) { return me; } } if (ownerCt && me.isPlaceHolderCollapse()) { return me.placeholderCollapse(direction, animate); } me.collapsed = collapseDir; me.beginCollapse(); me.getHierarchyState().collapsed = true; me.fireHierarchyEvent('collapse'); return me.doCollapseExpand(1, animate); }, doCollapseExpand: function (flags, animate) { var me = this, originalAnimCollapse = me.animCollapse, ownerLayout = me.ownerLayout; me.animCollapse = animate; me.isCollapsingOrExpanding = flags; if (animate) { me.addCls(Ext.baseCSSPrefix + 'animating-size'); } if (ownerLayout && !animate) { ownerLayout.onContentChange(me); } else { me.updateLayout({ isRoot: true }); } me.animCollapse = originalAnimCollapse; return me; }, afterCollapse: function(animated) { var me = this, ownerLayout = me.ownerLayout; me.isCollapsingOrExpanding = 0; me.updateCollapseTool(); if (animated) { me.removeCls(Ext.baseCSSPrefix + 'animating-size'); } if (ownerLayout && animated) { ownerLayout.onContentChange(me); } me.setHiddenDocked(); me.fireEvent('collapse', me); }, setHiddenDocked: function(){ var me = this, toHide = me.hiddenOnCollapse, items = me.getDockedItems(), len = items.length, i = 0, item, reExpander; if (me.header !== false) { reExpander = me.getReExpander(); } toHide.add(me.body); for (; i < len; i++) { item = items[i]; if (item && item !== reExpander && item.el) { toHide.add(item.el); } } toHide.setStyle('visibility', 'hidden'); }, restoreHiddenDocked: function(){ var toShow = this.hiddenOnCollapse; toShow.setStyle('visibility', ''); toShow.clear(); }, getPlaceholder: function(direction) { var me = this, collapseDir = direction || me.collapseDirection, listeners = null, placeholder = me.placeholder, floatable = me.floatable, titleCollapse = me.titleCollapse; if (!placeholder) { if (floatable || (me.collapsible && titleCollapse)) { listeners = { click: { fn: (!titleCollapse && floatable) ? me.floatCollapsedPanel : me.toggleCollapse, element: 'el', scope: me } }; } me.placeholder = placeholder = Ext.widget(me.createReExpander(collapseDir, { id: me.id + '-placeholder', listeners: listeners })); } if (!placeholder.placeholderFor) { if (!placeholder.isComponent) { me.placeholder = placeholder = me.lookupComponent(placeholder); } Ext.applyIf(placeholder, { margins: me.margins, placeholderFor: me }); placeholder.addCls([Ext.baseCSSPrefix + 'region-collapsed-placeholder', Ext.baseCSSPrefix + 'region-collapsed-' + collapseDir + '-placeholder', me.collapsedCls]); } return placeholder; }, placeholderCollapse: function(direction, animate) { var me = this, ownerCt = me.ownerCt, collapseDir = direction || me.collapseDirection, floatCls = Ext.baseCSSPrefix + 'border-region-slide-in', placeholder = me.getPlaceholder(collapseDir), slideInDirection; me.isCollapsingOrExpanding = 1; me.setHiddenState(true); me.collapsed = collapseDir; if (placeholder.rendered) { if (placeholder.el.dom.parentNode !== me.el.dom.parentNode) { me.el.dom.parentNode.insertBefore(placeholder.el.dom, me.el.dom); } placeholder.hidden = false; placeholder.el.show(); ownerCt.updateLayout(); } else { ownerCt.insert(ownerCt.items.indexOf(me), placeholder); } if (me.rendered) { me.el.setVisibilityMode(me.placeholderCollapseHideMode); if (animate) { me.el.addCls(floatCls); placeholder.el.hide(); slideInDirection = me.convertCollapseDir(collapseDir); me.el.slideOut(slideInDirection, { preserveScroll: true, duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration), listeners: { afteranimate: function() { me.el.removeCls(floatCls); placeholder.el.show().setStyle('display', 'none').slideIn(slideInDirection, { easing: 'linear', duration: 100, listeners: { afteranimate: function() { placeholder.focus(); me.isCollapsingOrExpanding = 0; me.fireEvent('collapse', me); } } }); } } }); } else { me.el.hide(); me.isCollapsingOrExpanding = 0; me.fireEvent('collapse', me); } } else { me.isCollapsingOrExpanding = 0; if (!me.preventCollapseFire) { me.fireEvent('collapse', me); } } return me; }, floatCollapsedPanel: function() { var me = this, placeholder = me.placeholder, ps = placeholder.getSize(), myBox, floatCls = Ext.baseCSSPrefix + 'border-region-slide-in', collapsed = me.collapsed, layoutOwner = me.ownerCt || me, slideDirection; if (me.isSliding) { return; } if (me.el.hasCls(floatCls)) { me.slideOutFloatedPanel(); return; } me.isSliding = true; placeholder.el.hide(); placeholder.hidden = true; me.el.show(); me.setHiddenState(false); me.collapsed = false; layoutOwner.updateLayout(); myBox = me.getBox(false, true); placeholder.el.show(); placeholder.hidden = false; me.el.hide(); me.setHiddenState(true); me.collapsed = collapsed; layoutOwner.updateLayout(); me.slideOutTask = me.slideOutTask || new Ext.util.DelayedTask(me.slideOutFloatedPanel, me); placeholder.el.on('mouseleave', me.onMouseLeaveFloated, me); me.el.on('mouseleave', me.onMouseLeaveFloated, me); placeholder.el.on('mouseenter', me.onMouseEnterFloated, me); me.el.on('mouseenter', me.onMouseEnterFloated, me); me.el.addCls(floatCls); me.floated = true; if (me.collapseTool) { me.collapseTool.el.hide(); } switch (me.collapsed) { case 'top': me.setLocalXY(myBox.x, myBox.y + ps.height - 1); break; case 'right': me.setLocalXY(myBox.x - ps.width + 1, myBox.y); break; case 'bottom': me.setLocalXY(myBox.x, myBox.y - ps.height + 1); break; case 'left': me.setLocalXY(myBox.x + ps.width - 1, myBox.y); break; } slideDirection = me.convertCollapseDir(me.collapsed); me.floatedFromCollapse = me.collapsed; me.collapsed = false; me.setHiddenState(false); me.el.slideIn(slideDirection, { preserveScroll: true, duration: Ext.Number.from(me.animCollapse, Ext.fx.Anim.prototype.duration), listeners: { afteranimate: function() { me.isSliding = false; me.fireEvent('float', me); } } }); }, onMouseLeaveFloated: function(e) { this.slideOutTask.delay(500); }, onMouseEnterFloated: function(e) { this.slideOutTask.cancel(); }, isLayoutRoot: function() { if (this.floatedFromCollapse) { return true; } return this.callParent(); }, slideOutFloatedPanel: function(preventAnimate) { var me = this, compEl = me.el, collapseDirection; if (me.isSliding || me.isDestroyed) { return; } me.isSliding = true; me.floated = false; me.slideOutFloatedPanelBegin(); if (typeof me.collapsed == 'string') { collapseDirection = me.convertCollapseDir(me.collapsed); } compEl.slideOut(collapseDirection, { preserveScroll: true, duration: Ext.Number.from(me.animCollapse, Ext.fx.Anim.prototype.duration), autoEnd: preventAnimate === true, listeners: { afteranimate: function() { me.slideOutFloatedPanelEnd(); me.el.removeCls(Ext.baseCSSPrefix + 'border-region-slide-in'); } } }); }, slideOutFloatedPanelBegin: function() { var me = this, placeholderEl = me.placeholder.el, el = me.el; me.collapsed = me.floatedFromCollapse; me.setHiddenState(true); me.floatedFromCollapse = null; placeholderEl.un('mouseleave', me.onMouseLeaveFloated, me); el.un('mouseleave', me.onMouseLeaveFloated, me); placeholderEl.un('mouseenter', me.onMouseEnterFloated, me); el.un('mouseenter', me.onMouseEnterFloated, me); }, slideOutFloatedPanelEnd: function(suppressEvents) { var me = this; if (me.collapseTool) { me.collapseTool.el.show(); } me.slideOutTask.cancel(); me.isSliding = false; if (!suppressEvents) { me.fireEvent('unfloat', me); } }, expand: function(animate) { var me = this, layout = me.ownerLayout; if (me.isCollapsingOrExpanding) { return me; } if (!arguments.length) { animate = me.animCollapse; } if (!me.collapsed && !me.floatedFromCollapse) { return me; } if (me.fireEvent('beforeexpand', me, animate) === false) { return me; } if (layout && layout.onBeforeComponentExpand) { if (layout.onBeforeComponentExpand(me) === false) { return me; } } delete me.getHierarchyState().collapsed; if (me.isPlaceHolderCollapse()) { return me.placeholderExpand(animate); } me.restoreHiddenDocked(); me.beginExpand(); me.collapsed = false; return me.doCollapseExpand(2, animate); }, placeholderExpand: function(animate) { var me = this, collapseDir = me.collapsed, floatCls = Ext.baseCSSPrefix + 'border-region-slide-in', finalPos, floatedPos, center = me.ownerLayout ? me.ownerLayout.centerRegion: null; if (Ext.AbstractComponent.layoutSuspendCount) { animate = false; } if (me.floatedFromCollapse) { floatedPos = me.getPosition(true); me.slideOutFloatedPanelBegin(); me.slideOutFloatedPanelEnd(); me.floated = false; } if (animate) { Ext.suspendLayouts(); me.placeholder.hide(); me.el.show(); me.collapsed = false; me.setHiddenState(false); if (center && !floatedPos) { center.hidden = true; } Ext.resumeLayouts(true); center.hidden = false; me.el.addCls(floatCls); me.isCollapsingOrExpanding = 2; if (floatedPos) { finalPos = me.getXY(); me.setLocalXY(floatedPos[0], floatedPos[1]); me.setXY([finalPos[0], finalPos[1]], { duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration), listeners: { afteranimate: function() { me.el.removeCls(floatCls); me.isCollapsingOrExpanding = 0; me.fireEvent('expand', me); } } }); } else { me.el.hide(); me.placeholder.el.show(); me.placeholder.hidden = false; me.setHiddenState(false); me.el.slideIn(me.convertCollapseDir(collapseDir), { preserveScroll: true, duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration), listeners: { afteranimate: function() { me.el.removeCls(floatCls); me.placeholder.hide(); me.updateLayout(); me.isCollapsingOrExpanding = 0; me.fireEvent('expand', me); } } }); } } else { me.floated = me.collapsed = false; me.el.removeCls(floatCls); Ext.suspendLayouts(); me.placeholder.hide(); me.show(); Ext.resumeLayouts(true); me.fireEvent('expand', me); } return me; }, afterExpand: function(animated) { var me = this, ownerLayout = me.ownerLayout; me.isCollapsingOrExpanding = 0; me.updateCollapseTool(); if (animated) { me.removeCls(Ext.baseCSSPrefix + 'animating-size'); } if (ownerLayout && animated) { ownerLayout.onContentChange(me); } me.fireEvent('expand', me); me.fireHierarchyEvent('expand'); }, setBorder: function(border, targetEl) { if (targetEl) { return; } var me = this, header = me.header; if (!border) { border = 0; } else if (border === true) { border = '1px'; } else { border = me.unitizeBox(border); } if (header) { if (header.isHeader) { header.setBorder(border); } else { header.border = border; } } if (me.rendered && me.bodyBorder !== false) { me.body.setStyle('border-width', border); } me.updateLayout(); me.border = border; }, toggleCollapse: function() { return (this.collapsed || this.floatedFromCollapse) ? this.expand() : this.collapse(); }, getKeyMap : function() { return this.keyMap || (this.keyMap = new Ext.util.KeyMap(Ext.apply({ target: this.el }, this.keys))); }, initDraggable : function() { var me = this; if (me.simpleDrag) { me.initSimpleDraggable(); } else { me.dd = new Ext.panel.DD(me, Ext.isBoolean(me.draggable) ? null : me.draggable); } }, initSimpleDraggable: function() { var me = this, ddConfig, dd; if (!me.header) { me.updateHeader(true); } if (me.header) { ddConfig = Ext.applyIf({ el: me.el, delegate: '#' + Ext.escapeId(me.header.id) }, me.draggable); if (me.constrain || me.constrainHeader) { ddConfig.constrain = me.constrain; ddConfig.constrainDelegate = me.constrainHeader; ddConfig.constrainTo = me.constrainTo || me.container; } dd = me.dd = new Ext.util.ComponentDragger(me, ddConfig); me.relayEvents(dd, ['dragstart', 'drag', 'dragend']); if (me.maximized) { dd.disable(); } } }, ghostTools : function() { var tools = [], header = this.header, headerTools = header ? header.query('tool[hidden=false]') : [], t, tLen, tool; if (headerTools.length) { t = 0; tLen = headerTools.length; for (; t < tLen; t++) { tool = headerTools[t]; tools.push({ type: tool.type }); } } else { tools = [{ type: 'placeholder' }]; } return tools; }, ghost: function(cls) { var me = this, ghostPanel = me.ghostPanel, box = me.getBox(), header = me.header, ghostHeader, tools, i; if (!ghostPanel) { me.ghostPanel = ghostPanel = Ext.widget(me.createGhost(cls)); } else { ghostPanel.el.show(); } ghostPanel.setHiddenState(false); ghostPanel.floatParent = me.floatParent; ghostPanel.toFront(); if (header && !me.preventHeader) { ghostHeader = ghostPanel.header; ghostHeader.suspendLayouts(); tools = ghostHeader.query('tool'); for (i = tools.length; i--;) { ghostHeader.remove(tools[i]); } ghostPanel.addTool(me.ghostTools()); ghostPanel.setTitle(me.title); ghostHeader.setTitlePosition(header.titlePosition); if (me.iconCls) { ghostPanel.setIconCls(me.iconCls); } else if (me.icon) { ghostPanel.setIcon(me.icon); } else if (me.glyph) { ghostPanel.setGlyph(me.glyph); } ghostHeader.addCls(Ext.baseCSSPrefix + 'header-ghost'); ghostHeader.resumeLayouts(); } ghostPanel.setPagePosition(box.x, box.y); ghostPanel.setSize(box.width, box.height); me.el.hide(); return ghostPanel; }, createGhost: function(cls) { var me = this, header = me.header, frame = me.frame && !me.alwaysFramed; return { xtype: 'panel', hidden: false, header: header ? { titleAlign: header.titleAlign } : null, ui: frame ? me.ui.replace(/-framed$/, '') : me.ui, id: me.id + '-ghost', renderTo: Ext.getBody(), resizable: false, floating: { shadow: false }, frame: frame, alwaysFramed: me.alwaysFramed, overlapHeader: me.overlapHeader, headerPosition: me.headerPosition, baseCls: me.baseCls, cls: me.baseCls + '-ghost ' + (cls || '') }; }, unghost: function(show, matchPosition) { var me = this, ghostPanel = me.ghostPanel; if (!ghostPanel) { return; } if (show !== false) { me.el.show(); if (matchPosition !== false) { me.setPagePosition(ghostPanel.getXY()); if (me.hideMode == 'offsets') { delete me.el.hideModeStyles; } } Ext.defer(me.focus, 10, me); } ghostPanel.el.hide(); ghostPanel.setHiddenState(true); }, beginDrag: function() { if (this.floatingDescendants) { this.floatingDescendants.hide(); } }, endDrag: function() { if (this.floatingDescendants) { this.floatingDescendants.show(); } }, initResizable: function() { this.callParent(arguments); if (this.collapsed) { this.resizer.disable(); } }, convertCollapseDir: function(collapseDir) { return collapseDir.substr(0, 1); } }, function() { this.prototype.animCollapse = Ext.enableFx; }); Ext.define('Ext.tip.Tip', { extend: Ext.panel.Panel , alternateClassName: 'Ext.Tip', minWidth : 40, maxWidth : 500, shadow : "sides", defaultAlign : "tl-bl?", constrainPosition : true, autoRender: true, hidden: true, baseCls: Ext.baseCSSPrefix + 'tip', floating: { shadow: true, shim: true }, focusOnToFront: false, closeAction: 'hide', alwaysFramed: true, frameHeader: false, initComponent: function() { var me = this; me.floating = Ext.apply( {}, { shadow: me.shadow, constrain: me.constrainPosition }, me.self.prototype.floating); me.callParent(arguments); me.constrain = me.constrain || me.constrainPosition; }, showAt : function(xy){ var me = this; this.callParent(arguments); if (me.isVisible()) { me.setPagePosition(xy[0], xy[1]); if (me.constrainPosition || me.constrain) { me.doConstrain(); } me.toFront(true); } }, initDraggable : function(){ var me = this; me.draggable = { el: me.getDragEl(), delegate: me.header.el, constrain: me, constrainTo: me.el.dom.parentNode }; Ext.Component.prototype.initDraggable.call(me); }, ghost: undefined, unghost: undefined }); Ext.define('Ext.tip.ToolTip', { extend: Ext.tip.Tip , alias: 'widget.tooltip', alternateClassName: 'Ext.ToolTip', autoHide: true, showDelay: 500, hideDelay: 200, dismissDelay: 5000, trackMouse: false, anchorToTarget: true, anchorOffset: 0, targetCounter: 0, quickShowInterval: 250, ariaRole: 'tooltip', initComponent: function() { var me = this; me.callParent(arguments); me.lastActive = new Date(); me.setTarget(me.target); me.origAnchor = me.anchor; }, onRender: function(ct, position) { var me = this; me.callParent(arguments); me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition(); me.anchorEl = me.el.createChild({ role: 'presentation', cls: Ext.baseCSSPrefix + 'tip-anchor ' + me.anchorCls }); }, setTarget: function(target) { var me = this, t = Ext.get(target), tg; if (me.target) { tg = Ext.get(me.target); me.mun(tg, 'mouseover', me.onTargetOver, me); me.mun(tg, 'mouseout', me.onTargetOut, me); me.mun(tg, 'mousemove', me.onMouseMove, me); } me.target = t; if (t) { me.mon(t, { freezeEvent: true, mouseover: me.onTargetOver, mouseout: me.onTargetOut, mousemove: me.onMouseMove, scope: me }); } if (me.anchor) { me.anchorTarget = me.target; } }, onMouseMove: function(e) { var me = this, t = me.delegate ? e.getTarget(me.delegate) : me.triggerElement = true, xy; if (t) { me.targetXY = e.getXY(); if (t === me.triggerElement) { if (!me.hidden && me.trackMouse) { xy = me.getTargetXY(); if (me.constrainPosition) { xy = me.el.adjustForConstraints(xy, me.el.parent()); } me.setPagePosition(xy); } } else { me.hide(); me.lastActive = new Date(0); me.onTargetOver(e); } } else if ((!me.closable && me.isVisible()) && me.autoHide !== false) { me.hide(); } }, getTargetXY: function() { var me = this, mouseOffset, offsets, xy, dw, dh, de, bd, scrollX, scrollY, axy, sz, constrainPosition; if (me.delegate) { me.anchorTarget = me.triggerElement; } if (me.anchor) { me.targetCounter++; offsets = me.getOffsets(); xy = (me.anchorToTarget && !me.trackMouse) ? me.getAlignToXY(me.anchorTarget, me.getAnchorAlign()) : me.targetXY; dw = Ext.Element.getViewWidth() - 5; dh = Ext.Element.getViewHeight() - 5; de = document.documentElement; bd = document.body; scrollX = (de.scrollLeft || bd.scrollLeft || 0) + 5; scrollY = (de.scrollTop || bd.scrollTop || 0) + 5; axy = [xy[0] + offsets[0], xy[1] + offsets[1]]; sz = me.getSize(); constrainPosition = me.constrainPosition; me.anchorEl.removeCls(me.anchorCls); if (me.targetCounter < 2 && constrainPosition) { if (axy[0] < scrollX) { if (me.anchorToTarget) { me.defaultAlign = 'l-r'; if (me.mouseOffset) { me.mouseOffset[0] *= -1; } } me.anchor = 'left'; return me.getTargetXY(); } if (axy[0] + sz.width > dw) { if (me.anchorToTarget) { me.defaultAlign = 'r-l'; if (me.mouseOffset) { me.mouseOffset[0] *= -1; } } me.anchor = 'right'; return me.getTargetXY(); } if (axy[1] < scrollY) { if (me.anchorToTarget) { me.defaultAlign = 't-b'; if (me.mouseOffset) { me.mouseOffset[1] *= -1; } } me.anchor = 'top'; return me.getTargetXY(); } if (axy[1] + sz.height > dh) { if (me.anchorToTarget) { me.defaultAlign = 'b-t'; if (me.mouseOffset) { me.mouseOffset[1] *= -1; } } me.anchor = 'bottom'; return me.getTargetXY(); } } me.anchorCls = Ext.baseCSSPrefix + 'tip-anchor-' + me.getAnchorPosition(); me.anchorEl.addCls(me.anchorCls); me.targetCounter = 0; return axy; } else { mouseOffset = me.getMouseOffset(); return (me.targetXY) ? [me.targetXY[0] + mouseOffset[0], me.targetXY[1] + mouseOffset[1]] : mouseOffset; } }, getMouseOffset: function() { var me = this, offset = me.anchor ? [0, 0] : [15, 18]; if (me.mouseOffset) { offset[0] += me.mouseOffset[0]; offset[1] += me.mouseOffset[1]; } return offset; }, getAnchorPosition: function() { var me = this, m; if (me.anchor) { me.tipAnchor = me.anchor.charAt(0); } else { m = me.defaultAlign.match(/^([a-z]+)-([a-z]+)(\?)?$/); me.tipAnchor = m[1].charAt(0); } switch (me.tipAnchor) { case 't': return 'top'; case 'b': return 'bottom'; case 'r': return 'right'; } return 'left'; }, getAnchorAlign: function() { switch (this.anchor) { case 'top': return 'tl-bl'; case 'left': return 'tl-tr'; case 'right': return 'tr-tl'; default: return 'bl-tl'; } }, getOffsets: function() { var me = this, mouseOffset, offsets, ap = me.getAnchorPosition().charAt(0); if (me.anchorToTarget && !me.trackMouse) { switch (ap) { case 't': offsets = [0, 9]; break; case 'b': offsets = [0, -13]; break; case 'r': offsets = [ - 13, 0]; break; default: offsets = [9, 0]; break; } } else { switch (ap) { case 't': offsets = [ - 15 - me.anchorOffset, 30]; break; case 'b': offsets = [ - 19 - me.anchorOffset, -13 - me.el.dom.offsetHeight]; break; case 'r': offsets = [ - 15 - me.el.dom.offsetWidth, -13 - me.anchorOffset]; break; default: offsets = [25, -13 - me.anchorOffset]; break; } } mouseOffset = me.getMouseOffset(); offsets[0] += mouseOffset[0]; offsets[1] += mouseOffset[1]; return offsets; }, onTargetOver: function(e) { var me = this, delegate = me.delegate, t; if (me.disabled || e.within(me.target.dom, true)) { return; } t = delegate ? e.getTarget(delegate) : true; if (t) { me.triggerElement = t; me.triggerEvent = e; me.clearTimer('hide'); me.targetXY = e.getXY(); me.delayShow(); } }, delayShow: function() { var me = this; if (me.hidden && !me.showTimer) { if (Ext.Date.getElapsed(me.lastActive) < me.quickShowInterval) { me.show(); } else { me.showTimer = Ext.defer(me.showFromDelay, me.showDelay, me); } } else if (!me.hidden && me.autoHide !== false) { me.show(); } }, showFromDelay: function(){ this.fromDelayShow = true; this.show(); delete this.fromDelayShow; }, onShowVeto: function(){ this.callParent(); delete this.triggerElement; this.clearTimer('show'); }, onTargetOut: function(e) { var me = this, triggerEl = me.triggerElement, target = triggerEl === true ? me.target : triggerEl; if (me.disabled || !triggerEl || e.within(target, true)) { return; } if (me.showTimer) { me.clearTimer('show'); me.triggerElement = null; } if (me.autoHide !== false) { me.delayHide(); } }, delayHide: function() { var me = this; if (!me.hidden && !me.hideTimer) { me.hideTimer = Ext.defer(me.hide, me.hideDelay, me); } }, hide: function() { var me = this; me.clearTimer('dismiss'); me.lastActive = new Date(); if (me.anchorEl) { me.anchorEl.hide(); } me.callParent(arguments); delete me.triggerElement; }, show: function() { var me = this; this.callParent(); if (this.hidden === false) { me.setPagePosition(-10000, -10000); if (me.anchor) { me.anchor = me.origAnchor; } if (!me.calledFromShowAt) { me.showAt(me.getTargetXY()); } if (me.anchor) { me.syncAnchor(); me.anchorEl.show(); } else { me.anchorEl.hide(); } } }, showAt: function(xy) { var me = this; me.lastActive = new Date(); me.clearTimers(); me.calledFromShowAt = true; if (!me.isVisible()) { this.callParent(arguments); } if (me.isVisible()) { me.setPagePosition(xy[0], xy[1]); if (me.constrainPosition || me.constrain) { me.doConstrain(); } me.toFront(true); me.el.sync(true); if (me.dismissDelay && me.autoHide !== false) { me.dismissTimer = Ext.defer(me.hide, me.dismissDelay, me); } if (me.anchor) { me.syncAnchor(); if (!me.anchorEl.isVisible()) { me.anchorEl.show(); } } else { me.anchorEl.hide(); } } delete me.calledFromShowAt; }, syncAnchor: function() { var me = this, anchorPos, targetPos, offset; switch (me.tipAnchor.charAt(0)) { case 't': anchorPos = 'b'; targetPos = 'tl'; offset = [20 + me.anchorOffset, 1]; break; case 'r': anchorPos = 'l'; targetPos = 'tr'; offset = [ - 1, 12 + me.anchorOffset]; break; case 'b': anchorPos = 't'; targetPos = 'bl'; offset = [20 + me.anchorOffset, -1]; break; default: anchorPos = 'r'; targetPos = 'tl'; offset = [1, 12 + me.anchorOffset]; break; } me.anchorEl.alignTo(me.el, anchorPos + '-' + targetPos, offset); me.anchorEl.setStyle('z-index', parseInt(me.el.getZIndex(), 10) || 0 + 1).setVisibilityMode(Ext.Element.DISPLAY); }, setPagePosition: function(x, y) { var me = this; me.callParent(arguments); if (me.anchor) { me.syncAnchor(); } }, _timerNames: {}, clearTimer: function (name) { var me = this, names = me._timerNames, propName = names[name] || (names[name] = name + 'Timer'), timer = me[propName]; if (timer) { clearTimeout(timer); me[propName] = null; } }, clearTimers: function() { var me = this; me.clearTimer('show'); me.clearTimer('dismiss'); me.clearTimer('hide'); }, onShow: function() { var me = this; me.callParent(); me.mon(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me); }, onHide: function() { var me = this; me.callParent(); me.mun(Ext.getDoc(), 'mousedown', me.onDocMouseDown, me); }, onDocMouseDown: function(e) { var me = this; if (!me.closable && !e.within(me.el.dom)) { me.disable(); Ext.defer(me.doEnable, 100, me); } }, doEnable: function() { if (!this.isDestroyed) { this.enable(); } }, onDisable: function() { this.callParent(); this.clearTimers(); this.hide(); }, beforeDestroy: function() { var me = this; me.clearTimers(); Ext.destroy(me.anchorEl); delete me.anchorEl; delete me.target; delete me.anchorTarget; delete me.triggerElement; me.callParent(); }, onDestroy: function() { Ext.getDoc().un('mousedown', this.onDocMouseDown, this); this.callParent(); } }); Ext.define('Ext.tip.QuickTip', { extend: Ext.tip.ToolTip , alias: 'widget.quicktip', alternateClassName: 'Ext.QuickTip', interceptTitles : false, title: ' ', tagConfig : { namespace : 'data-', attribute : 'qtip', width : 'qwidth', target : 'target', title : 'qtitle', hide : 'hide', cls : 'qclass', align : 'qalign', anchor : 'anchor', showDelay: 'qshowDelay' }, shrinkWrapDock: true, initComponent : function(){ var me = this; me.target = me.target || Ext.getDoc(); me.targets = me.targets || {}; me.callParent(); }, register : function(config){ var configs = Ext.isArray(config) ? config : arguments, i = 0, len = configs.length, target, j, targetLen; for (; i < len; i++) { config = configs[i]; target = config.target; if (target) { if (Ext.isArray(target)) { for (j = 0, targetLen = target.length; j < targetLen; j++) { this.targets[Ext.id(target[j])] = config; } } else{ this.targets[Ext.id(target)] = config; } } } }, unregister : function(el){ delete this.targets[Ext.id(el)]; }, cancelShow: function(el){ var me = this, activeTarget = me.activeTarget; el = Ext.get(el).dom; if (me.isVisible()) { if (activeTarget && activeTarget.el == el) { me.hide(); } } else if (activeTarget && activeTarget.el == el) { me.clearTimer('show'); } }, getTipCfg: function(e) { var t = e.getTarget(), titleText = t.title, cfg; if (this.interceptTitles && titleText && Ext.isString(titleText)) { t.qtip = titleText; t.removeAttribute("title"); e.preventDefault(); return { text: titleText }; } else { cfg = this.tagConfig; t = e.getTarget('[' + cfg.namespace + cfg.attribute + ']'); if (t) { return { target: t, text: t.getAttribute(cfg.namespace + cfg.attribute) }; } } }, onTargetOver : function(e){ var me = this, target = e.getTarget(me.delegate), hasShowDelay, delay, elTarget, cfg, ns, tipConfig, autoHide, targets, targetEl, value, key; if (me.disabled) { return; } me.targetXY = e.getXY(); if(!target || target.nodeType !== 1 || target == document.documentElement || target == document.body){ return; } if (me.activeTarget && ((target == me.activeTarget.el) || Ext.fly(me.activeTarget.el).contains(target))) { if (me.targetTextEmpty()) { me.onShowVeto(); delete me.activeTarget; } else { me.clearTimer('hide'); me.show(); } return; } if (target) { targets = me.targets; for (key in targets) { if (targets.hasOwnProperty(key)) { value = targets[key]; targetEl = Ext.fly(value.target); if (targetEl && (targetEl.dom === target || targetEl.contains(target))) { elTarget = targetEl.dom; break; } } } if (elTarget) { me.activeTarget = me.targets[elTarget.id]; me.activeTarget.el = target; me.anchor = me.activeTarget.anchor; if (me.anchor) { me.anchorTarget = target; } hasShowDelay = parseInt(me.activeTarget.showDelay, 10); if (hasShowDelay) { delay = me.showDelay; me.showDelay = hasShowDelay; } me.delayShow(); if (hasShowDelay) { me.showDelay = delay; } return; } } elTarget = Ext.fly(target, '_quicktip-target'); cfg = me.tagConfig; ns = cfg.namespace; tipConfig = me.getTipCfg(e); if (tipConfig) { if (tipConfig.target) { target = tipConfig.target; elTarget = Ext.fly(target, '_quicktip-target'); } autoHide = elTarget.getAttribute(ns + cfg.hide); me.activeTarget = { el: target, text: tipConfig.text, width: +elTarget.getAttribute(ns + cfg.width) || null, autoHide: autoHide != "user" && autoHide !== 'false', title: elTarget.getAttribute(ns + cfg.title), cls: elTarget.getAttribute(ns + cfg.cls), align: elTarget.getAttribute(ns + cfg.align), showDelay: parseInt(elTarget.getAttribute(ns + cfg.showDelay), 10) }; me.anchor = elTarget.getAttribute(ns + cfg.anchor); if (me.anchor) { me.anchorTarget = target; } hasShowDelay = parseInt(me.activeTarget.showDelay, 10); if (hasShowDelay) { delay = me.showDelay; me.showDelay = hasShowDelay; } me.delayShow(); if (hasShowDelay) { me.showDelay = delay; } } }, onTargetOut : function(e){ var me = this, active = me.activeTarget, hasHideDelay, delay; if (active && e.within(me.activeTarget.el) && !me.getTipCfg(e)) { return; } me.clearTimer('show'); delete me.activeTarget; if (me.autoHide !== false) { hasHideDelay = active && parseInt(active.hideDelay, 10); if (hasHideDelay) { delay = me.hideDelay; me.hideDelay = hasHideDelay; } me.delayHide(); if (hasHideDelay) { me.hideDelay = delay; } } }, targetTextEmpty: function(){ var me = this, target = me.activeTarget, cfg = me.tagConfig, el, text; if (target) { el = target.el; if (el) { text = el.getAttribute(cfg.namespace + cfg.attribute); if (!text && !me.targets[Ext.id(target.target)]) { return true; } } } return false; }, show: function(){ var me = this, fromDelay = me.fromDelayShow; if (fromDelay && me.targetTextEmpty()) { me.onShowVeto(); delete me.activeTarget; return; } me.callParent(arguments); }, showAt : function(xy){ var me = this, target = me.activeTarget, header = me.header, dismiss, cls; if (target) { if (!me.rendered) { me.render(Ext.getBody()); me.activeTarget = target; } me.suspendLayouts(); if (target.title) { me.setTitle(target.title); header.show(); } else if (header) { header.hide(); } me.update(target.text); me.autoHide = target.autoHide; dismiss = target.dismissDelay; me.dismissDelay = Ext.isNumber(dismiss) ? dismiss : me.dismissDelay; if (target.mouseOffset) { xy[0] += target.mouseOffset[0]; xy[1] += target.mouseOffset[1]; } cls = me.lastCls; if (cls) { me.removeCls(cls); delete me.lastCls; } cls = target.cls; if (cls) { me.addCls(cls); me.lastCls = cls; } me.setWidth(target.width); if (me.anchor) { me.constrainPosition = false; } else if (target.align) { xy = me.getAlignToXY(target.el, target.align); me.constrainPosition = false; }else{ me.constrainPosition = true; } me.resumeLayouts(true); } me.callParent([xy]); }, hide: function(){ delete this.activeTarget; this.callParent(); } }); Ext.define('Ext.tip.QuickTipManager', { singleton: true, alternateClassName: 'Ext.QuickTips', disabled: false, init : function (autoRender, config) { var me = this; if (!me.tip) { if (!Ext.isReady) { Ext.onReady(function(){ Ext.tip.QuickTipManager.init(autoRender, config); }); return false; } var tipConfig = Ext.apply({ disabled: me.disabled, id: 'ext-quicktips-tip' }, config), className = tipConfig.className, xtype = tipConfig.xtype; if (className) { delete tipConfig.className; } else if (xtype) { className = 'widget.' + xtype; delete tipConfig.xtype; } if (autoRender !== false) { tipConfig.renderTo = document.body; } me.tip = Ext.create(className || 'Ext.tip.QuickTip', tipConfig); Ext.quickTipsActive = true; } }, destroy: function() { Ext.destroy(this.tip); this.tip = undefined; }, ddDisable : function() { var me = this, tip = me.tip; if (tip && !me.disabled) { tip.disable(); } }, ddEnable : function() { var me = this, tip = me.tip; if (tip && !me.disabled) { tip.enable(); } }, enable : function(){ var me = this, tip = me.tip; if (tip) { tip.enable(); } me.disabled = false; }, disable : function(){ var me = this, tip = me.tip; if(tip){ tip.disable(); } me.disabled = true; }, isEnabled : function(){ var tip = this.tip; return tip !== undefined && !tip.disabled; }, getQuickTip : function(){ return this.tip; }, register : function(){ var tip = this.tip; tip.register.apply(tip, arguments); }, unregister : function(){ var tip = this.tip; tip.unregister.apply(tip, arguments); }, tips : function(){ var tip = this.tip; tip.register.apply(tip, arguments); } }); Ext.define('Ext.app.Application', { extend: Ext.app.Controller , scope: undefined, enableQuickTips: true, appFolder: 'app', appProperty: 'app', namespaces: [], autoCreateViewport: false, paths: null, onClassExtended: function(cls, data, hooks) { var Controller = Ext.app.Controller, proto = cls.prototype, requires = [], onBeforeClassCreated, paths, namespace, ns, appFolder; namespace = data.name || cls.superclass.name; appFolder = data.appFolder || cls.superclass.appFolder; if (namespace) { data.$namespace = namespace; Ext.app.addNamespaces(namespace); } if (data.namespaces) { Ext.app.addNamespaces(data.namespaces); } if (!data['paths processed']) { if (namespace && appFolder) { Ext.Loader.setPath(namespace, appFolder); } paths = data.paths; if (paths) { for (ns in paths) { if (paths.hasOwnProperty(ns)) { Ext.Loader.setPath(ns, paths[ns]); } } } } else { delete data['paths processed']; } if (data.autoCreateViewport) { Controller.processDependencies(proto, requires, namespace, 'view', ['Viewport']); } if (requires.length) { onBeforeClassCreated = hooks.onBeforeCreated; hooks.onBeforeCreated = function(cls, data) { var args = Ext.Array.clone(arguments); Ext.require(requires, function () { return onBeforeClassCreated.apply(this, args); }); }; } }, constructor: function(config) { var me = this; me.callParent(arguments); me.doInit(me); me.initNamespace(); me.initControllers(); me.onBeforeLaunch(); me.finishInitControllers(); }, initNamespace: function() { var me = this, appProperty = me.appProperty, ns; ns = Ext.namespace(me.name); if (ns) { ns.getApplication = function() { return me; }; if (appProperty) { if (!ns[appProperty]) { ns[appProperty] = me; } } } }, initControllers: function() { var me = this, controllers = Ext.Array.from(me.controllers); me.controllers = new Ext.util.MixedCollection(); for (var i = 0, ln = controllers.length; i < ln; i++) { me.getController(controllers[i]); } }, finishInitControllers: function() { var me = this, controllers, i, l; controllers = me.controllers.getRange(); for (i = 0, l = controllers.length; i < l; i++) { controllers[i].finishInit(me); } }, launch: Ext.emptyFn, onBeforeLaunch: function() { var me = this, controllers, c, cLen, controller; if (me.enableQuickTips) { me.initQuickTips(); } if (me.autoCreateViewport) { me.initViewport(); } me.launch.call(me.scope || me); me.launched = true; me.fireEvent('launch', me); controllers = me.controllers.items; cLen = controllers.length; for (c = 0; c < cLen; c++) { controller = controllers[c]; controller.onLaunch(me); } }, getModuleClassName: function(name, kind) { return Ext.app.Controller.getFullName(name, kind, this.name).absoluteName; }, initQuickTips: function() { Ext.tip.QuickTipManager.init(); }, initViewport: function() { var viewport = this.getView('Viewport'); if (viewport) { viewport.create(); } }, getController: function(name) { var me = this, controllers = me.controllers, className, controller; controller = controllers.get(name); if (!controller) { className = me.getModuleClassName(name, 'controller'); controller = Ext.create(className, { application: me, id: name }); controllers.add(controller); if (me._initialized) { controller.doInit(me); } } return controller; }, getApplication: function() { return this; } }); Ext.define('Ext.app.domain.Controller', { extend: Ext.app.EventDomain , singleton: true, type: 'controller', idProperty: 'id', constructor: function() { var me = this; me.callParent(); me.monitor(Ext.app.Controller); } }); Ext.define('Ext.direct.Provider', { alias: 'direct.provider', mixins: { observable: Ext.util.Observable }, isProvider: true, constructor: function(config) { var me = this; Ext.apply(me, config); Ext.applyIf(me, { id: Ext.id(null, 'provider-') }); me.addEvents( 'connect', 'disconnect', 'data', 'exception' ); me.mixins.observable.constructor.call(me, config); }, isConnected: function() { return false; }, connect: Ext.emptyFn, disconnect: Ext.emptyFn }); Ext.define('Ext.app.domain.Direct', { extend: Ext.app.EventDomain , singleton: true, type: 'direct', idProperty: 'id', constructor: function() { var me = this; me.callParent(); me.monitor(Ext.direct.Provider); } }); Ext.define('Ext.button.Split', { alias: 'widget.splitbutton', extend: Ext.button.Button , alternateClassName: 'Ext.SplitButton', arrowCls : 'split', split : true, initComponent : function(){ this.callParent(); this.addEvents("arrowclick"); }, setArrowHandler : function(handler, scope){ this.arrowHandler = handler; this.scope = scope; }, onClick : function(e) { var me = this; me.doPreventDefault(e); if (!me.disabled) { if (me.overMenuTrigger) { e.preventDefault(); me.maybeShowMenu(); me.fireEvent("arrowclick", me, e); if (me.arrowHandler) { me.arrowHandler.call(me.scope || me, me, e); } } else { me.doToggle(); me.fireHandler(e); } } } }); Ext.define('Ext.button.Cycle', { alias: 'widget.cycle', extend: Ext.button.Split , alternateClassName: 'Ext.CycleButton', getButtonText: function(item) { var me = this, text = ''; if (item && me.showText === true) { if (me.prependText) { text += me.prependText; } text += item.text; return text; } return me.text; }, setActiveItem: function(item, suppressEvent) { var me = this; if (!Ext.isObject(item)) { item = me.menu.getComponent(item); } if (item) { if (!me.rendered) { me.text = me.getButtonText(item); me.iconCls = item.iconCls; me.glyph = item.glyph; } else { me.setText(me.getButtonText(item)); me.setIconCls(item.iconCls); me.setGlyph(item.glyph); } me.activeItem = item; if (!item.checked) { item.setChecked(true, false); } if (me.forceIcon) { me.setIconCls(me.forceIcon); } if (me.forceGlyph) { me.setGlyph(me.forceGlyph); } if (!suppressEvent) { me.fireEvent('change', me, item); } } }, getActiveItem: function() { return this.activeItem; }, initComponent: function() { var me = this, checked = 0, items, i, iLen, item; me.addEvents( "change" ); if (me.changeHandler) { me.on('change', me.changeHandler, me.scope || me); delete me.changeHandler; } items = (me.menu.items || []).concat(me.items || []); me.menu = Ext.applyIf({ cls: Ext.baseCSSPrefix + 'cycle-menu', items: [] }, me.menu); iLen = items.length; for (i = 0; i < iLen; i++) { item = items[i]; item = Ext.applyIf({ group : me.id, itemIndex : i, checkHandler : me.checkHandler, scope : me, checked : item.checked || false }, item); me.menu.items.push(item); if (item.checked) { checked = i; } } me.itemCount = me.menu.items.length; me.callParent(arguments); me.on('click', me.toggleSelected, me); me.setActiveItem(checked, me); if (me.width && me.showText) { me.addCls(Ext.baseCSSPrefix + 'cycle-fixed-width'); } }, checkHandler: function(item, pressed) { if (pressed) { this.setActiveItem(item); } }, toggleSelected: function() { var me = this, m = me.menu, checkItem; checkItem = me.activeItem.next(':not([disabled])') || m.items.getAt(0); checkItem.setChecked(true); } }); Ext.define('Ext.chart.Callout', { constructor: function(config) { if (config.callouts) { config.callouts.styles = Ext.applyIf(config.callouts.styles || {}, { color: "#000", font: "11px Helvetica, sans-serif" }); this.callouts = Ext.apply(this.callouts || {}, config.callouts); this.calloutsArray = []; } }, renderCallouts: function() { if (!this.callouts) { return; } var me = this, items = me.items, animate = me.chart.animate, config = me.callouts, styles = config.styles, group = me.calloutsArray, store = me.chart.getChartStore(), len = store.getCount(), ratio = items.length / len, previouslyPlacedCallouts = [], i, count, j, p, item, label, storeItem, display; for (i = 0, count = 0; i < len; i++) { for (j = 0; j < ratio; j++) { item = items[count]; label = group[count]; storeItem = store.getAt(i); display = (!config.filter || config.filter(storeItem)); if (!display && !label) { count++; continue; } if (!label) { group[count] = label = me.onCreateCallout(storeItem, item, i, display, j, count); } for (p in label) { if (label[p] && label[p].setAttributes) { label[p].setAttributes(styles, true); } } if (!display) { for (p in label) { if (label[p]) { if (label[p].setAttributes) { label[p].setAttributes({ hidden: true }, true); } else if(label[p].setVisible) { label[p].setVisible(false); } } } } if (config && config.renderer) { config.renderer(label, storeItem); } me.onPlaceCallout(label, storeItem, item, i, display, animate, j, count, previouslyPlacedCallouts); previouslyPlacedCallouts.push(label); count++; } } this.hideCallouts(count); }, onCreateCallout: function(storeItem, item, i, display) { var me = this, group = me.calloutsGroup, config = me.callouts, styles = (config ? config.styles : undefined), width = (styles ? styles.width : 0), height = (styles ? styles.height : 0), chart = me.chart, surface = chart.surface, calloutObj = { lines: false }; calloutObj.lines = surface.add(Ext.apply({}, { type: 'path', path: 'M0,0', stroke: me.getLegendColor() || '#555' }, styles)); if (config.items) { calloutObj.panel = new Ext.Panel({ style: "position: absolute;", width: width, height: height, items: config.items, renderTo: chart.el }); } return calloutObj; }, hideCallouts: function(index) { var calloutsArray = this.calloutsArray, len = calloutsArray.length, co, p; while (len-->index) { co = calloutsArray[len]; for (p in co) { if (co[p]) { co[p].hide(true); } } } } }); Ext.define('Ext.draw.CompositeSprite', { extend: Ext.util.MixedCollection , mixins: { animate: Ext.util.Animate }, autoDestroy: false, isCompositeSprite: true, constructor: function(config) { var me = this; config = config || {}; Ext.apply(me, config); me.addEvents( 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'click' ); me.id = Ext.id(null, 'ext-sprite-group-'); me.callParent(); }, onClick: function(e) { this.fireEvent('click', e); }, onMouseUp: function(e) { this.fireEvent('mouseup', e); }, onMouseDown: function(e) { this.fireEvent('mousedown', e); }, onMouseOver: function(e) { this.fireEvent('mouseover', e); }, onMouseOut: function(e) { this.fireEvent('mouseout', e); }, attachEvents: function(o) { var me = this; o.on({ scope: me, mousedown: me.onMouseDown, mouseup: me.onMouseUp, mouseover: me.onMouseOver, mouseout: me.onMouseOut, click: me.onClick }); }, add: function(key, o) { var result = this.callParent(arguments); this.attachEvents(result); return result; }, insert: function(index, key, o) { return this.callParent(arguments); }, remove: function(o) { var me = this; o.un({ scope: me, mousedown: me.onMouseDown, mouseup: me.onMouseUp, mouseover: me.onMouseOver, mouseout: me.onMouseOut, click: me.onClick }); return me.callParent(arguments); }, getBBox: function() { var i = 0, sprite, bb, items = this.items, len = this.length, infinity = Infinity, minX = infinity, maxHeight = -infinity, minY = infinity, maxWidth = -infinity, maxWidthBBox, maxHeightBBox; for (; i < len; i++) { sprite = items[i]; if (sprite.el && ! sprite.bboxExcluded) { bb = sprite.getBBox(); minX = Math.min(minX, bb.x); minY = Math.min(minY, bb.y); maxHeight = Math.max(maxHeight, bb.height + bb.y); maxWidth = Math.max(maxWidth, bb.width + bb.x); } } return { x: minX, y: minY, height: maxHeight - minY, width: maxWidth - minX }; }, setAttributes: function(attrs, redraw) { var i = 0, items = this.items, len = this.length; for (; i < len; i++) { items[i].setAttributes(attrs, redraw); } return this; }, hide: function(redraw) { var i = 0, items = this.items, len = this.length; for (; i < len; i++) { items[i].hide(redraw); } return this; }, show: function(redraw) { var i = 0, items = this.items, len = this.length; for (; i < len; i++) { items[i].show(redraw); } return this; }, redraw: function() { var me = this, i = 0, items = me.items, surface = me.getSurface(), len = me.length; if (surface) { for (; i < len; i++) { surface.renderItem(items[i]); } } return me; }, setStyle: function(obj) { var i = 0, items = this.items, len = this.length, item, el; for (; i < len; i++) { item = items[i]; el = item.el; if (el) { el.setStyle(obj); } } }, addCls: function(obj) { var i = 0, items = this.items, surface = this.getSurface(), len = this.length; if (surface) { for (; i < len; i++) { surface.addCls(items[i], obj); } } }, removeCls: function(obj) { var i = 0, items = this.items, surface = this.getSurface(), len = this.length; if (surface) { for (; i < len; i++) { surface.removeCls(items[i], obj); } } }, getSurface: function(){ var first = this.first(); if (first) { return first.surface; } return null; }, destroy: function(){ var me = this, surface = me.getSurface(), destroySprites = me.autoDestroy, item; if (surface) { while (me.getCount() > 0) { item = me.first(); me.remove(item); surface.remove(item, destroySprites); } } me.clearListeners(); } }); Ext.define('Ext.draw.Surface', { mixins: { observable: Ext.util.Observable }, separatorRe: /[, ]+/, enginePriority: ['Svg', 'Vml'], statics: { create: function(config, enginePriority) { enginePriority = enginePriority || this.prototype.enginePriority; var i = 0, len = enginePriority.length; for (; i < len; i++) { if (Ext.supports[enginePriority[i]]) { return Ext.create('Ext.draw.engine.' + enginePriority[i], config); } } return false; }, save: function(surface, config) { config = config || {}; var exportTypes = { 'image/png': 'Image', 'image/jpeg': 'Image', 'image/svg+xml': 'Svg' }, prefix = exportTypes[config.type] || 'Svg', exporter = Ext.draw.engine[prefix + 'Exporter']; return exporter.generate(surface, config); } }, availableAttrs: { blur: 0, "clip-rect": "0 0 1e9 1e9", cursor: "default", cx: 0, cy: 0, 'dominant-baseline': 'auto', fill: "none", "fill-opacity": 1, font: '10px "Arial"', "font-family": '"Arial"', "font-size": "10", "font-style": "normal", "font-weight": 400, gradient: "", height: 0, hidden: false, href: "http://sencha.com/", opacity: 1, path: "M0,0", radius: 0, rx: 0, ry: 0, scale: "1 1", src: "", stroke: "none", "stroke-dasharray": "", "stroke-linecap": "butt", "stroke-linejoin": "butt", "stroke-miterlimit": 0, "stroke-opacity": 1, "stroke-width": 1, target: "_blank", text: "", "text-anchor": "middle", title: "Ext Draw", width: 0, x: 0, y: 0, zIndex: 0 }, container: undefined, height: 352, width: 512, x: 0, y: 0, orderSpritesByZIndex: true, constructor: function(config) { var me = this; config = config || {}; Ext.apply(me, config); me.domRef = Ext.getDoc().dom; me.customAttributes = {}; me.addEvents( 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', 'mouseenter', 'mouseleave', 'click', 'dblclick' ); me.mixins.observable.constructor.call(me); me.getId(); me.initGradients(); me.initItems(); if (me.renderTo) { me.render(me.renderTo); delete me.renderTo; } me.initBackground(config.background); }, initSurface: Ext.emptyFn, renderItem: Ext.emptyFn, renderItems: Ext.emptyFn, setViewBox: function (x, y, width, height) { if (isFinite(x) && isFinite(y) && isFinite(width) && isFinite(height)) { this.viewBox = {x: x, y: y, width: width, height: height}; this.applyViewBox(); } }, addCls: Ext.emptyFn, removeCls: Ext.emptyFn, setStyle: Ext.emptyFn, initGradients: function() { if (this.hasOwnProperty('gradients')) { var gradients = this.gradients, fn = this.addGradient, g, gLen; if (gradients) { for (g = 0, gLen = gradients.length; g < gLen; g++) { if (fn.call(this, gradients[g], g, gLen) === false) { break; } } } } }, initItems: function() { var items = this.items; this.items = new Ext.draw.CompositeSprite(); this.items.autoDestroy = true; this.groups = new Ext.draw.CompositeSprite(); if (items) { this.add(items); } }, initBackground: function(config) { var me = this, width = me.width, height = me.height, gradientId, gradient; if (Ext.isString(config)) { config = { fill : config }; } if (config) { if (config.gradient) { gradient = config.gradient; gradientId = gradient.id; me.addGradient(gradient); me.background = me.add({ type: 'rect', isBackground: true, x: 0, y: 0, width: width, height: height, fill: 'url(#' + gradientId + ')', zIndex: -1 }); } else if (config.fill) { me.background = me.add({ type: 'rect', isBackground: true, x: 0, y: 0, width: width, height: height, fill: config.fill, zIndex: -1 }); } else if (config.image) { me.background = me.add({ type: 'image', isBackground: true, x: 0, y: 0, width: width, height: height, src: config.image, zIndex: -1 }); } me.background.bboxExcluded = true; } }, setSize: function(w, h) { this.applyViewBox(); }, scrubAttrs: function(sprite) { var i, attrs = {}, exclude = {}, sattr = sprite.attr; for (i in sattr) { if (this.translateAttrs.hasOwnProperty(i)) { attrs[this.translateAttrs[i]] = sattr[i]; exclude[this.translateAttrs[i]] = true; } else if (this.availableAttrs.hasOwnProperty(i) && !exclude[i]) { attrs[i] = sattr[i]; } } return attrs; }, onClick: function(e) { this.processEvent('click', e); }, onDblClick: function(e) { this.processEvent('dblclick', e); }, onMouseUp: function(e) { this.processEvent('mouseup', e); }, onMouseDown: function(e) { this.processEvent('mousedown', e); }, onMouseOver: function(e) { this.processEvent('mouseover', e); }, onMouseOut: function(e) { this.processEvent('mouseout', e); }, onMouseMove: function(e) { this.fireEvent('mousemove', e); }, onMouseEnter: Ext.emptyFn, onMouseLeave: Ext.emptyFn, addGradient: Ext.emptyFn, add: function() { var args = Array.prototype.slice.call(arguments), sprite, hasMultipleArgs = args.length > 1, items, results, i, ln, item; if (hasMultipleArgs || Ext.isArray(args[0])) { items = hasMultipleArgs ? args : args[0]; results = []; for (i = 0, ln = items.length; i < ln; i++) { item = items[i]; item = this.add(item); results.push(item); } return results; } sprite = this.prepareItems(args[0], true)[0]; this.insertByZIndex(sprite); this.onAdd(sprite); return sprite; }, insertByZIndex: function(sprite) { var me = this, sprites = me.items.items, len = sprites.length, ceil = Math.ceil, zIndex = sprite.attr.zIndex, idx = len, high = idx - 1, low = 0, otherZIndex; if (me.orderSpritesByZIndex && len && zIndex < sprites[high].attr.zIndex) { while (low <= high) { idx = ceil((low + high) / 2); otherZIndex = sprites[idx].attr.zIndex; if (otherZIndex > zIndex) { high = idx - 1; } else if (otherZIndex < zIndex) { low = idx + 1; } else { break; } } while (idx < len && sprites[idx].attr.zIndex <= zIndex) { idx++; } } me.items.insert(idx, sprite); return idx; }, onAdd: function(sprite) { var group = sprite.group, draggable = sprite.draggable, groups, ln, i; if (group) { groups = [].concat(group); ln = groups.length; for (i = 0; i < ln; i++) { group = groups[i]; this.getGroup(group).add(sprite); } delete sprite.group; } if (draggable) { sprite.initDraggable(); } }, remove: function(sprite, destroySprite) { if (sprite) { this.items.remove(sprite); var groups = [].concat(this.groups.items), gLen = groups.length, g; for (g = 0; g < gLen; g++) { groups[g].remove(sprite); } sprite.onRemove(); if (destroySprite === true) { sprite.destroy(); } } }, removeAll: function(destroySprites) { var items = this.items.items, ln = items.length, i; for (i = ln - 1; i > -1; i--) { this.remove(items[i], destroySprites); } }, onRemove: Ext.emptyFn, onDestroy: Ext.emptyFn, applyViewBox: function() { var me = this, viewBox = me.viewBox, width = me.width || 1, height = me.height || 1, viewBoxX, viewBoxY, viewBoxWidth, viewBoxHeight, relativeHeight, relativeWidth, size; if (viewBox && (width || height)) { viewBoxX = viewBox.x; viewBoxY = viewBox.y; viewBoxWidth = viewBox.width; viewBoxHeight = viewBox.height; relativeHeight = height / viewBoxHeight; relativeWidth = width / viewBoxWidth; size = Math.min(relativeWidth, relativeHeight); if (viewBoxWidth * size < width) { viewBoxX -= (width - viewBoxWidth * size) / 2 / size; } if (viewBoxHeight * size < height) { viewBoxY -= (height - viewBoxHeight * size) / 2 / size; } me.viewBoxShift = { dx: -viewBoxX, dy: -viewBoxY, scale: size }; if (me.background) { me.background.setAttributes(Ext.apply({}, { x: viewBoxX, y: viewBoxY, width: width / size, height: height / size }, { hidden: false }), true); } } else { if (me.background && width && height) { me.background.setAttributes(Ext.apply({x: 0, y: 0, width: width, height: height}, { hidden: false }), true); } } }, getBBox: function (sprite, isWithoutTransform) { var realPath = this["getPath" + sprite.type](sprite); if (isWithoutTransform) { sprite.bbox.plain = sprite.bbox.plain || Ext.draw.Draw.pathDimensions(realPath); return sprite.bbox.plain; } if (sprite.dirtyTransform) { this.applyTransformations(sprite, true); } sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix)); return sprite.bbox.transform; }, transformToViewBox: function (x, y) { if (this.viewBoxShift) { var me = this, shift = me.viewBoxShift; return [x / shift.scale - shift.dx, y / shift.scale - shift.dy]; } else { return [x, y]; } }, applyTransformations: function(sprite, onlyMatrix) { if (sprite.type == 'text') { sprite.bbox.transform = 0; this.transform(sprite, false); } sprite.dirtyTransform = false; var me = this, attr = sprite.attr; if (attr.translation.x != null || attr.translation.y != null) { me.translate(sprite); } if (attr.scaling.x != null || attr.scaling.y != null) { me.scale(sprite); } if (attr.rotation.degrees != null) { me.rotate(sprite); } sprite.bbox.transform = 0; this.transform(sprite, onlyMatrix); sprite.transformations = []; }, rotate: function (sprite) { var bbox, deg = sprite.attr.rotation.degrees, centerX = sprite.attr.rotation.x, centerY = sprite.attr.rotation.y; if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) { bbox = this.getBBox(sprite, true); centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX; centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY; } sprite.transformations.push({ type: "rotate", degrees: deg, x: centerX, y: centerY }); }, translate: function(sprite) { var x = sprite.attr.translation.x || 0, y = sprite.attr.translation.y || 0; sprite.transformations.push({ type: "translate", x: x, y: y }); }, scale: function(sprite) { var bbox, x = sprite.attr.scaling.x || 1, y = sprite.attr.scaling.y || 1, centerX = sprite.attr.scaling.centerX, centerY = sprite.attr.scaling.centerY; if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) { bbox = this.getBBox(sprite, true); centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX; centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY; } sprite.transformations.push({ type: "scale", x: x, y: y, centerX: centerX, centerY: centerY }); }, rectPath: function (x, y, w, h, r) { if (r) { return [["M", x + r, y], ["l", w - r * 2, 0], ["a", r, r, 0, 0, 1, r, r], ["l", 0, h - r * 2], ["a", r, r, 0, 0, 1, -r, r], ["l", r * 2 - w, 0], ["a", r, r, 0, 0, 1, -r, -r], ["l", 0, r * 2 - h], ["a", r, r, 0, 0, 1, r, -r], ["z"]]; } return [["M", x, y], ["l", w, 0], ["l", 0, h], ["l", -w, 0], ["z"]]; }, ellipsePath: function (x, y, rx, ry) { if (ry == null) { ry = rx; } return [["M", x, y], ["m", 0, -ry], ["a", rx, ry, 0, 1, 1, 0, 2 * ry], ["a", rx, ry, 0, 1, 1, 0, -2 * ry], ["z"]]; }, getPathpath: function (el) { return el.attr.path; }, getPathcircle: function (el) { var a = el.attr; return this.ellipsePath(a.x, a.y, a.radius, a.radius); }, getPathellipse: function (el) { var a = el.attr; return this.ellipsePath(a.x, a.y, a.radiusX || (a.width / 2) || 0, a.radiusY || (a.height / 2) || 0); }, getPathrect: function (el) { var a = el.attr; return this.rectPath(a.x || 0, a.y || 0, a.width || 0, a.height || 0, a.r || 0); }, getPathimage: function (el) { var a = el.attr; return this.rectPath(a.x || 0, a.y || 0, a.width, a.height); }, getPathtext: function (el) { var bbox = this.getBBoxText(el); return this.rectPath(bbox.x, bbox.y, bbox.width, bbox.height); }, createGroup: function(id) { var group = this.groups.get(id); if (!group) { group = new Ext.draw.CompositeSprite({ surface: this }); group.id = id || Ext.id(null, 'ext-surface-group-'); this.groups.add(group); } return group; }, getGroup: function(id) { var group; if (typeof id == "string") { group = this.groups.get(id); if (!group) { group = this.createGroup(id); } } else { group = id; } return group; }, prepareItems: function(items, applyDefaults) { items = [].concat(items); var item, i, ln; for (i = 0, ln = items.length; i < ln; i++) { item = items[i]; if (!(item instanceof Ext.draw.Sprite)) { item.surface = this; items[i] = this.createItem(item); } else { item.surface = this; } } return items; }, setText: Ext.emptyFn, createItem: Ext.emptyFn, getId: function() { return this.id || (this.id = Ext.id(null, 'ext-surface-')); }, destroy: function() { var me = this; delete me.domRef; if (me.background) { me.background.destroy(); } me.removeAll(true); Ext.destroy(me.groups.items); } }); Ext.define('Ext.layout.component.Draw', { alias: 'layout.draw', extend: Ext.layout.component.Auto , setHeightInDom: true, setWidthInDom: true, type: 'draw', measureContentWidth : function (ownerContext) { var target = ownerContext.target, paddingInfo = ownerContext.getPaddingInfo(), bbox = this.getBBox(ownerContext); if (!target.viewBox) { if (target.autoSize) { return bbox.width + paddingInfo.width; } else { return bbox.x + bbox.width + paddingInfo.width; } } else { if (ownerContext.heightModel.shrinkWrap) { return paddingInfo.width; } else { return bbox.width / bbox.height * (ownerContext.getProp('contentHeight') - paddingInfo.height) + paddingInfo.width; } } }, measureContentHeight : function (ownerContext) { var target = ownerContext.target, paddingInfo = ownerContext.getPaddingInfo(), bbox = this.getBBox(ownerContext); if (!ownerContext.target.viewBox) { if (target.autoSize) { return bbox.height + paddingInfo.height; } else { return bbox.y + bbox.height + paddingInfo.height; } } else { if (ownerContext.widthModel.shrinkWrap) { return paddingInfo.height; } else { return bbox.height / bbox.width * (ownerContext.getProp('contentWidth') - paddingInfo.width) + paddingInfo.height; } } }, getBBox: function(ownerContext) { var bbox = ownerContext.surfaceBBox; if (!bbox) { bbox = ownerContext.target.surface.items.getBBox(); if (bbox.width === -Infinity && bbox.height === -Infinity) { bbox.width = bbox.height = bbox.x = bbox.y = 0; } ownerContext.surfaceBBox = bbox; } return bbox; }, publishInnerWidth: function (ownerContext, width) { ownerContext.setContentWidth(width - ownerContext.getFrameInfo().width, true); }, publishInnerHeight: function (ownerContext, height) { ownerContext.setContentHeight(height - ownerContext.getFrameInfo().height, true); }, finishedLayout: function (ownerContext) { var props = ownerContext.props, paddingInfo = ownerContext.getPaddingInfo(); this.owner.setSurfaceSize(props.contentWidth - paddingInfo.width, props.contentHeight - paddingInfo.height); this.callParent(arguments); } }); Ext.define('Ext.draw.Component', { alias: 'widget.draw', extend: Ext.Component , enginePriority: ['Svg', 'Vml'], baseCls: Ext.baseCSSPrefix + 'surface', componentLayout: 'draw', viewBox: true, shrinkWrap: 3, autoSize: false, suspendSizing: 0, initComponent: function() { this.callParent(arguments); this.addEvents( 'mousedown', 'mouseup', 'mousemove', 'mouseenter', 'mouseleave', 'click', 'dblclick' ); }, onRender: function() { this.callParent(arguments); if (this.createSurface() !== false) { this.configureSurfaceSize(); } }, configureSurfaceSize: function(){ var me = this, viewBox = me.viewBox, autoSize = me.autoSize, bbox; if ((viewBox || autoSize) && !me.suspendSizing) { bbox = me.surface.items.getBBox(); if (viewBox) { me.surface.setViewBox(bbox.x, bbox.y, bbox.width, bbox.height); } else { me.autoSizeSurface(bbox); } } }, autoSizeSurface: function(bbox) { bbox = bbox || this.surface.items.getBBox(); this.setSurfaceSize(bbox.width, bbox.height); }, setSurfaceSize: function (width, height) { this.surface.setSize(width, height); if (this.autoSize) { var bbox = this.surface.items.getBBox(); this.surface.setViewBox(bbox.x, bbox.y - (+Ext.isOpera), width, height); } }, createSurface: function() { var me = this, cfg = Ext.applyIf({ renderTo: me.el, height: me.height, width: me.width, items: me.items }, me.initialConfig), surface; delete cfg.listeners; if (!cfg.gradients) { cfg.gradients = me.gradients; } me.initSurfaceCfg(cfg); surface = Ext.draw.Surface.create(cfg, me.enginePriority); if (!surface) { return false; } me.surface = surface; surface.owner = me; function refire(eventName) { return function(e) { me.fireEvent(eventName, e); }; } surface.on({ scope: me, mouseup: refire('mouseup'), mousedown: refire('mousedown'), mousemove: refire('mousemove'), mouseenter: refire('mouseenter'), mouseleave: refire('mouseleave'), click: refire('click'), dblclick: refire('dblclick') }); }, initSurfaceCfg: Ext.emptyFn, onDestroy: function() { Ext.destroy(this.surface); this.callParent(arguments); } }); Ext.chart = Ext.chart || {}; Ext.define('Ext.chart.theme.Theme', ( function() { (function() { Ext.chart.theme = function(config, base) { config = config || {}; var i = 0, d = Ext.Date.now(), l, colors, color, seriesThemes, markerThemes, seriesTheme, markerTheme, key, gradients = [], midColor, midL; if (config.baseColor) { midColor = Ext.draw.Color.fromString(config.baseColor); midL = midColor.getHSL()[2]; if (midL < 0.15) { midColor = midColor.getLighter(0.3); } else if (midL < 0.3) { midColor = midColor.getLighter(0.15); } else if (midL > 0.85) { midColor = midColor.getDarker(0.3); } else if (midL > 0.7) { midColor = midColor.getDarker(0.15); } config.colors = [ midColor.getDarker(0.3).toString(), midColor.getDarker(0.15).toString(), midColor.toString(), midColor.getLighter(0.15).toString(), midColor.getLighter(0.3).toString()]; delete config.baseColor; } if (config.colors) { colors = config.colors.slice(); markerThemes = base.markerThemes; seriesThemes = base.seriesThemes; l = colors.length; base.colors = colors; for (; i < l; i++) { color = colors[i]; markerTheme = markerThemes[i] || {}; seriesTheme = seriesThemes[i] || {}; markerTheme.fill = seriesTheme.fill = markerTheme.stroke = seriesTheme.stroke = color; markerThemes[i] = markerTheme; seriesThemes[i] = seriesTheme; } base.markerThemes = markerThemes.slice(0, l); base.seriesThemes = seriesThemes.slice(0, l); } for (key in base) { if (key in config) { if (Ext.isObject(config[key]) && Ext.isObject(base[key])) { Ext.apply(base[key], config[key]); } else { base[key] = config[key]; } } } if (config.useGradients) { colors = base.colors || (function () { var ans = []; for (i = 0, seriesThemes = base.seriesThemes, l = seriesThemes.length; i < l; i++) { ans.push(seriesThemes[i].fill || seriesThemes[i].stroke); } return ans; }()); for (i = 0, l = colors.length; i < l; i++) { midColor = Ext.draw.Color.fromString(colors[i]); if (midColor) { color = midColor.getDarker(0.1).toString(); midColor = midColor.toString(); key = 'theme-' + midColor.substr(1) + '-' + color.substr(1) + '-' + d; gradients.push({ id: key, angle: 45, stops: { 0: { color: midColor.toString() }, 100: { color: color.toString() } } }); colors[i] = 'url(#' + key + ')'; } } base.gradients = gradients; base.colors = colors; } Ext.apply(this, base); }; }()); return { theme: 'Base', themeAttrs: false, initTheme: function(theme) { var me = this, themes = Ext.chart.theme, key, gradients; if (theme) { theme = theme.split(':'); for (key in themes) { if (key == theme[0]) { gradients = theme[1] == 'gradients'; me.themeAttrs = new themes[key]({ useGradients: gradients }); if (gradients) { me.gradients = me.themeAttrs.gradients; } if (me.themeAttrs.background) { me.background = me.themeAttrs.background; } return; } } } } }; })()); Ext.define('Ext.chart.MaskLayer', { extend: Ext.Component , constructor: function(config) { config = Ext.apply(config || {}, { style: 'position:absolute;background-color:#ff9;cursor:crosshair;opacity:0.5;border:1px solid #00f;' }); this.callParent([config]); }, initComponent: function() { var me = this; me.callParent(arguments); me.addEvents( 'mousedown', 'mouseup', 'mousemove', 'mouseenter', 'mouseleave' ); }, initDraggable: function() { this.callParent(arguments); this.dd.onStart = function (e) { var me = this, comp = me.comp; this.startPosition = comp.getPosition(true); if (comp.ghost && !comp.liveDrag) { me.proxy = comp.ghost(); me.dragTarget = me.proxy.header.el; } if (me.constrain || me.constrainDelegate) { me.constrainTo = me.calculateConstrainRegion(); } }; } }); Ext.define('Ext.chart.Mask', { constructor: function(config) { var me = this; me.addEvents('select'); if (config) { Ext.apply(me, config); } if (me.enableMask) { me.on('afterrender', function() { var comp = new Ext.chart.MaskLayer({ renderTo: me.el, hidden: true }); comp.el.on({ 'mousemove': function(e) { me.onMouseMove(e); }, 'mouseup': function(e) { me.onMouseUp(e); } }); comp.initDraggable(); me.maskType = me.mask; me.mask = comp; me.maskSprite = me.surface.add({ type: 'path', path: ['M', 0, 0], zIndex: 1001, opacity: 0.6, hidden: true, stroke: '#00f', cursor: 'crosshair' }); }, me, { single: true }); } }, onMouseUp: function(e) { var me = this, bbox = me.bbox || me.chartBBox, sel; me.maskMouseDown = false; me.mouseDown = false; if (me.mouseMoved) { me.handleMouseEvent(e); me.mouseMoved = false; sel = me.maskSelection; me.fireEvent('select', me, { x: sel.x - bbox.x, y: sel.y - bbox.y, width: sel.width, height: sel.height }); } }, onMouseDown: function(e) { this.handleMouseEvent(e); }, onMouseMove: function(e) { this.handleMouseEvent(e); }, handleMouseEvent: function(e) { var me = this, mask = me.maskType, bbox = me.bbox || me.chartBBox, x = bbox.x, y = bbox.y, math = Math, floor = math.floor, abs = math.abs, min = math.min, max = math.max, height = floor(y + bbox.height), width = floor(x + bbox.width), staticX = e.getPageX() - me.el.getX(), staticY = e.getPageY() - me.el.getY(), maskMouseDown = me.maskMouseDown, path; staticX = max(staticX, x); staticY = max(staticY, y); staticX = min(staticX, width); staticY = min(staticY, height); if (e.type === 'mousedown') { me.mouseDown = true; me.mouseMoved = false; me.maskMouseDown = { x: staticX, y: staticY }; } else { me.mouseMoved = me.mouseDown; if (maskMouseDown && me.mouseDown) { if (mask == 'horizontal') { staticY = y; maskMouseDown.y = height; } else if (mask == 'vertical') { staticX = x; maskMouseDown.x = width; } width = maskMouseDown.x - staticX; height = maskMouseDown.y - staticY; path = ['M', staticX, staticY, 'l', width, 0, 0, height, -width, 0, 'z']; me.maskSelection = { x: (width > 0 ? staticX : staticX + width) + me.el.getX(), y: (height > 0 ? staticY : staticY + height) + me.el.getY(), width: abs(width), height: abs(height) }; me.mask.updateBox(me.maskSelection); me.mask.show(); me.maskSprite.setAttributes({ hidden: true }, true); } else { if (mask == 'horizontal') { path = ['M', staticX, y, 'L', staticX, height]; } else if (mask == 'vertical') { path = ['M', x, staticY, 'L', width, staticY]; } else { path = ['M', staticX, y, 'L', staticX, height, 'M', x, staticY, 'L', width, staticY]; } me.maskSprite.setAttributes({ path: path, 'stroke-width': mask === true ? 1 : 1, hidden: false }, true); } } }, onMouseLeave: function(e) { var me = this; me.mouseMoved = false; me.mouseDown = false; me.maskMouseDown = false; me.mask.hide(); me.maskSprite.hide(true); } }); Ext.define('Ext.chart.Navigation', { setZoom: function(zoomConfig) { var me = this, axesItems = me.axes.items, i, ln, axis, bbox = me.chartBBox, xScale = bbox.width, yScale = bbox.height, zoomArea = { x : zoomConfig.x - me.el.getX(), y : zoomConfig.y - me.el.getY(), width : zoomConfig.width, height : zoomConfig.height }, zoomer, ends, from, to, store, count, step, length, horizontal; for (i = 0, ln = axesItems.length; i < ln; i++) { axis = axesItems[i]; horizontal = (axis.position == 'bottom' || axis.position == 'top'); if (axis.type == 'Category') { if (!store) { store = me.getChartStore(); count = store.data.items.length; } zoomer = zoomArea; length = axis.length; step = Math.round(length / count); if (horizontal) { from = (zoomer.x ? Math.floor(zoomer.x / step) + 1 : 0); to = (zoomer.x + zoomer.width) / step; } else { from = (zoomer.y ? Math.floor(zoomer.y / step) + 1 : 0); to = (zoomer.y + zoomer.height) / step; } } else { zoomer = { x : zoomArea.x / xScale, y : zoomArea.y / yScale, width : zoomArea.width / xScale, height : zoomArea.height / yScale } ends = axis.calcEnds(); if (horizontal) { from = (ends.to - ends.from) * zoomer.x + ends.from; to = (ends.to - ends.from) * zoomer.width + from; } else { to = (ends.to - ends.from) * (1 - zoomer.y) + ends.from; from = to - (ends.to - ends.from) * zoomer.height; } } axis.minimum = from; axis.maximum = to; if (horizontal) { if (axis.doConstrain && me.maskType != 'vertical') { axis.doConstrain(); } } else { if (axis.doConstrain && me.maskType != 'horizontal') { axis.doConstrain(); } } } me.redraw(false); }, restoreZoom: function() { var me = this, axesItems = me.axes.items, i, ln, axis; me.setSubStore(null); for (i = 0, ln = axesItems.length; i < ln; i++) { axis = axesItems[i]; delete axis.minimum; delete axis.maximum; } me.redraw(false); } }); Ext.define('Ext.chart.Shape', { singleton: true, circle: function (surface, opts) { return surface.add(Ext.apply({ type: 'circle', x: opts.x, y: opts.y, stroke: null, radius: opts.radius }, opts)); }, line: function (surface, opts) { return surface.add(Ext.apply({ type: 'rect', x: opts.x - opts.radius, y: opts.y - opts.radius, height: 2 * opts.radius, width: 2 * opts.radius / 5 }, opts)); }, square: function (surface, opts) { return surface.add(Ext.applyIf({ type: 'rect', x: opts.x - opts.radius, y: opts.y - opts.radius, height: 2 * opts.radius, width: 2 * opts.radius, radius: null }, opts)); }, triangle: function (surface, opts) { opts.radius *= 1.75; return surface.add(Ext.apply({ type: 'path', stroke: null, path: "M".concat(opts.x, ",", opts.y, "m0-", opts.radius * 0.58, "l", opts.radius * 0.5, ",", opts.radius * 0.87, "-", opts.radius, ",0z") }, opts)); }, diamond: function (surface, opts) { var r = opts.radius; r *= 1.5; return surface.add(Ext.apply({ type: 'path', stroke: null, path: ["M", opts.x, opts.y - r, "l", r, r, -r, r, -r, -r, r, -r, "z"] }, opts)); }, cross: function (surface, opts) { var r = opts.radius; r = r / 1.7; return surface.add(Ext.apply({ type: 'path', stroke: null, path: "M".concat(opts.x - r, ",", opts.y, "l", [-r, -r, r, -r, r, r, r, -r, r, r, -r, r, r, r, -r, r, -r, -r, -r, r, -r, -r, "z"]) }, opts)); }, plus: function (surface, opts) { var r = opts.radius / 1.3; return surface.add(Ext.apply({ type: 'path', stroke: null, path: "M".concat(opts.x - r / 2, ",", opts.y - r / 2, "l", [0, -r, r, 0, 0, r, r, 0, 0, r, -r, 0, 0, r, -r, 0, 0, -r, -r, 0, 0, -r, "z"]) }, opts)); }, arrow: function (surface, opts) { var r = opts.radius; return surface.add(Ext.apply({ type: 'path', path: "M".concat(opts.x - r * 0.7, ",", opts.y - r * 0.4, "l", [r * 0.6, 0, 0, -r * 0.4, r, r * 0.8, -r, r * 0.8, 0, -r * 0.4, -r * 0.6, 0], "z") }, opts)); }, drop: function (surface, x, y, text, size, angle) { size = size || 30; angle = angle || 0; surface.add({ type: 'path', path: ['M', x, y, 'l', size, 0, 'A', size * 0.4, size * 0.4, 0, 1, 0, x + size * 0.7, y - size * 0.7, 'z'], fill: '#000', stroke: 'none', rotate: { degrees: 22.5 - angle, x: x, y: y } }); angle = (angle + 90) * Math.PI / 180; surface.add({ type: 'text', x: x + size * Math.sin(angle) - 10, y: y + size * Math.cos(angle) + 5, text: text, 'font-size': size * 12 / 40, stroke: 'none', fill: '#fff' }); } }); Ext.define('Ext.chart.LegendItem', { extend: Ext.draw.CompositeSprite , hiddenSeries: false, label: undefined, x: 0, y: 0, zIndex: 500, boldRe: /bold\s\d{1,}.*/i, constructor: function(config) { this.callParent(arguments); this.createLegend(config); }, createLegend: function(config) { var me = this, series = me.series, index = config.yFieldIndex; me.label = me.createLabel(config); me.createSeriesMarkers(config); me.setAttributes({ hidden: false }, true); me.yFieldIndex = index; me.on('mouseover', me.onMouseOver, me); me.on('mouseout', me.onMouseOut, me); me.on('mousedown', me.onMouseDown, me); if (!series.visibleInLegend(index)) { me.hiddenSeries = true; me.label.setAttributes({ opacity: 0.5 }, true); }; me.updatePosition({ x: 0, y: 0 }); }, getLabelText: function() { var me = this, series = me.series, idx = me.yFieldIndex; function getSeriesProp(name) { var val = series[name]; return (Ext.isArray(val) ? val[idx] : val); } return getSeriesProp('title') || getSeriesProp('yField'); }, createLabel: function(config) { var me = this, legend = me.legend; return me.add('label', me.surface.add({ type: 'text', x: 20, y: 0, zIndex: (me.zIndex || 0) + 2, fill: legend.labelColor, font: legend.labelFont, text: me.getLabelText(), style: { cursor: 'pointer' } })); }, createSeriesMarkers: function(config) { var me = this, index = config.yFieldIndex, series = me.series, seriesType = series.type, surface = me.surface, z = me.zIndex; if (seriesType === 'line' || seriesType === 'scatter') { if(seriesType === 'line') { var seriesStyle = Ext.apply(series.seriesStyle, series.style); me.drawLine(0.5, 0.5, 16.5, 0.5, z, seriesStyle, index); }; if (series.showMarkers || seriesType === 'scatter') { var markerConfig = Ext.apply(series.markerStyle, series.markerConfig || {}, { fill: series.getLegendColor(index) }); me.drawMarker(8.5, 0.5, z, markerConfig); } } else { me.drawFilledBox(12, 12, z, index); } }, drawLine: function(fromX, fromY, toX, toY, z, seriesStyle, index) { var me = this, surface = me.surface, series = me.series; return me.add('line', surface.add({ type: 'path', path: 'M' + fromX + ',' + fromY + 'L' + toX + ',' + toY, zIndex: (z || 0) + 2, "stroke-width": series.lineWidth, "stroke-linejoin": "round", "stroke-dasharray": series.dash, stroke: seriesStyle.stroke || series.getLegendColor(index) || '#000', style: { cursor: 'pointer' } })); }, drawMarker: function(x, y, z, markerConfig) { var me = this, surface = me.surface, series = me.series; return me.add('marker', Ext.chart.Shape[markerConfig.type](surface, { fill: markerConfig.fill, x: x, y: y, zIndex: (z || 0) + 2, radius: markerConfig.radius || markerConfig.size, style: { cursor: 'pointer' } })); }, drawFilledBox: function(width, height, z, index) { var me = this, surface = me.surface, series = me.series; return me.add('box', surface.add({ type: 'rect', zIndex: (z || 0) + 2, x: 0, y: 0, width: width, height: height, fill: series.getLegendColor(index), style: { cursor: 'pointer' } })); }, onMouseOver: function() { var me = this; me.label.setStyle({ 'font-weight': 'bold' }); me.series._index = me.yFieldIndex; me.series.highlightItem(); }, onMouseOut: function() { var me = this, legend = me.legend, boldRe = me.boldRe; me.label.setStyle({ 'font-weight': legend.labelFont && boldRe.test(legend.labelFont) ? 'bold' : 'normal' }); me.series._index = me.yFieldIndex; me.series.unHighlightItem(); }, onMouseDown: function() { var me = this, index = me.yFieldIndex; if (!me.hiddenSeries) { me.series.hideAll(index); me.label.setAttributes({ opacity: 0.5 }, true); } else { me.series.showAll(index); me.label.setAttributes({ opacity: 1 }, true); } me.hiddenSeries = !me.hiddenSeries; me.legend.chart.redraw(); }, updatePosition: function(relativeTo) { var me = this, items = me.items, ln = items.length, currentX = me.x, currentY = me.y, item, i, x, y, translate, o, relativeX, relativeY; if (!relativeTo) { relativeTo = me.legend; } relativeX = relativeTo.x; relativeY = relativeTo.y; for (i = 0; i < ln; i++) { translate = true; item = items[i]; switch (item.type) { case 'text': x = 20 + relativeX + currentX; y = relativeY + currentY; translate = false; break; case 'rect': x = relativeX + currentX; y = relativeY + currentY - 6; break; default: x = relativeX + currentX; y = relativeY + currentY; } o = { x: x, y: y }; item.setAttributes(translate ? { translate: o } : o, true); } } }); Ext.define('Ext.chart.Legend', { visible: true, update: true, position: 'bottom', x: 0, y: 0, labelColor: '#000', labelFont: '12px Helvetica, sans-serif', boxStroke: '#000', boxStrokeWidth: 1, boxFill: '#FFF', itemSpacing: 10, padding: 5, width: 0, height: 0, boxZIndex: 100, constructor: function(config) { var me = this; if (config) { Ext.apply(me, config); } me.items = []; me.isVertical = ("left|right|float".indexOf(me.position) !== -1); me.origX = me.x; me.origY = me.y; }, create: function() { var me = this, seriesItems = me.chart.series.items, i, ln, series; me.createBox(); if (me.rebuild !== false) { me.createItems(); } if (!me.created && me.isDisplayed()) { me.created = true; for (i = 0, ln = seriesItems.length; i < ln; i++) { series = seriesItems[i]; series.on('titlechange', me.redraw, me); } } }, init: Ext.emptyFn, redraw: function() { var me = this; me.create(); me.updatePosition(); }, isDisplayed: function() { return this.visible && this.chart.series.findIndex('showInLegend', true) !== -1; }, createItems: function() { var me = this, seriesItems = me.chart.series.items, items = me.items, fields, i, li, j, lj, series, item; me.removeItems(); for (i = 0, li = seriesItems.length; i < li; i++) { series = seriesItems[i]; if (series.showInLegend) { fields = [].concat(series.yField); for (j = 0, lj = fields.length; j < lj; j++) { item = me.createLegendItem(series, j); items.push(item); } } } me.alignItems(); }, removeItems: function() { var me = this, items = me.items, len = items ? items.length : 0, i; if (len) { for (i = 0; i < len; i++) { items[i].destroy(); } } items.length = []; }, alignItems: function() { var me = this, padding = me.padding, vertical = me.isVertical, mfloor = Math.floor, dim, maxWidth, maxHeight, totalWidth, totalHeight; dim = me.updateItemDimensions(); maxWidth = dim.maxWidth; maxHeight = dim.maxHeight; totalWidth = dim.totalWidth; totalHeight = dim.totalHeight; me.width = mfloor((vertical ? maxWidth : totalWidth) + padding * 2); me.height = mfloor((vertical ? totalHeight : maxHeight) + padding * 2); }, updateItemDimensions: function() { var me = this, items = me.items, padding = me.padding, itemSpacing = me.itemSpacing, maxWidth = 0, maxHeight = 0, totalWidth = 0, totalHeight = 0, vertical = me.isVertical, mfloor = Math.floor, mmax = Math.max, spacing = 0, i, l, item, bbox, width, height; for (i = 0, l = items.length; i < l; i++) { item = items[i]; bbox = item.getBBox(); width = bbox.width; height = bbox.height; spacing = (i === 0 ? 0 : itemSpacing); item.x = padding + mfloor(vertical ? 0 : totalWidth + spacing); item.y = padding + mfloor(vertical ? totalHeight + spacing : 0) + height / 2; totalWidth += spacing + width; totalHeight += spacing + height; maxWidth = mmax(maxWidth, width); maxHeight = mmax(maxHeight, height); } return { totalWidth: totalWidth, totalHeight: totalHeight, maxWidth: maxWidth, maxHeight: maxHeight }; }, createLegendItem: function(series, yFieldIndex) { var me = this; return new Ext.chart.LegendItem({ legend: me, series: series, surface: me.chart.surface, yFieldIndex: yFieldIndex }); }, getBBox: function() { var me = this; return { x: Math.round(me.x) - me.boxStrokeWidth / 2, y: Math.round(me.y) - me.boxStrokeWidth / 2, width: me.width + me.boxStrokeWidth, height: me.height + me.boxStrokeWidth }; }, createBox: function() { var me = this, box, bbox; if (me.boxSprite) { me.boxSprite.destroy(); } bbox = me.getBBox(); if (isNaN(bbox.width) || isNaN(bbox.height)) { me.boxSprite = false; return; } box = me.boxSprite = me.chart.surface.add(Ext.apply({ type: 'rect', stroke: me.boxStroke, "stroke-width": me.boxStrokeWidth, fill: me.boxFill, zIndex: me.boxZIndex }, bbox)); box.redraw(); }, calcPosition: function() { var me = this, x, y, legendWidth = me.width, legendHeight = me.height, chart = me.chart, chartBBox = chart.chartBBox, insets = chart.insetPadding, chartWidth = chartBBox.width - (insets * 2), chartHeight = chartBBox.height - (insets * 2), chartX = chartBBox.x + insets, chartY = chartBBox.y + insets, surface = chart.surface, mfloor = Math.floor; switch(me.position) { case "left": x = insets; y = mfloor(chartY + chartHeight / 2 - legendHeight / 2); break; case "right": x = mfloor(surface.width - legendWidth) - insets; y = mfloor(chartY + chartHeight / 2 - legendHeight / 2); break; case "top": x = mfloor(chartX + chartWidth / 2 - legendWidth / 2); y = insets; break; case "bottom": x = mfloor(chartX + chartWidth / 2 - legendWidth / 2); y = mfloor(surface.height - legendHeight) - insets; break; default: x = mfloor(me.origX) + insets; y = mfloor(me.origY) + insets; } return { x: x, y: y }; }, updatePosition: function() { var me = this, items = me.items, pos, i, l, bbox; if (me.isDisplayed()) { pos = me.calcPosition(); me.x = pos.x; me.y = pos.y; for (i = 0, l = items.length; i < l; i++) { items[i].updatePosition(); } bbox = me.getBBox(); if (isNaN(bbox.width) || isNaN(bbox.height)) { if (me.boxSprite) { me.boxSprite.hide(true); } } else { if (!me.boxSprite) { me.createBox(); } me.boxSprite.setAttributes(bbox, true); me.boxSprite.show(true); } } }, toggle: function(show) { var me = this, i = 0, items = me.items, len = items.length; if (me.boxSprite) { if (show) { me.boxSprite.show(true); } else { me.boxSprite.hide(true); } } for (; i < len; ++i) { if (show) { items[i].show(true); } else { items[i].hide(true); } } me.visible = show; } }); Ext.define('Ext.chart.theme.Base', { constructor: function(config) { var ident = Ext.identityFn; Ext.chart.theme.call(this, config, { background: false, axis: { stroke: '#444', 'stroke-width': 1 }, axisLabelTop: { fill: '#444', font: '12px Arial, Helvetica, sans-serif', spacing: 2, padding: 5, renderer: ident }, axisLabelRight: { fill: '#444', font: '12px Arial, Helvetica, sans-serif', spacing: 2, padding: 5, renderer: ident }, axisLabelBottom: { fill: '#444', font: '12px Arial, Helvetica, sans-serif', spacing: 2, padding: 5, renderer: ident }, axisLabelLeft: { fill: '#444', font: '12px Arial, Helvetica, sans-serif', spacing: 2, padding: 5, renderer: ident }, axisTitleTop: { font: 'bold 18px Arial', fill: '#444' }, axisTitleRight: { font: 'bold 18px Arial', fill: '#444', rotate: { x:0, y:0, degrees: 270 } }, axisTitleBottom: { font: 'bold 18px Arial', fill: '#444' }, axisTitleLeft: { font: 'bold 18px Arial', fill: '#444', rotate: { x:0, y:0, degrees: 270 } }, series: { 'stroke-width': 0 }, seriesLabel: { font: '12px Arial', fill: '#333' }, marker: { stroke: '#555', radius: 3, size: 3 }, colors: [ "#94ae0a", "#115fa6","#a61120", "#ff8809", "#ffd13e", "#a61187", "#24ad9a", "#7c7474", "#a66111"], seriesThemes: [{ fill: "#115fa6" }, { fill: "#94ae0a" }, { fill: "#a61120" }, { fill: "#ff8809" }, { fill: "#ffd13e" }, { fill: "#a61187" }, { fill: "#24ad9a" }, { fill: "#7c7474" }, { fill: "#115fa6" }, { fill: "#94ae0a" }, { fill: "#a61120" }, { fill: "#ff8809" }, { fill: "#ffd13e" }, { fill: "#a61187" }, { fill: "#24ad9a" }, { fill: "#7c7474" }, { fill: "#a66111" }], markerThemes: [{ fill: "#115fa6", type: 'circle' }, { fill: "#94ae0a", type: 'cross' }, { fill: "#115fa6", type: 'plus' }, { fill: "#94ae0a", type: 'circle' }, { fill: "#a61120", type: 'cross' }] }); } }, function() { var palette = ['#b1da5a', '#4ce0e7', '#e84b67', '#da5abd', '#4d7fe6', '#fec935'], names = ['Green', 'Sky', 'Red', 'Purple', 'Blue', 'Yellow'], i = 0, j = 0, l = palette.length, themes = Ext.chart.theme, categories = [['#f0a50a', '#c20024', '#2044ba', '#810065', '#7eae29'], ['#6d9824', '#87146e', '#2a9196', '#d39006', '#1e40ac'], ['#fbbc29', '#ce2e4e', '#7e0062', '#158b90', '#57880e'], ['#ef5773', '#fcbd2a', '#4f770d', '#1d3eaa', '#9b001f'], ['#7eae29', '#fdbe2a', '#910019', '#27b4bc', '#d74dbc'], ['#44dce1', '#0b2592', '#996e05', '#7fb325', '#b821a1']], cats = categories.length; for (; i < l; i++) { themes[names[i]] = (function(color) { return Ext.extend(themes.Base, { constructor: function(config) { themes.Base.prototype.constructor.call(this, Ext.apply({ baseColor: color }, config)); } }); }(palette[i])); } for (i = 0; i < cats; i++) { themes['Category' + (i + 1)] = (function(category) { return Ext.extend(themes.Base, { constructor: function(config) { themes.Base.prototype.constructor.call(this, Ext.apply({ colors: category }, config)); } }); }(categories[i])); } }); Ext.define('Ext.chart.Chart', { extend: Ext.draw.Component , alias: 'widget.chart', mixins: { themeManager: Ext.chart.theme.Theme , mask: Ext.chart.Mask , navigation: Ext.chart.Navigation , bindable: Ext.util.Bindable , observable: Ext.util.Observable }, viewBox: false, animate: false, legend: false, insetPadding: 10, background: false, refreshBuffer: 1, constructor: function(config) { var me = this, defaultAnim; config = Ext.apply({}, config); me.initTheme(config.theme || me.theme); if (me.gradients) { Ext.apply(config, { gradients: me.gradients }); } if (me.background) { Ext.apply(config, { background: me.background }); } if (config.animate) { defaultAnim = { easing: 'ease', duration: 500 }; if (Ext.isObject(config.animate)) { config.animate = Ext.applyIf(config.animate, defaultAnim); } else { config.animate = defaultAnim; } } me.mixins.observable.constructor.call(me, config); if (config.mask) { config = Ext.apply({ enableMask: true }, config); } if (config.enableMask) { me.mixins.mask.constructor.call(me, config); } me.mixins.navigation.constructor.call(me); me.callParent([config]); }, getChartStore: function(){ return this.substore || this.store; }, initComponent: function() { var me = this, axes, series; me.callParent(); me.addEvents( 'itemmousedown', 'itemmouseup', 'itemmouseover', 'itemmouseout', 'itemclick', 'itemdblclick', 'itemdragstart', 'itemdrag', 'itemdragend', 'beforerefresh', 'refresh' ); Ext.applyIf(me, { zoom: { width: 1, height: 1, x: 0, y: 0 } }); me.maxGutters = { left: 0, right: 0, bottom: 0, top: 0 }; me.store = Ext.data.StoreManager.lookup(me.store); axes = me.axes; me.axes = new Ext.util.MixedCollection(false, function(a) { return a.position; }); if (axes) { me.axes.addAll(axes); } series = me.series; me.series = new Ext.util.MixedCollection(false, function(a) { return a.seriesId || (a.seriesId = Ext.id(null, 'ext-chart-series-')); }); if (series) { me.series.addAll(series); } if (me.legend !== false) { me.legend = new Ext.chart.Legend(Ext.applyIf({ chart: me }, me.legend)); } me.on({ mousemove: me.onMouseMove, mouseleave: me.onMouseLeave, mousedown: me.onMouseDown, mouseup: me.onMouseUp, click: me.onClick, dblclick: me.onDblClick, scope: me }); }, afterComponentLayout: function(width, height, oldWidth, oldHeight) { var me = this; if (Ext.isNumber(width) && Ext.isNumber(height)) { if (width !== oldWidth || height !== oldHeight) { me.curWidth = width; me.curHeight = height; me.redraw(true); me.needsRedraw = false; } else if (me.needsRedraw) { me.redraw(); me.needsRedraw = false; } } this.callParent(arguments); }, redraw: function(resize) { var me = this, seriesItems = me.series.items, seriesLen = seriesItems.length, axesItems = me.axes.items, axesLen = axesItems.length, themeIndex = 0, i, item, chartBBox = me.chartBBox = { x: 0, y: 0, height: me.curHeight, width: me.curWidth }, legend = me.legend, series; me.surface.setSize(chartBBox.width, chartBBox.height); for (i = 0; i < seriesLen; i++) { item = seriesItems[i]; if (!item.initialized) { series = me.initializeSeries(item, i, themeIndex); } else { series = item; } series.onRedraw(); if (Ext.isArray(item.yField)) { themeIndex += item.yField.length; } else { ++themeIndex; } } for (i = 0; i < axesLen; i++) { item = axesItems[i]; if (!item.initialized) { me.initializeAxis(item); } } for (i = 0; i < axesLen; i++) { axesItems[i].processView(); } for (i = 0; i < axesLen; i++) { axesItems[i].drawAxis(true); } if (legend !== false && legend.visible) { if (legend.update || !legend.created) { legend.create(); } } me.alignAxes(); if (legend !== false && legend.visible) { legend.updatePosition(); } me.getMaxGutters(); me.resizing = !!resize; for (i = 0; i < axesLen; i++) { axesItems[i].drawAxis(); } for (i = 0; i < seriesLen; i++) { me.drawCharts(seriesItems[i]); } me.resizing = false; }, afterRender: function() { var me = this, legend = me.legend; me.callParent(arguments); if (me.categoryNames) { me.setCategoryNames(me.categoryNames); } if (legend) { legend.init(); } me.bindStore(me.store, true); me.refresh(); if (me.surface.engine === 'Vml') { me.on('added', me.onAddedVml, me); me.mon(me.hierarchyEventSource, 'added', me.onContainerAddedVml, me); } }, onAddedVml: function() { this.needsRedraw = true; }, onContainerAddedVml: function(container) { if (this.isDescendantOf(container)) { this.needsRedraw = true; } }, getEventXY: function(e) { var box = this.surface.getRegion(), pageXY = e.getXY(), x = pageXY[0] - box.left, y = pageXY[1] - box.top; return [x, y]; }, onClick: function(e) { this.handleClick('itemclick', e); }, onDblClick: function(e) { this.handleClick('itemdblclick', e); }, handleClick: function(name, e) { var me = this, position = me.getEventXY(e), seriesItems = me.series.items, i, ln, series, item; for (i = 0, ln = seriesItems.length; i < ln; i++) { series = seriesItems[i]; if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) { if (series.getItemForPoint) { item = series.getItemForPoint(position[0], position[1]); if (item) { series.fireEvent(name, item); } } } } }, onMouseDown: function(e) { var me = this, position = me.getEventXY(e), seriesItems = me.series.items, i, ln, series, item; if (me.enableMask) { me.mixins.mask.onMouseDown.call(me, e); } for (i = 0, ln = seriesItems.length; i < ln; i++) { series = seriesItems[i]; if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) { if (series.getItemForPoint) { item = series.getItemForPoint(position[0], position[1]); if (item) { series.fireEvent('itemmousedown', item); } } } } }, onMouseUp: function(e) { var me = this, position = me.getEventXY(e), seriesItems = me.series.items, i, ln, series, item; if (me.enableMask) { me.mixins.mask.onMouseUp.call(me, e); } for (i = 0, ln = seriesItems.length; i < ln; i++) { series = seriesItems[i]; if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) { if (series.getItemForPoint) { item = series.getItemForPoint(position[0], position[1]); if (item) { series.fireEvent('itemmouseup', item); } } } } }, onMouseMove: function(e) { var me = this, position = me.getEventXY(e), seriesItems = me.series.items, i, ln, series, item, last, storeItem, storeField; if (me.enableMask) { me.mixins.mask.onMouseMove.call(me, e); } for (i = 0, ln = seriesItems.length; i < ln; i++) { series = seriesItems[i]; if (Ext.draw.Draw.withinBox(position[0], position[1], series.bbox)) { if (series.getItemForPoint) { item = series.getItemForPoint(position[0], position[1]); last = series._lastItemForPoint; storeItem = series._lastStoreItem; storeField = series._lastStoreField; if (item !== last || item && (item.storeItem != storeItem || item.storeField != storeField)) { if (last) { series.fireEvent('itemmouseout', last); delete series._lastItemForPoint; delete series._lastStoreField; delete series._lastStoreItem; } if (item) { series.fireEvent('itemmouseover', item); series._lastItemForPoint = item; series._lastStoreItem = item.storeItem; series._lastStoreField = item.storeField; } } } } else { last = series._lastItemForPoint; if (last) { series.fireEvent('itemmouseout', last); delete series._lastItemForPoint; delete series._lastStoreField; delete series._lastStoreItem; } } } }, onMouseLeave: function(e) { var me = this, seriesItems = me.series.items, i, ln, series; if (me.enableMask) { me.mixins.mask.onMouseLeave.call(me, e); } for (i = 0, ln = seriesItems.length; i < ln; i++) { series = seriesItems[i]; delete series._lastItemForPoint; } }, delayRefresh: function() { var me = this; if (!me.refreshTask) { me.refreshTask = new Ext.util.DelayedTask(me.refresh, me); } me.refreshTask.delay(me.refreshBuffer); }, refresh: function() { var me = this; if (me.rendered && me.curWidth !== undefined && me.curHeight !== undefined) { if (!me.isVisible(true)) { if (!me.refreshPending) { me.setShowListeners('mon'); me.refreshPending = true; } return; } if (me.fireEvent('beforerefresh', me) !== false) { me.redraw(); me.fireEvent('refresh', me); } } }, onShow: function(){ var me = this; me.callParent(arguments); if (me.refreshPending) { me.delayRefresh(); me.setShowListeners('mun'); } delete me.refreshPending; }, setShowListeners: function(method){ var me = this; me[method](me.hierarchyEventSource, { scope: me, single: true, show: me.forceRefresh, expand: me.forceRefresh }); }, doRefresh: function(){ this.setSubStore(null); this.refresh(); }, forceRefresh: function(container) { var me = this; if (me.isDescendantOf(container) && me.refreshPending) { me.setShowListeners('mun'); me.delayRefresh(); } delete me.refreshPending; }, bindStore: function(store, initial) { var me = this; me.mixins.bindable.bindStore.apply(me, arguments); if (me.store && !initial) { me.refresh(); } }, getStoreListeners: function() { var refresh = this.doRefresh, delayRefresh = this.delayRefresh; return { refresh: refresh, add: delayRefresh, bulkremove: delayRefresh, update: delayRefresh, clear: refresh }; }, setSubStore: function(subStore){ this.substore = subStore; }, initializeAxis: function(axis) { var me = this, chartBBox = me.chartBBox, w = chartBBox.width, h = chartBBox.height, x = chartBBox.x, y = chartBBox.y, themeAttrs = me.themeAttrs, axes = me.axes, config = { chart: me }; if (themeAttrs) { config.axisStyle = Ext.apply({}, themeAttrs.axis); config.axisLabelLeftStyle = Ext.apply({}, themeAttrs.axisLabelLeft); config.axisLabelRightStyle = Ext.apply({}, themeAttrs.axisLabelRight); config.axisLabelTopStyle = Ext.apply({}, themeAttrs.axisLabelTop); config.axisLabelBottomStyle = Ext.apply({}, themeAttrs.axisLabelBottom); config.axisTitleLeftStyle = Ext.apply({}, themeAttrs.axisTitleLeft); config.axisTitleRightStyle = Ext.apply({}, themeAttrs.axisTitleRight); config.axisTitleTopStyle = Ext.apply({}, themeAttrs.axisTitleTop); config.axisTitleBottomStyle = Ext.apply({}, themeAttrs.axisTitleBottom); } switch (axis.position) { case 'top': Ext.apply(config, { length: w, width: h, x: x, y: y }); break; case 'bottom': Ext.apply(config, { length: w, width: h, x: x, y: h }); break; case 'left': Ext.apply(config, { length: h, width: w, x: x, y: h }); break; case 'right': Ext.apply(config, { length: h, width: w, x: w, y: h }); break; } if (!axis.chart) { Ext.apply(config, axis); axis = Ext.createByAlias('axis.' + axis.type.toLowerCase(), config); axes.replace(axis); } else { Ext.apply(axis, config); } axis.initialized = true; }, getInsets: function() { var me = this, insetPadding = me.insetPadding; return { top: insetPadding, right: insetPadding, bottom: insetPadding, left: insetPadding }; }, calculateInsets: function() { var me = this, legend = me.legend, axes = me.axes, edges = ['top', 'right', 'bottom', 'left'], insets, i, l, edge, isVertical, axis, bbox; function getAxis(edge) { var i = axes.findIndex('position', edge); return (i < 0) ? null : axes.getAt(i); } insets = me.getInsets(); for (i = 0, l = edges.length; i < l; i++) { edge = edges[i]; isVertical = (edge === 'left' || edge === 'right'); axis = getAxis(edge); if (legend !== false) { if (legend.position === edge) { bbox = legend.getBBox(); insets[edge] += (isVertical ? bbox.width : bbox.height) + me.insetPadding; } } if (axis && axis.bbox) { bbox = axis.bbox; insets[edge] += (isVertical ? bbox.width : bbox.height); } } return insets; }, alignAxes: function() { var me = this, axesItems = me.axes.items, insets, chartBBox, i, l, axis, pos, isVertical; insets = me.calculateInsets(); chartBBox = { x: insets.left, y: insets.top, width: me.curWidth - insets.left - insets.right, height: me.curHeight - insets.top - insets.bottom }; me.chartBBox = chartBBox; for (i = 0, l = axesItems.length; i < l; i++) { axis = axesItems[i]; pos = axis.position; isVertical = pos === 'left' || pos === 'right'; axis.x = (pos === 'right' ? chartBBox.x + chartBBox.width : chartBBox.x); axis.y = (pos === 'top' ? chartBBox.y : chartBBox.y + chartBBox.height); axis.width = (isVertical ? chartBBox.width : chartBBox.height); axis.length = (isVertical ? chartBBox.height : chartBBox.width); } }, initializeSeries: function(series, idx, themeIndex) { var me = this, themeAttrs = me.themeAttrs, seriesObj, markerObj, seriesThemes, st, markerThemes, colorArrayStyle = [], isInstance = (series instanceof Ext.chart.series.Series). i = 0, l, config; if (!series.initialized) { config = { chart: me, seriesId: series.seriesId }; if (themeAttrs) { seriesThemes = themeAttrs.seriesThemes; markerThemes = themeAttrs.markerThemes; seriesObj = Ext.apply({}, themeAttrs.series); markerObj = Ext.apply({}, themeAttrs.marker); config.seriesStyle = Ext.apply(seriesObj, seriesThemes[themeIndex % seriesThemes.length]); config.seriesLabelStyle = Ext.apply({}, themeAttrs.seriesLabel); config.markerStyle = Ext.apply(markerObj, markerThemes[themeIndex % markerThemes.length]); if (themeAttrs.colors) { config.colorArrayStyle = themeAttrs.colors; } else { colorArrayStyle = []; for (l = seriesThemes.length; i < l; i++) { st = seriesThemes[i]; if (st.fill || st.stroke) { colorArrayStyle.push(st.fill || st.stroke); } } if (colorArrayStyle.length) { config.colorArrayStyle = colorArrayStyle; } } config.seriesIdx = idx; config.themeIdx = themeIndex; } if (isInstance) { Ext.applyIf(series, config); } else { Ext.applyIf(config, series); series = me.series.replace(Ext.createByAlias('series.' + series.type.toLowerCase(), config)); } } series.initialize(); series.initialized = true; return series; }, getMaxGutters: function() { var me = this, seriesItems = me.series.items, i, ln, series, gutters, lowerH = 0, upperH = 0, lowerV = 0, upperV = 0; for (i = 0, ln = seriesItems.length; i < ln; i++) { gutters = seriesItems[i].getGutters(); if (gutters) { if (gutters.verticalAxis) { lowerV = Math.max(lowerV, gutters.lower); upperV = Math.max(upperV, gutters.upper); } else { lowerH = Math.max(lowerH, gutters.lower); upperH = Math.max(upperH, gutters.upper); } } } me.maxGutters = { left: lowerH, right: upperH, bottom: lowerV, top: upperV }; }, drawAxis: function(axis) { axis.drawAxis(); }, drawCharts: function(series) { series.triggerafterrender = false; series.drawSeries(); if (!this.animate) { series.fireEvent('afterrender', series); } }, save: function(config){ return Ext.draw.Surface.save(this.surface, config); }, destroy: function() { var me = this, task = me.refreshTask; if (task) { task.cancel(); me.refreshTask = null; } Ext.destroy(me.surface); me.bindStore(null); me.callParent(arguments); } }); Ext.define('Ext.chart.Highlight', { highlight: false, highlightCfg : { fill: '#fdd', "stroke-width": 5, stroke: '#f55' }, constructor: function(config) { if (config.highlight && (typeof config.highlight !== 'boolean')) { this.highlightCfg = Ext.merge({}, this.highlightCfg, config.highlight); } }, highlightItem: function(item) { if (!item) { return; } var me = this, sprite = item.sprite, opts = Ext.merge({}, me.highlightCfg, me.highlight), surface = me.chart.surface, animate = me.chart.animate, p, from, to, pi; if (!me.highlight || !sprite || sprite._highlighted) { return; } if (sprite._anim) { sprite._anim.paused = true; } sprite._highlighted = true; if (!sprite._defaults) { sprite._defaults = Ext.apply({}, sprite.attr); from = {}; to = {}; for (p in opts) { if (! (p in sprite._defaults)) { sprite._defaults[p] = surface.availableAttrs[p]; } from[p] = sprite._defaults[p]; to[p] = opts[p]; if (Ext.isObject(opts[p])) { from[p] = {}; to[p] = {}; Ext.apply(sprite._defaults[p], sprite.attr[p]); Ext.apply(from[p], sprite._defaults[p]); for (pi in sprite._defaults[p]) { if (! (pi in opts[p])) { to[p][pi] = from[p][pi]; } else { to[p][pi] = opts[p][pi]; } } for (pi in opts[p]) { if (! (pi in to[p])) { to[p][pi] = opts[p][pi]; } } } } sprite._from = from; sprite._to = to; sprite._endStyle = to; } if (animate) { sprite._anim = new Ext.fx.Anim({ target: sprite, from: sprite._from, to: sprite._to, duration: 150 }); } else { sprite.setAttributes(sprite._to, true); } }, unHighlightItem: function() { if (!this.highlight || !this.items) { return; } var me = this, items = me.items, len = items.length, opts = Ext.merge({}, me.highlightCfg, me.highlight), animate = me.chart.animate, i = 0, obj, p, sprite; for (; i < len; i++) { if (!items[i]) { continue; } sprite = items[i].sprite; if (sprite && sprite._highlighted) { if (sprite._anim) { sprite._anim.paused = true; } obj = {}; for (p in opts) { if (Ext.isObject(sprite._defaults[p])) { obj[p] = Ext.apply({}, sprite._defaults[p]); } else { obj[p] = sprite._defaults[p]; } } if (animate) { sprite._endStyle = obj; sprite._anim = new Ext.fx.Anim({ target: sprite, to: obj, duration: 150 }); } else { sprite.setAttributes(obj, true); } delete sprite._highlighted; } } }, cleanHighlights: function() { if (!this.highlight) { return; } var group = this.group, markerGroup = this.markerGroup, i = 0, l; for (l = group.getCount(); i < l; i++) { delete group.getAt(i)._defaults; } if (markerGroup) { for (l = markerGroup.getCount(); i < l; i++) { delete markerGroup.getAt(i)._defaults; } } } }); Ext.define('Ext.chart.Label', { colorStringRe: /url\s*\(\s*#([^\/)]+)\s*\)/, constructor: function(config) { var me = this; me.label = Ext.applyIf(me.label || {}, { display: "none", stackedDisplay: "none", color: "#000", field: "name", minMargin: 50, font: "11px Helvetica, sans-serif", orientation: "horizontal", renderer: Ext.identityFn }); if (me.label.display !== 'none') { me.labelsGroup = me.chart.surface.getGroup(me.seriesId + '-labels'); } }, renderLabels: function() { var me = this, chart = me.chart, gradients = chart.gradients, items = me.items, animate = chart.animate, config = me.label, display = config.display, stackedDisplay = config.stackedDisplay, format = config.renderer, color = config.color, field = [].concat(config.field), group = me.labelsGroup, groupLength = (group || 0) && group.length, store = me.chart.getChartStore(), len = store.getCount(), itemLength = (items || 0) && items.length, ratio = itemLength / len, gradientsCount = (gradients || 0) && gradients.length, Color = Ext.draw.Color, hides = [], gradient, i, count, groupIndex, index, j, k, colorStopTotal, colorStopIndex, colorStop, item, label, storeItem, sprite, spriteColor, spriteBrightness, labelColor, colorString, total, totalPositive, totalNegative, topText, bottomText; if (display == 'none' || !group) { return; } if(itemLength == 0){ while(groupLength--) { hides.push(groupLength); } } else { for (i = 0, count = 0, groupIndex = 0; i < len; i++) { index = 0; for (j = 0; j < ratio; j++) { item = items[count]; label = group.getAt(groupIndex); storeItem = store.getAt(i); while(this.__excludes && this.__excludes[index]) { index++; } if (!item && label) { label.hide(true); groupIndex++; } if (item && field[j]) { if (!label) { label = me.onCreateLabel(storeItem, item, i, display); if (!label) { break; } } label.setAttributes({ fill: String(color) }, true); me.onPlaceLabel(label, storeItem, item, i, display, animate, index); groupIndex++; if (config.contrast && item.sprite) { sprite = item.sprite; if (animate && sprite._endStyle) { colorString = sprite._endStyle.fill; } else if (animate && sprite._to) { colorString = sprite._to.fill; } else { colorString = sprite.attr.fill; } colorString = colorString || sprite.attr.fill; spriteColor = Color.fromString(colorString); if (colorString && !spriteColor) { colorString = colorString.match(me.colorStringRe)[1]; for (k = 0; k < gradientsCount; k++) { gradient = gradients[k]; if (gradient.id == colorString) { colorStop = 0; colorStopTotal = 0; for (colorStopIndex in gradient.stops) { colorStop++; colorStopTotal += Color.fromString(gradient.stops[colorStopIndex].color).getGrayscale(); } spriteBrightness = (colorStopTotal / colorStop) / 255; break; } } } else { spriteBrightness = spriteColor.getGrayscale() / 255; } if (label.isOutside) { spriteBrightness = 1; } labelColor = Color.fromString(label.attr.fill || label.attr.color).getHSL(); labelColor[2] = spriteBrightness > 0.5 ? 0.2 : 0.8; label.setAttributes({ fill: String(Color.fromHSL.apply({}, labelColor)) }, true); } if (me.stacked && stackedDisplay && (item.totalPositiveValues || item.totalNegativeValues)) { totalPositive = (item.totalPositiveValues || 0); totalNegative = (item.totalNegativeValues || 0); total = totalPositive + totalNegative; if (stackedDisplay == 'total') { topText = format(total); } else if (stackedDisplay == 'balances') { if (totalPositive == 0 && totalNegative == 0) { topText = format(0); } else { topText = format(totalPositive); bottomText = format(totalNegative); } } if (topText) { label = group.getAt(groupIndex); if (!label) { label = me.onCreateLabel(storeItem, item, i, 'over'); } labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL(); label.setAttributes({ text: topText, style: config.font, fill: String(Color.fromHSL.apply({}, labelColor)) }, true); me.onPlaceLabel(label, storeItem, item, i, 'over', animate, index); groupIndex ++; } if (bottomText) { label = group.getAt(groupIndex); if (!label) { label = me.onCreateLabel(storeItem, item, i, 'under'); } labelColor = Color.fromString(label.attr.color || label.attr.fill).getHSL(); label.setAttributes({ text: bottomText, style: config.font, fill: String(Color.fromHSL.apply({}, labelColor)) }, true); me.onPlaceLabel(label, storeItem, item, i, 'under', animate, index); groupIndex ++; } } } count++; index++; } } groupLength = group.length; while(groupLength > groupIndex){ hides.push(groupIndex); groupIndex++; } } me.hideLabels(hides); }, hideLabels: function(hides){ var labelsGroup = this.labelsGroup, hlen = !!hides && hides.length; if (!labelsGroup) { return; } if (hlen === false) { hlen = labelsGroup.getCount(); while (hlen--) { labelsGroup.getAt(hlen).hide(true); } } else { while(hlen--) { labelsGroup.getAt(hides[hlen]).hide(true); } } } }); Ext.define('Ext.chart.TipSurface', { extend: Ext.draw.Component , spriteArray: false, renderFirst: true, constructor: function(config) { this.callParent([config]); if (config.sprites) { this.spriteArray = [].concat(config.sprites); delete config.sprites; } }, onRender: function() { var me = this, i = 0, l = 0, sp, sprites; this.callParent(arguments); sprites = me.spriteArray; if (me.renderFirst && sprites) { me.renderFirst = false; for (l = sprites.length; i < l; i++) { sp = me.surface.add(sprites[i]); sp.setAttributes({ hidden: false }, true); } } } }); Ext.define('Ext.chart.Tip', { constructor: function(config) { var me = this, surface, sprites, tipSurface; if (config.tips) { me.tipTimeout = null; me.tipConfig = Ext.apply({}, config.tips, { renderer: Ext.emptyFn, constrainPosition: true, autoHide: true, shrinkWrapDock: true }); me.tooltip = new Ext.tip.ToolTip(me.tipConfig); me.chart.surface.on('mousemove', me.tooltip.onMouseMove, me.tooltip); me.chart.surface.on('mouseleave', function() { me.hideTip(); }); if (me.tipConfig.surface) { surface = me.tipConfig.surface; sprites = surface.sprites; tipSurface = new Ext.chart.TipSurface({ id: 'tipSurfaceComponent', sprites: sprites }); if (surface.width && surface.height) { tipSurface.setSize(surface.width, surface.height); } me.tooltip.add(tipSurface); me.spriteTip = tipSurface; } } }, showTip: function(item) { var me = this, tooltip, spriteTip, tipConfig, trackMouse, sprite, surface, surfaceExt, pos, x, y; if (!me.tooltip) { return; } clearTimeout(me.tipTimeout); tooltip = me.tooltip; spriteTip = me.spriteTip; tipConfig = me.tipConfig; trackMouse = tooltip.trackMouse; if (!trackMouse) { tooltip.trackMouse = true; sprite = item.sprite; surface = sprite.surface; surfaceExt = Ext.get(surface.getId()); if (surfaceExt) { pos = surfaceExt.getXY(); x = pos[0] + (sprite.attr.x || 0) + (sprite.attr.translation && sprite.attr.translation.x || 0); y = pos[1] + (sprite.attr.y || 0) + (sprite.attr.translation && sprite.attr.translation.y || 0); tooltip.targetXY = [x, y]; } } if (spriteTip) { tipConfig.renderer.call(tooltip, item.storeItem, item, spriteTip.surface); } else { tipConfig.renderer.call(tooltip, item.storeItem, item); } tooltip.delayShow(); tooltip.trackMouse = trackMouse; }, hideTip: function(item) { var tooltip = this.tooltip; if (!tooltip) { return; } clearTimeout(this.tipTimeout); this.tipTimeout = setTimeout(function() { tooltip.delayHide(); }, 0); } }); Ext.define('Ext.chart.axis.Abstract', { constructor: function(config) { config = config || {}; var me = this, pos = config.position || 'left'; pos = pos.charAt(0).toUpperCase() + pos.substring(1); config.label = Ext.apply(config['axisLabel' + pos + 'Style'] || {}, config.label || {}); config.axisTitleStyle = Ext.apply(config['axisTitle' + pos + 'Style'] || {}, config.labelTitle || {}); Ext.apply(me, config); me.fields = Ext.Array.from(me.fields); this.callParent(); me.labels = []; me.getId(); me.labelGroup = me.chart.surface.getGroup(me.axisId + "-labels"); }, alignment: null, grid: false, steps: 10, x: 0, y: 0, minValue: 0, maxValue: 0, getId: function() { return this.axisId || (this.axisId = Ext.id(null, 'ext-axis-')); }, processView: Ext.emptyFn, drawAxis: Ext.emptyFn, addDisplayAndLabels: Ext.emptyFn }); Ext.define('Ext.chart.axis.Axis', { extend: Ext.chart.axis.Abstract , alternateClassName: 'Ext.chart.Axis', hidden: false, forceMinMax: false, dashSize: 3, position: 'bottom', skipFirst: false, length: 0, width: 0, adjustEnd: true, majorTickSteps: false, nullGutters: { lower: 0, upper: 0, verticalAxis: undefined }, applyData: Ext.emptyFn, getRange: function () { var me = this, chart = me.chart, store = chart.getChartStore(), data = store.data.items, series = chart.series.items, position = me.position, axes, seriesClasses = Ext.chart.series, aggregations = [], min = Infinity, max = -Infinity, vertical = me.position === 'left' || me.position === 'right' || me.position === 'radial', i, ln, ln2, j, k, dataLength = data.length, aggregates, countedFields = {}, allFields = {}, excludable = true, fields, fieldMap, record, field, value; fields = me.fields; for (j = 0, ln = fields.length; j < ln; j++) { allFields[fields[j]] = true; } for (i = 0, ln = series.length; i < ln; i++) { if (series[i].seriesIsHidden) { continue; } if (!series[i].getAxesForXAndYFields) { continue; } axes = series[i].getAxesForXAndYFields(); if (axes.xAxis && axes.xAxis !== position && axes.yAxis && axes.yAxis !== position) { continue; } if (seriesClasses.Bar && series[i] instanceof seriesClasses.Bar && !series[i].column) { fields = vertical ? Ext.Array.from(series[i].xField) : Ext.Array.from(series[i].yField); } else { fields = vertical ? Ext.Array.from(series[i].yField) : Ext.Array.from(series[i].xField); } if (me.fields.length) { for (j = 0, ln2 = fields.length; j < ln2; j++) { if (allFields[fields[j]]) { break; } } if (j == ln2) { continue; } } if (aggregates = series[i].stacked) { if (seriesClasses.Bar && series[i] instanceof seriesClasses.Bar) { if (series[i].column != vertical) { aggregates = false; excludable = false; } } else if (!vertical) { aggregates = false; excludable = false; } } if (aggregates) { fieldMap = {}; for (j = 0; j < fields.length; j++) { if (excludable && series[i].__excludes && series[i].__excludes[j]) { continue; } if (!allFields[fields[j]]) { Ext.Logger.warn('Field `' + fields[j] + '` is not included in the ' + position + ' axis config.'); } allFields[fields[j]] = fieldMap[fields[j]] = true; } aggregations.push({ fields: fieldMap, positiveValue: 0, negativeValue: 0 }); } else { if (!fields || fields.length == 0) { fields = me.fields; } for (j = 0; j < fields.length; j++) { if (excludable && series[i].__excludes && series[i].__excludes[j]) { continue; } allFields[fields[j]] = countedFields[fields[j]] = true; } } } for (i = 0; i < dataLength; i++) { record = data[i]; for (k = 0; k < aggregations.length; k++) { aggregations[k].positiveValue = 0; aggregations[k].negativeValue = 0; } for (field in allFields) { value = record.get(field); if (me.type == 'Time' && typeof value == "string") { value = Date.parse(value); } if (isNaN(value)) { continue; } if (value === undefined) { value = 0; } else { value = Number(value); } if (countedFields[field]) { if (min > value) { min = value; } if (max < value) { max = value; } } for (k = 0; k < aggregations.length; k++) { if (aggregations[k].fields[field]) { if (value >= 0) { aggregations[k].positiveValue += value; if (max < aggregations[k].positiveValue) { max = aggregations[k].positiveValue; } if (min > 0) { min = 0; } } else { aggregations[k].negativeValue += value; if (min > aggregations[k].negativeValue) { min = aggregations[k].negativeValue; } if (max < 0) { max = 0; } } } } } } if (!isFinite(max)) { max = me.prevMax || 0; } if (!isFinite(min)) { min = me.prevMin || 0; } if (typeof min === 'number') { min = Ext.Number.correctFloat(min); } if (typeof max === 'number') { max = Ext.Number.correctFloat(max); } if (min != max && (max != Math.floor(max) || min != Math.floor(min))) { min = Math.floor(min); max = Math.floor(max) + 1; } if (!isNaN(me.minimum)) { min = me.minimum; } if (!isNaN(me.maximum)) { max = me.maximum; } if (min >= max) { min = Math.floor(min); max = min + 1; } return {min: min, max: max}; }, calcEnds: function () { var me = this, range = me.getRange(), min = range.min, max = range.max, steps, prettyNumbers, out, changedRange; steps = (Ext.isNumber(me.majorTickSteps) ? me.majorTickSteps + 1 : me.steps); prettyNumbers = !(Ext.isNumber(me.maximum) && Ext.isNumber(me.minimum) && Ext.isNumber(me.majorTickSteps) && me.majorTickSteps > 0); out = Ext.draw.Draw.snapEnds(min, max, steps, prettyNumbers); if (Ext.isNumber(me.maximum)) { out.to = me.maximum; changedRange = true; } if (Ext.isNumber(me.minimum)) { out.from = me.minimum; changedRange = true; } if (me.adjustMaximumByMajorUnit) { out.to = Math.ceil(out.to / out.step) * out.step; changedRange = true; } if (me.adjustMinimumByMajorUnit) { out.from = Math.floor(out.from / out.step) * out.step; changedRange = true; } if (changedRange) { out.steps = Math.ceil((out.to - out.from) / out.step); } me.prevMin = (min == max ? 0 : min); me.prevMax = max; return out; }, drawAxis: function (init) { var me = this, i, x = me.x, y = me.y, dashSize = me.dashSize, length = me.length, position = me.position, verticalAxis = (position == 'left' || position == 'right'), inflections = [], calcLabels = (me.isNumericAxis), stepCalcs = me.applyData(), step = stepCalcs.step, steps = stepCalcs.steps, stepsArray = Ext.isArray(steps), from = stepCalcs.from, to = stepCalcs.to, axisRange = (to - from) || 1, trueLength, currentX, currentY, path, subDashesX = me.minorTickSteps || 0, subDashesY = me.minorTickSteps || 0, dashesX = Math.max(subDashesX + 1, 0), dashesY = Math.max(subDashesY + 1, 0), dashDirection = (position == 'left' || position == 'top' ? -1 : 1), dashLength = dashSize * dashDirection, series = me.chart.series.items, firstSeries = series[0], gutters = Ext.clone(firstSeries ? firstSeries.nullGutters : me.nullGutters), seriesGutters, hasGutters, sameDirectionGutters, padding, subDashes, subDashValue, delta = 0, stepCount = 0, tick, axes, ln, val, begin, end; me.from = from; me.to = to; if (me.hidden || (from > to)) { return; } if ((stepsArray && (steps.length == 0)) || (!stepsArray && isNaN(step))) { return; } if (stepsArray) { steps = Ext.Array.filter(steps, function(elem, index, array) { return (+elem > +me.from && +elem < +me.to); }, this); steps = Ext.Array.union([me.from], steps, [me.to]); } else { steps = new Array; for (val = +me.from; val < +me.to; val += step) { steps.push(val); } steps.push(+me.to); } stepCount = steps.length; for (i = 0, ln = series.length; i < ln; i++) { if (series[i].seriesIsHidden) { continue; } if (!series[i].getAxesForXAndYFields) { continue; } axes = series[i].getAxesForXAndYFields(); if (!axes.xAxis || !axes.yAxis || (axes.xAxis === position) || (axes.yAxis === position)) { seriesGutters = Ext.clone(series[i].getGutters()); hasGutters = (seriesGutters.verticalAxis !== undefined); sameDirectionGutters = (hasGutters && (seriesGutters.verticalAxis == verticalAxis)); if (hasGutters) { if (!sameDirectionGutters) { padding = series[i].getPadding(); if (verticalAxis) { seriesGutters = { lower: padding.bottom, upper: padding.top, verticalAxis: true }; } else { seriesGutters = { lower: padding.left, upper: padding.right, verticalAxis: false }; } } if (gutters.lower < seriesGutters.lower) { gutters.lower = seriesGutters.lower; } if (gutters.upper < seriesGutters.upper) { gutters.upper = seriesGutters.upper; } gutters.verticalAxis = verticalAxis; } } } if (calcLabels) { me.labels = []; } if (gutters) { if (verticalAxis) { currentX = Math.floor(x); path = ["M", currentX + 0.5, y, "l", 0, -length]; trueLength = length - (gutters.lower + gutters.upper); for (tick = 0; tick < stepCount; tick++) { currentY = y - gutters.lower - (steps[tick] - steps[0]) * trueLength / axisRange; path.push("M", currentX, Math.floor(currentY) + 0.5, "l", dashLength * 2, 0); inflections.push([ currentX, Math.floor(currentY) ]); if (calcLabels) { me.labels.push(steps[tick]); } } } else { currentY = Math.floor(y); path = ["M", x, currentY + 0.5, "l", length, 0]; trueLength = length - (gutters.lower + gutters.upper); for (tick = 0; tick < stepCount; tick++) { currentX = x + gutters.lower + (steps[tick] - steps[0]) * trueLength / axisRange; path.push("M", Math.floor(currentX) + 0.5, currentY, "l", 0, dashLength * 2 + 1); inflections.push([ Math.floor(currentX), currentY ]); if (calcLabels) { me.labels.push(steps[tick]); } } } } subDashes = (verticalAxis ? subDashesY : subDashesX); if (Ext.isArray(subDashes)) { if (subDashes.length == 2) { subDashValue = +Ext.Date.add(new Date(), subDashes[0], subDashes[1]) - Date.now(); } else { subDashValue = subDashes[0]; } } else { if (Ext.isNumber(subDashes) && subDashes > 0) { subDashValue = step / (subDashes + 1); } } if (gutters && subDashValue) { for (tick = 0; tick < stepCount - 1; tick++) { begin = +steps[tick]; end = +steps[tick+1]; if (verticalAxis) { for (value = begin + subDashValue; value < end; value += subDashValue) { currentY = y - gutters.lower - (value - steps[0]) * trueLength / axisRange; path.push("M", currentX, Math.floor(currentY) + 0.5, "l", dashLength, 0); } } else { for (value = begin + subDashValue; value < end; value += subDashValue) { currentX = x + gutters.upper + (value - steps[0]) * trueLength / axisRange; path.push("M", Math.floor(currentX) + 0.5, currentY, "l", 0, dashLength + 1); } } } } if (!me.axis) { me.axis = me.chart.surface.add(Ext.apply({ type: 'path', path: path }, me.axisStyle)); } me.axis.setAttributes({ path: path }, true); me.inflections = inflections; if (!init && me.grid) { me.drawGrid(); } me.axisBBox = me.axis.getBBox(); me.drawLabel(); }, drawGrid: function () { var me = this, surface = me.chart.surface, grid = me.grid, odd = grid.odd, even = grid.even, inflections = me.inflections, ln = inflections.length - ((odd || even) ? 0 : 1), position = me.position, maxGutters = me.chart.maxGutters, width = me.width - 2, point, prevPoint, i = 1, path = [], styles, lineWidth, dlineWidth, oddPath = [], evenPath = []; if (((maxGutters.bottom !== 0 || maxGutters.top !== 0) && (position == 'left' || position == 'right')) || ((maxGutters.left !== 0 || maxGutters.right !== 0) && (position == 'top' || position == 'bottom'))) { i = 0; ln++; } for (; i < ln; i++) { point = inflections[i]; prevPoint = inflections[i - 1]; if (odd || even) { path = (i % 2) ? oddPath : evenPath; styles = ((i % 2) ? odd : even) || {}; lineWidth = (styles.lineWidth || styles['stroke-width'] || 0) / 2; dlineWidth = 2 * lineWidth; if (position == 'left') { path.push("M", prevPoint[0] + 1 + lineWidth, prevPoint[1] + 0.5 - lineWidth, "L", prevPoint[0] + 1 + width - lineWidth, prevPoint[1] + 0.5 - lineWidth, "L", point[0] + 1 + width - lineWidth, point[1] + 0.5 + lineWidth, "L", point[0] + 1 + lineWidth, point[1] + 0.5 + lineWidth, "Z"); } else if (position == 'right') { path.push("M", prevPoint[0] - lineWidth, prevPoint[1] + 0.5 - lineWidth, "L", prevPoint[0] - width + lineWidth, prevPoint[1] + 0.5 - lineWidth, "L", point[0] - width + lineWidth, point[1] + 0.5 + lineWidth, "L", point[0] - lineWidth, point[1] + 0.5 + lineWidth, "Z"); } else if (position == 'top') { path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + lineWidth, "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] + 1 + width - lineWidth, "L", point[0] + 0.5 - lineWidth, point[1] + 1 + width - lineWidth, "L", point[0] + 0.5 - lineWidth, point[1] + 1 + lineWidth, "Z"); } else { path.push("M", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - lineWidth, "L", prevPoint[0] + 0.5 + lineWidth, prevPoint[1] - width + lineWidth, "L", point[0] + 0.5 - lineWidth, point[1] - width + lineWidth, "L", point[0] + 0.5 - lineWidth, point[1] - lineWidth, "Z"); } } else { if (position == 'left') { path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", width, 0]); } else if (position == 'right') { path = path.concat(["M", point[0] - 0.5, point[1] + 0.5, "l", -width, 0]); } else if (position == 'top') { path = path.concat(["M", point[0] + 0.5, point[1] + 0.5, "l", 0, width]); } else { path = path.concat(["M", point[0] + 0.5, point[1] - 0.5, "l", 0, -width]); } } } if (odd || even) { if (oddPath.length) { if (!me.gridOdd && oddPath.length) { me.gridOdd = surface.add({ type: 'path', path: oddPath }); } me.gridOdd.setAttributes(Ext.apply({ path: oddPath, hidden: false }, odd || {}), true); } if (evenPath.length) { if (!me.gridEven) { me.gridEven = surface.add({ type: 'path', path: evenPath }); } me.gridEven.setAttributes(Ext.apply({ path: evenPath, hidden: false }, even || {}), true); } } else { if (path.length) { if (!me.gridLines) { me.gridLines = me.chart.surface.add({ type: 'path', path: path, "stroke-width": me.lineWidth || 1, stroke: me.gridColor || '#ccc' }); } me.gridLines.setAttributes({ hidden: false, path: path }, true); } else if (me.gridLines) { me.gridLines.hide(true); } } }, getOrCreateLabel: function (i, text) { var me = this, labelGroup = me.labelGroup, textLabel = labelGroup.getAt(i), surface = me.chart.surface; if (textLabel) { if (text != textLabel.attr.text) { textLabel.setAttributes(Ext.apply({ text: text }, me.label), true); textLabel._bbox = textLabel.getBBox(); } } else { textLabel = surface.add(Ext.apply({ group: labelGroup, type: 'text', x: 0, y: 0, text: text }, me.label)); surface.renderItem(textLabel); textLabel._bbox = textLabel.getBBox(); } if (me.label.rotation) { textLabel.setAttributes({ rotation: { degrees: 0 } }, true); textLabel._ubbox = textLabel.getBBox(); textLabel.setAttributes(me.label, true); } else { textLabel._ubbox = textLabel._bbox; } return textLabel; }, rect2pointArray: function (sprite) { var surface = this.chart.surface, rect = surface.getBBox(sprite, true), p1 = [rect.x, rect.y], p1p = p1.slice(), p2 = [rect.x + rect.width, rect.y], p2p = p2.slice(), p3 = [rect.x + rect.width, rect.y + rect.height], p3p = p3.slice(), p4 = [rect.x, rect.y + rect.height], p4p = p4.slice(), matrix = sprite.matrix; p1[0] = matrix.x.apply(matrix, p1p); p1[1] = matrix.y.apply(matrix, p1p); p2[0] = matrix.x.apply(matrix, p2p); p2[1] = matrix.y.apply(matrix, p2p); p3[0] = matrix.x.apply(matrix, p3p); p3[1] = matrix.y.apply(matrix, p3p); p4[0] = matrix.x.apply(matrix, p4p); p4[1] = matrix.y.apply(matrix, p4p); return [p1, p2, p3, p4]; }, intersect: function (l1, l2) { var r1 = this.rect2pointArray(l1), r2 = this.rect2pointArray(l2); return !!Ext.draw.Draw.intersect(r1, r2).length; }, drawHorizontalLabels: function () { var me = this, labelConf = me.label, floor = Math.floor, max = Math.max, axes = me.chart.axes, insetPadding = me.chart.insetPadding, gutters = me.chart.maxGutters, position = me.position, inflections = me.inflections, ln = inflections.length, labels = me.labels, maxHeight = 0, ratio, bbox, point, prevLabel, prevLabelId, adjustEnd = me.adjustEnd, hasLeft = axes.findIndex('position', 'left') != -1, hasRight = axes.findIndex('position', 'right') != -1, reverse = me.reverse, textLabel, text, idx, last, x, y, i, firstLabel; last = ln - 1; point = inflections[0]; firstLabel = me.getOrCreateLabel(0, me.label.renderer(labels[0])); ratio = Math.floor(Math.abs(Math.sin(labelConf.rotate && (labelConf.rotate.degrees * Math.PI / 180) || 0))); for (i = 0; i < ln; i++) { point = inflections[i]; idx = i; if (reverse) { idx = ln - i - 1; } text = me.label.renderer(labels[idx]); textLabel = me.getOrCreateLabel(i, text); bbox = textLabel._bbox; maxHeight = max(maxHeight, bbox.height + me.dashSize + me.label.padding); x = floor(point[0] - (ratio ? bbox.height : bbox.width) / 2); if (adjustEnd && gutters.left == 0 && gutters.right == 0) { if (i == 0 && !hasLeft) { x = point[0]; } else if (i == last && !hasRight) { x = Math.min(x, point[0] - bbox.width + insetPadding); } } if (position == 'top') { y = point[1] - (me.dashSize * 2) - me.label.padding - (bbox.height / 2); } else { y = point[1] + (me.dashSize * 2) + me.label.padding + (bbox.height / 2); } textLabel.setAttributes({ hidden: false, x: x, y: y }, true); if (i != 0 && (me.intersect(textLabel, prevLabel) || me.intersect(textLabel, firstLabel))) { if (i === last && prevLabelId !== 0) { prevLabel.hide(true); } else { textLabel.hide(true); continue; } } prevLabel = textLabel; prevLabelId = i; } return maxHeight; }, drawVerticalLabels: function () { var me = this, inflections = me.inflections, position = me.position, ln = inflections.length, chart = me.chart, insetPadding = chart.insetPadding, labels = me.labels, maxWidth = 0, max = Math.max, floor = Math.floor, ceil = Math.ceil, axes = me.chart.axes, gutters = me.chart.maxGutters, bbox, point, prevLabel, prevLabelId, hasTop = axes.findIndex('position', 'top') != -1, hasBottom = axes.findIndex('position', 'bottom') != -1, adjustEnd = me.adjustEnd, textLabel, text, last = ln - 1, x, y, i; for (i = 0; i < ln; i++) { point = inflections[i]; text = me.label.renderer(labels[i]); textLabel = me.getOrCreateLabel(i, text); bbox = textLabel._bbox; maxWidth = max(maxWidth, bbox.width + me.dashSize + me.label.padding); y = point[1]; if (adjustEnd && (gutters.bottom + gutters.top) < bbox.height / 2) { if (i == last && !hasTop) { y = Math.max(y, me.y - me.length + ceil(bbox.height / 2) - insetPadding); } else if (i == 0 && !hasBottom) { y = me.y + gutters.bottom - floor(bbox.height / 2); } } if (position == 'left') { x = point[0] - bbox.width - me.dashSize - me.label.padding - 2; } else { x = point[0] + me.dashSize + me.label.padding + 2; } textLabel.setAttributes(Ext.apply({ hidden: false, x: x, y: y }, me.label), true); if (i != 0 && me.intersect(textLabel, prevLabel)) { if (i === last && prevLabelId !== 0) { prevLabel.hide(true); } else { textLabel.hide(true); continue; } } prevLabel = textLabel; prevLabelId = i; } return maxWidth; }, drawLabel: function () { var me = this, position = me.position, labelGroup = me.labelGroup, inflections = me.inflections, maxWidth = 0, maxHeight = 0, ln, i; if (position == 'left' || position == 'right') { maxWidth = me.drawVerticalLabels(); } else { maxHeight = me.drawHorizontalLabels(); } ln = labelGroup.getCount(); i = inflections.length; for (; i < ln; i++) { labelGroup.getAt(i).hide(true); } me.bbox = {}; Ext.apply(me.bbox, me.axisBBox); me.bbox.height = maxHeight; me.bbox.width = maxWidth; if (Ext.isString(me.title)) { me.drawTitle(maxWidth, maxHeight); } }, setTitle: function (title) { this.title = title; this.drawLabel(); }, drawTitle: function (maxWidth, maxHeight) { var me = this, position = me.position, surface = me.chart.surface, displaySprite = me.displaySprite, title = me.title, rotate = (position == 'left' || position == 'right'), x = me.x, y = me.y, base, bbox, pad; if (displaySprite) { displaySprite.setAttributes({text: title}, true); } else { base = { type: 'text', x: 0, y: 0, text: title }; displaySprite = me.displaySprite = surface.add(Ext.apply(base, me.axisTitleStyle, me.labelTitle)); surface.renderItem(displaySprite); } bbox = displaySprite.getBBox(); pad = me.dashSize + me.label.padding; if (rotate) { y -= ((me.length / 2) - (bbox.height / 2)); if (position == 'left') { x -= (maxWidth + pad + (bbox.width / 2)); } else { x += (maxWidth + pad + bbox.width - (bbox.width / 2)); } me.bbox.width += bbox.width + 10; } else { x += (me.length / 2) - (bbox.width * 0.5); if (position == 'top') { y -= (maxHeight + pad + (bbox.height * 0.3)); } else { y += (maxHeight + pad + (bbox.height * 0.8)); } me.bbox.height += bbox.height + 10; } displaySprite.setAttributes({ translate: { x: x, y: y } }, true); } }); Ext.define('Ext.chart.axis.Category', { extend: Ext.chart.axis.Axis , alternateClassName: 'Ext.chart.CategoryAxis', alias: 'axis.category', isCategoryAxis: true, doConstrain: function() { var me = this, chart = me.chart, store = chart.getChartStore(), items = store.data.items, series = chart.series.items, seriesLength = series.length, data = [], i for (i = 0; i < seriesLength; i++) { if (series[i].type === 'bar' && series[i].stacked) { return; } } for (i = me.minimum; i < me.maximum; i++) { data.push(items[i]); } chart.setSubStore(new Ext.data.Store({ model: store.model, data: data })); }, setLabels: function() { var store = this.chart.getChartStore(), data = store.data.items, d, dLen, record, fields = this.fields, ln = fields.length, labels, name, i; labels = this.labels = []; for (d = 0, dLen = data.length; d < dLen; d++) { record = data[d]; for (i = 0; i < ln; i++) { name = record.get(fields[i]); labels.push(name); } } }, applyData: function() { this.callParent(); this.setLabels(); var count = this.chart.getChartStore().getCount(); return { from: 0, to: count - 1, power: 1, step: 1, steps: count - 1 }; } }); Ext.define('Ext.chart.axis.Gauge', { extend: Ext.chart.axis.Abstract , position: 'gauge', alias: 'axis.gauge', drawAxis: function(init) { var chart = this.chart, surface = chart.surface, bbox = chart.chartBBox, centerX = bbox.x + (bbox.width / 2), centerY = bbox.y + bbox.height, margin = this.margin || 10, rho = Math.min(bbox.width, 2 * bbox.height) /2 + margin, sprites = [], sprite, steps = this.steps, i, pi = Math.PI, cos = Math.cos, sin = Math.sin; if (this.sprites && !chart.resizing) { this.drawLabel(); return; } if (this.margin >= 0) { if (!this.sprites) { for (i = 0; i <= steps; i++) { sprite = surface.add({ type: 'path', path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi), centerY + (rho - margin) * sin(i / steps * pi - pi), 'L', centerX + rho * cos(i / steps * pi - pi), centerY + rho * sin(i / steps * pi - pi), 'Z'], stroke: '#ccc' }); sprite.setAttributes({ hidden: false }, true); sprites.push(sprite); } } else { sprites = this.sprites; for (i = 0; i <= steps; i++) { sprites[i].setAttributes({ path: ['M', centerX + (rho - margin) * cos(i / steps * pi - pi), centerY + (rho - margin) * sin(i / steps * pi - pi), 'L', centerX + rho * cos(i / steps * pi - pi), centerY + rho * sin(i / steps * pi - pi), 'Z'], stroke: '#ccc' }, true); } } } this.sprites = sprites; this.drawLabel(); if (this.title) { this.drawTitle(); } }, drawTitle: function() { var me = this, chart = me.chart, surface = chart.surface, bbox = chart.chartBBox, labelSprite = me.titleSprite, labelBBox; if (!labelSprite) { me.titleSprite = labelSprite = surface.add(Ext.apply({ type: 'text', zIndex: 2 }, me.axisTitleStyle, me.labelTitle)); } labelSprite.setAttributes(Ext.apply({ text: me.title }, me.label || {}), true); labelBBox = labelSprite.getBBox(); labelSprite.setAttributes({ x: bbox.x + (bbox.width / 2) - (labelBBox.width / 2), y: bbox.y + bbox.height - (labelBBox.height / 2) - 4 }, true); }, setTitle: function(title) { this.title = title; this.drawTitle(); }, drawLabel: function() { var me = this, chart = me.chart, surface = chart.surface, bbox = chart.chartBBox, centerX = bbox.x + (bbox.width / 2), centerY = bbox.y + bbox.height, margin = me.margin || 10, rho = Math.min(bbox.width, 2 * bbox.height) /2 + 2 * margin, round = Math.round, labelArray = [], label, maxValue = me.maximum || 0, minValue = me.minimum || 0, steps = me.steps, pi = Math.PI, cos = Math.cos, sin = Math.sin, labelConf = this.label, renderer = labelConf.renderer || Ext.identityFn, reverse = me.reverse, i, adjY, idx; if (!this.labelArray) { for (i = 0; i <= steps; i++) { adjY = (i === 0 || i === steps) ? 7 : 0; idx = reverse ? steps - i : i; label = surface.add({ type: 'text', text: renderer(round(minValue + idx / steps * (maxValue - minValue))), x: centerX + rho * cos(i / steps * pi - pi), y: centerY + rho * sin(i / steps * pi - pi) - adjY, 'text-anchor': 'middle', 'stroke-width': 0.2, zIndex: 10, stroke: '#333' }); label.setAttributes({ hidden: false }, true); labelArray.push(label); } } else { labelArray = this.labelArray; for (i = 0; i <= steps; i++) { adjY = (i === 0 || i === steps) ? 7 : 0; idx = reverse ? steps - i : i; labelArray[i].setAttributes({ text: renderer(round(minValue + idx / steps * (maxValue - minValue))), x: centerX + rho * cos(i / steps * pi - pi), y: centerY + rho * sin(i / steps * pi - pi) - adjY }, true); } } this.labelArray = labelArray; } }); Ext.define('Ext.chart.axis.Numeric', { extend: Ext.chart.axis.Axis , alternateClassName: 'Ext.chart.NumericAxis', type: 'Numeric', isNumericAxis: true, alias: 'axis.numeric', constructor: function(config) { var me = this, hasLabel = !!(config.label && config.label.renderer), label; me.callParent([config]); label = me.label; if (config.constrain == null) { me.constrain = (config.minimum != null && config.maximum != null); } if (!hasLabel) { label.renderer = function(v) { return me.roundToDecimal(v, me.decimals); }; } }, roundToDecimal: function(v, dec) { var val = Math.pow(10, dec || 0); return Math.round(v * val) / val; }, minimum: NaN, maximum: NaN, constrain: true, decimals: 2, scale: "linear", doConstrain: function() { var me = this, chart = me.chart, store = chart.getChartStore(), items = store.data.items, d, dLen, record, series = chart.series.items, fields = me.fields, ln = fields.length, range = me.calcEnds(), min = range.from, max = range.to, i, l, useAcum = false, value, data = [], addRecord; for (d = 0, dLen = items.length; d < dLen; d++) { addRecord = true; record = items[d]; for (i = 0; i < ln; i++) { value = record.get(fields[i]); if (me.type == 'Time' && typeof value == "string") { value = Date.parse(value); } if (+value < +min) { addRecord = false; break; } if (+value > +max) { addRecord = false; break; } } if (addRecord) { data.push(record); } } chart.setSubStore(new Ext.data.Store({ model: store.model, data: data })); }, position: 'left', adjustMaximumByMajorUnit: false, adjustMinimumByMajorUnit: false, processView: function() { var me = this, chart = me.chart, series = chart.series.items, i, l; for (i = 0, l = series.length; i < l; i++) { if (series[i].stacked) { delete me.minimum; delete me.maximum; me.constrain = false; break; } } if (me.constrain) { me.doConstrain(); } }, applyData: function() { this.callParent(); return this.calcEnds(); } }); Ext.define('Ext.chart.axis.Radial', { extend: Ext.chart.axis.Numeric , position: 'radial', alias: 'axis.radial', drawAxis: function(init) { var chart = this.chart, surface = chart.surface, bbox = chart.chartBBox, store = chart.getChartStore(), l = store.getCount(), centerX = bbox.x + (bbox.width / 2), centerY = bbox.y + (bbox.height / 2), rho = Math.min(bbox.width, bbox.height) /2, sprites = [], sprite, steps = this.steps, i, j, pi2 = Math.PI * 2, cos = Math.cos, sin = Math.sin; if (this.sprites && !chart.resizing) { this.drawLabel(); return; } if (!this.sprites) { for (i = 1; i <= steps; i++) { sprite = surface.add({ type: 'circle', x: centerX, y: centerY, radius: Math.max(rho * i / steps, 0), stroke: '#ccc' }); sprite.setAttributes({ hidden: false }, true); sprites.push(sprite); } for (i = 0; i < l; i++) { sprite = surface.add({ type: 'path', path: ['M', centerX, centerY, 'L', centerX + rho * cos(i / l * pi2), centerY + rho * sin(i / l * pi2), 'Z'], stroke: '#ccc' }); sprite.setAttributes({ hidden: false }, true); sprites.push(sprite); } } else { sprites = this.sprites; for (i = 0; i < steps; i++) { sprites[i].setAttributes({ x: centerX, y: centerY, radius: Math.max(rho * (i + 1) / steps, 0), stroke: '#ccc' }, true); } for (j = 0; j < l; j++) { sprites[i + j].setAttributes({ path: ['M', centerX, centerY, 'L', centerX + rho * cos(j / l * pi2), centerY + rho * sin(j / l * pi2), 'Z'], stroke: '#ccc' }, true); } } this.sprites = sprites; this.drawLabel(); }, drawLabel: function() { var chart = this.chart, seriesItems = chart.series.items, series, surface = chart.surface, bbox = chart.chartBBox, store = chart.getChartStore(), data = store.data.items, ln, record, centerX = bbox.x + (bbox.width / 2), centerY = bbox.y + (bbox.height / 2), rho = Math.min(bbox.width, bbox.height) /2, max = Math.max, round = Math.round, labelArray = [], label, fields = [], nfields, categories = [], xField, aggregate = !this.maximum, maxValue = this.maximum || 0, steps = this.steps, i = 0, j, dx, dy, pi2 = Math.PI * 2, cos = Math.cos, sin = Math.sin, display = this.label.display, draw = display !== 'none', margin = 10; if (!draw) { return; } for (i = 0, ln = seriesItems.length; i < ln; i++) { series = seriesItems[i]; fields.push(series.yField); xField = series.xField; } for (j = 0, ln = data.length; j < ln; j++) { record = data[j]; categories.push(record.get(xField)); if (aggregate) { for (i = 0, nfields = fields.length; i < nfields; i++) { maxValue = max(+record.get(fields[i]), maxValue); } } } if (!this.labelArray) { if (display != 'categories') { for (i = 1; i <= steps; i++) { label = surface.add({ type: 'text', text: round(i / steps * maxValue), x: centerX, y: centerY - rho * i / steps, 'text-anchor': 'middle', 'stroke-width': 0.1, stroke: '#333' }); label.setAttributes({ hidden: false }, true); labelArray.push(label); } } if (display != 'scale') { for (j = 0, steps = categories.length; j < steps; j++) { dx = cos(j / steps * pi2) * (rho + margin); dy = sin(j / steps * pi2) * (rho + margin); label = surface.add({ type: 'text', text: categories[j], x: centerX + dx, y: centerY + dy, 'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start') }); label.setAttributes({ hidden: false }, true); labelArray.push(label); } } } else { labelArray = this.labelArray; if (display != 'categories') { for (i = 0; i < steps; i++) { labelArray[i].setAttributes({ text: round((i + 1) / steps * maxValue), x: centerX, y: centerY - rho * (i + 1) / steps, 'text-anchor': 'middle', 'stroke-width': 0.1, stroke: '#333' }, true); } } if (display != 'scale') { for (j = 0, steps = categories.length; j < steps; j++) { dx = cos(j / steps * pi2) * (rho + margin); dy = sin(j / steps * pi2) * (rho + margin); if (labelArray[i + j]) { labelArray[i + j].setAttributes({ type: 'text', text: categories[j], x: centerX + dx, y: centerY + dy, 'text-anchor': dx * dx <= 0.001? 'middle' : (dx < 0? 'end' : 'start') }, true); } } } } this.labelArray = labelArray; }, getRange: function () { var range = this.callParent(); range.min = 0; return range; }, processView: function() { var me = this, seriesItems = me.chart.series.items, i, ln, series, ends, fields = []; for (i = 0, ln = seriesItems.length; i < ln; i++) { series = seriesItems[i]; fields.push(series.yField); } me.fields = fields; ends = me.calcEnds(); me.maximum = ends.to; me.steps = ends.steps; } }); Ext.define('Ext.chart.axis.Time', { extend: Ext.chart.axis.Numeric , alternateClassName: 'Ext.chart.TimeAxis', type: 'Time', alias: 'axis.time', dateFormat: false, fromDate: false, toDate: false, step: [Ext.Date.DAY, 1], constrain: false, constructor: function (config) { var me = this, label, f, df; me.callParent([config]); label = me.label || {}; df = this.dateFormat; if (df) { if (label.renderer) { f = label.renderer; label.renderer = function(v) { v = f(v); return Ext.Date.format(new Date(f(v)), df); }; } else { label.renderer = function(v) { return Ext.Date.format(new Date(v >> 0), df); }; } } }, processView: function () { var me = this; if (me.fromDate) { me.minimum = +me.fromDate; } if (me.toDate) { me.maximum = +me.toDate; } if(me.constrain){ me.doConstrain(); } }, calcEnds: function() { var me = this, range, step = me.step; if (step) { range = me.getRange(); range = Ext.draw.Draw.snapEndsByDateAndStep(new Date(range.min), new Date(range.max), Ext.isNumber(step) ? [Date.MILLI, step]: step); if (me.minimum) { range.from = me.minimum; } if (me.maximum) { range.to = me.maximum; } return range; } else { return me.callParent(arguments); } } }); Ext.define('Ext.chart.series.Series', { mixins: { observable: Ext.util.Observable , labels: Ext.chart.Label , highlights: Ext.chart.Highlight , tips: Ext.chart.Tip , callouts: Ext.chart.Callout }, type: null, title: null, showInLegend: true, renderer: function(sprite, record, attributes, index, store) { return attributes; }, shadowAttributes: null, animating: false, nullGutters: { lower: 0, upper: 0, verticalAxis: undefined }, nullPadding: { left:0, right:0, width:0, bottom:0, top:0, height:0 }, constructor: function(config) { var me = this; if (config) { Ext.apply(me, config); } me.shadowGroups = []; me.mixins.labels.constructor.call(me, config); me.mixins.highlights.constructor.call(me, config); me.mixins.tips.constructor.call(me, config); me.mixins.callouts.constructor.call(me, config); me.addEvents({ scope: me, itemclick: true, itemdblclick: true, itemmouseover: true, itemmouseout: true, itemmousedown: true, itemmouseup: true, mouseleave: true, afterdraw: true, titlechange: true }); me.mixins.observable.constructor.call(me, config); me.on({ scope: me, itemmouseover: me.onItemMouseOver, itemmouseout: me.onItemMouseOut, mouseleave: me.onMouseLeave }); if (me.style) { Ext.apply(me.seriesStyle, me.style); } }, initialize: Ext.emptyFn, onRedraw: Ext.emptyFn, eachRecord: function(fn, scope) { var chart = this.chart; chart.getChartStore().each(fn, scope); }, getRecordCount: function() { var chart = this.chart, store = chart.getChartStore(); return store ? store.getCount() : 0; }, isExcluded: function(index) { var excludes = this.__excludes; return !!(excludes && excludes[index]); }, setBBox: function(noGutter) { var me = this, chart = me.chart, chartBBox = chart.chartBBox, maxGutters = noGutter ? { left: 0, right: 0, bottom: 0, top: 0 } : chart.maxGutters, clipBox, bbox; clipBox = { x: chartBBox.x, y: chartBBox.y, width: chartBBox.width, height: chartBBox.height }; me.clipBox = clipBox; bbox = { x: (clipBox.x + maxGutters.left) - (chart.zoom.x * chart.zoom.width), y: (clipBox.y + maxGutters.bottom) - (chart.zoom.y * chart.zoom.height), width: (clipBox.width - (maxGutters.left + maxGutters.right)) * chart.zoom.width, height: (clipBox.height - (maxGutters.bottom + maxGutters.top)) * chart.zoom.height }; me.bbox = bbox; }, onAnimate: function(sprite, attr) { var me = this; sprite.stopAnimation(); if (me.animating) { return sprite.animate(Ext.applyIf(attr, me.chart.animate)); } else { me.animating = true; return sprite.animate(Ext.apply(Ext.applyIf(attr, me.chart.animate), { callback: function() { me.animating = false; me.fireEvent('afterrender', me); } })); } }, getGutters: function() { return this.nullGutters; }, getPadding: function() { return this.nullPadding; }, onItemMouseOver: function(item) { var me = this; if (item.series === me) { if (me.highlight) { me.highlightItem(item); } if (me.tooltip) { me.showTip(item); } } }, onItemMouseOut: function(item) { var me = this; if (item.series === me) { me.unHighlightItem(); if (me.tooltip) { me.hideTip(item); } } }, onMouseLeave: function() { var me = this; me.unHighlightItem(); if (me.tooltip) { me.hideTip(); } }, getItemForPoint: function(x, y) { if (!this.items || !this.items.length || this.seriesIsHidden) { return null; } var me = this, items = me.items, bbox = me.bbox, item, i, ln; if (!Ext.draw.Draw.withinBox(x, y, bbox)) { return null; } for (i = 0, ln = items.length; i < ln; i++) { if (items[i] && this.isItemInPoint(x, y, items[i], i)) { return items[i]; } } return null; }, isItemInPoint: function(x, y, item, i) { return false; }, hideAll: function() { var me = this, items = me.items, item, len, i, j, l, sprite, shadows; me.seriesIsHidden = true; me._prevShowMarkers = me.showMarkers; me.showMarkers = false; me.hideLabels(0); for (i = 0, len = items.length; i < len; i++) { item = items[i]; sprite = item.sprite; if (sprite) { sprite.setAttributes({ hidden: true }, true); } if (sprite && sprite.shadows) { shadows = sprite.shadows; for (j = 0, l = shadows.length; j < l; ++j) { shadows[j].setAttributes({ hidden: true }, true); } } } }, showAll: function() { var me = this, prevAnimate = me.chart.animate; me.chart.animate = false; me.seriesIsHidden = false; me.showMarkers = me._prevShowMarkers; me.drawSeries(); me.chart.animate = prevAnimate; }, hide: function() { if (this.items) { var me = this, items = me.items, i, j, lsh, ln, shadows; if (items && items.length) { for (i = 0, ln = items.length; i < ln; ++i) { if (items[i].sprite) { items[i].sprite.hide(true); shadows = items[i].shadows || items[i].sprite.shadows; if (shadows) { for (j = 0, lsh = shadows.length; j < lsh; ++j) { shadows[j].hide(true); } } } } me.hideLabels(); } } }, getLegendColor: function(index) { var me = this, fill, stroke; if (me.seriesStyle) { fill = me.seriesStyle.fill; stroke = me.seriesStyle.stroke; if (fill && fill != 'none') { return fill; } if(stroke){ return stroke; } } return (me.colorArrayStyle)?me.colorArrayStyle[me.themeIdx % me.colorArrayStyle.length]:'#000'; }, visibleInLegend: function(index){ var excludes = this.__excludes; if (excludes) { return !excludes[index]; } return !this.seriesIsHidden; }, setTitle: function(index, title) { var me = this, oldTitle = me.title; if (Ext.isString(index)) { title = index; index = 0; } if (Ext.isArray(oldTitle)) { oldTitle[index] = title; } else { me.title = title; } me.fireEvent('titlechange', title, index); } }); Ext.define('Ext.chart.series.Cartesian', { extend: Ext.chart.series.Series , alternateClassName: ['Ext.chart.CartesianSeries', 'Ext.chart.CartesianChart'], xField: null, yField: null, axis: 'left', getLegendLabels: function() { var me = this, labels = [], fields, i, ln, combinations = me.combinations, title, combo, label0, label1; fields = [].concat(me.yField); for (i = 0, ln = fields.length; i < ln; i++) { title = me.title; labels.push((Ext.isArray(title) ? title[i] : title) || fields[i]); } if (combinations) { combinations = Ext.Array.from(combinations); for (i = 0, ln = combinations.length; i < ln; i++) { combo = combinations[i]; label0 = labels[combo[0]]; label1 = labels[combo[1]]; labels[combo[1]] = label0 + ' & ' + label1; labels.splice(combo[0], 1); } } return labels; }, eachYValue: function(record, fn, scope) { var me = this, yValueAccessors = me.getYValueAccessors(), i, ln, accessor; for (i = 0, ln = yValueAccessors.length; i < ln; i++) { accessor = yValueAccessors[i]; fn.call(scope, accessor(record), i); } }, getYValueCount: function() { return this.getYValueAccessors().length; }, combine: function(index1, index2) { var me = this, accessors = me.getYValueAccessors(), accessor1 = accessors[index1], accessor2 = accessors[index2]; accessors[index2] = function(record) { return accessor1(record) + accessor2(record); }; accessors.splice(index1, 1); me.callParent([index1, index2]); }, clearCombinations: function() { delete this.yValueAccessors; this.callParent(); }, getYValueAccessors: function() { var me = this, accessors = me.yValueAccessors, yFields, i, ln; function getFieldAccessor(field) { return function(record) { return record.get(field); } } if (!accessors) { accessors = me.yValueAccessors = []; yFields = [].concat(me.yField); for (i = 0, ln = yFields.length; i < ln; i++) { accessors.push(getFieldAccessor(yFields[i])); } } return accessors; }, getMinMaxXValues: function() { var me = this, chart = me.chart, store = chart.getChartStore(), data = store.data.items, count = me.getRecordCount(), i, ln, record, min, max, xField = me.xField, xValue; if (count > 0) { min = Infinity; max = -min; for (i = 0, ln = data.length; i < ln; i++) { record = data[i]; xValue = record.get(xField); if (xValue > max) { max = xValue; } if (xValue < min) { min = xValue; } } if (min == Infinity) { min = 0; } if (max == -Infinity) { max = count - 1; } } else { min = max = 0; } return [min, max]; }, getMinMaxYValues: function() { var me = this, chart = me.chart, store = chart.getChartStore(), data = store.data.items, count = me.getRecordCount(), i, ln, record, stacked = me.stacked, min, max, positiveTotal, negativeTotal; function eachYValueStacked(yValue, i) { if (!me.isExcluded(i)) { if (yValue < 0) { negativeTotal += yValue; } else { positiveTotal += yValue; } } } function eachYValue(yValue, i) { if (!me.isExcluded(i)) { if (yValue > max) { max = yValue; } if (yValue < min) { min = yValue; } } } if (count > 0) { min = Infinity; max = -min; for (i = 0, ln = data.length; i < ln; i++) { record = data[i]; if (stacked) { positiveTotal = 0; negativeTotal = 0; me.eachYValue(record, eachYValueStacked); if (positiveTotal > max) { max = positiveTotal; } if (negativeTotal < min) { min = negativeTotal; } } else { me.eachYValue(record, eachYValue); } } if (min == Infinity) { min = 0; } if (max == -Infinity) { max = count - 1; } } else { min = max = 0; } return [min, max]; }, getAxesForXAndYFields: function() { var me = this, axes = me.chart.axes, reverse = me.reverse, axis = [].concat(me.axis), yFields = {}, yFieldList = [].concat(me.yField), xFields = {}, xFieldList = [].concat(me.xField), fields, xAxis, yAxis, i, ln, flipXY; flipXY = me.type === 'bar' && me.column === false; if(flipXY) { fields = yFieldList; yFieldList = xFieldList; xFieldList = fields; } if (Ext.Array.indexOf(axis, 'top') > -1) { xAxis = 'top'; } else if (Ext.Array.indexOf(axis, 'bottom') > -1) { xAxis = 'bottom'; } else { if (axes.get('top') && axes.get('bottom')) { for (i = 0, ln = xFieldList.length; i < ln; i++) { xFields[xFieldList[i]] = true; } fields = [].concat(axes.get('bottom').fields); for (i = 0, ln = fields.length; i < ln; i++) { if (xFields[fields[i]]) { xAxis = 'bottom'; break; } } fields = [].concat(axes.get('top').fields); for (i = 0, ln = fields.length; i < ln; i++) { if (xFields[fields[i]]) { xAxis = 'top'; break; } } } else if (axes.get('top')) { xAxis = 'top'; } else if (axes.get('bottom')) { xAxis = 'bottom'; } } if (Ext.Array.indexOf(axis, 'left') > -1) { yAxis = flipXY ? 'right' : 'left'; } else if (Ext.Array.indexOf(axis, 'right') > -1) { yAxis = flipXY ? 'left' : 'right'; } else { if (axes.get('left') && axes.get('right')) { for (i = 0, ln = yFieldList.length; i < ln; i++) { yFields[yFieldList[i]] = true; } fields = [].concat(axes.get('right').fields); for (i = 0, ln = fields.length; i < ln; i++) { if (yFields[fields[i]]) { break; } } fields = [].concat(axes.get('left').fields); for (i = 0, ln = fields.length; i < ln; i++) { if (yFields[fields[i]]) { yAxis = 'left'; break; } } } else if (axes.get('left')) { yAxis = 'left'; } else if (axes.get('right')) { yAxis = 'right'; } } return flipXY ? { xAxis: yAxis, yAxis: xAxis }: { xAxis: xAxis, yAxis: yAxis }; } }); Ext.define('Ext.chart.series.Area', { extend: Ext.chart.series.Cartesian , alias: 'series.area', type: 'area', stacked: true, style: {}, constructor: function(config) { this.callParent(arguments); var me = this, surface = me.chart.surface, i, l; config.highlightCfg = Ext.Object.merge({}, { lineWidth: 3, stroke: '#55c', opacity: 0.8, color: '#f00' }, config.highlightCfg); Ext.apply(me, config, { __excludes: [] }); if (me.highlight) { me.highlightSprite = surface.add({ type: 'path', path: ['M', 0, 0], zIndex: 1000, opacity: 0.3, lineWidth: 5, hidden: true, stroke: '#444' }); } me.group = surface.getGroup(me.seriesId); }, shrink: function(xValues, yValues, size) { var len = xValues.length, ratio = Math.floor(len / size), i, j, xSum = 0, yCompLen = this.areas.length, ySum = [], xRes = [], yRes = []; for (j = 0; j < yCompLen; ++j) { ySum[j] = 0; } for (i = 0; i < len; ++i) { xSum += +xValues[i]; for (j = 0; j < yCompLen; ++j) { ySum[j] += +yValues[i][j]; } if (i % ratio == 0) { xRes.push(xSum/ratio); for (j = 0; j < yCompLen; ++j) { ySum[j] /= ratio; } yRes.push(ySum); xSum = 0; for (j = 0, ySum = []; j < yCompLen; ++j) { ySum[j] = 0; } } } return { x: xRes, y: yRes }; }, getBounds: function() { var me = this, chart = me.chart, store = chart.getChartStore(), data = store.data.items, i, l, record, areas = [].concat(me.yField), areasLen = areas.length, xValues = [], yValues = [], infinity = Infinity, minX = infinity, minY = infinity, maxX = -infinity, maxY = -infinity, math = Math, mmin = math.min, mmax = math.max, boundAxis = me.getAxesForXAndYFields(), boundXAxis = boundAxis.xAxis, boundYAxis = boundAxis.yAxis, ends, allowDate, tmp, bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem, axis, out; me.setBBox(); bbox = me.bbox; if (axis = chart.axes.get(boundXAxis)) { if (axis.type === 'Time') { allowDate = true; } ends = axis.applyData(); minX = ends.from; maxX = ends.to; } if (axis = chart.axes.get(boundYAxis)) { ends = axis.applyData(); minY = ends.from; maxY = ends.to; } if (me.xField && !Ext.isNumber(minX)) { axis = me.getMinMaxXValues(); allowDate = true; minX = axis[0]; maxX = axis[1]; } if (me.yField && !Ext.isNumber(minY)) { axis = me.getMinMaxYValues(); minY = axis[0]; maxY = axis[1]; } if (!Ext.isNumber(minY)) { minY = 0; } if (!Ext.isNumber(maxY)) { maxY = 0; } l = data.length; if (l > 0 && allowDate) { tmp = data[0].get(me.xField); if (typeof tmp != 'number') { tmp = +tmp; if (isNaN(tmp)) { allowDate = false; } } } for (i = 0; i < l; i++) { record = data[i]; xValue = record.get(me.xField); yValue = []; if (typeof xValue != 'number') { if (allowDate) { xValue = +xValue; } else { xValue = i; } } xValues.push(xValue); acumY = 0; for (areaIndex = 0; areaIndex < areasLen; areaIndex++) { if (me.__excludes[areaIndex]) { continue; } areaElem = record.get(areas[areaIndex]); if (typeof areaElem == 'number') { yValue.push(areaElem); } } yValues.push(yValue); } xScale = bbox.width / ((maxX - minX) || 1); yScale = bbox.height / ((maxY - minY) || 1); ln = xValues.length; if ((ln > bbox.width) && me.areas) { sumValues = me.shrink(xValues, yValues, bbox.width); xValues = sumValues.x; yValues = sumValues.y; } return { bbox: bbox, minX: minX, minY: minY, xValues: xValues, yValues: yValues, xScale: xScale, yScale: yScale, areasLen: areasLen }; }, getPaths: function() { var me = this, chart = me.chart, store = chart.getChartStore(), first = true, bounds = me.getBounds(), bbox = bounds.bbox, items = me.items = [], componentPaths = [], componentPath, count = 0, paths = [], reverse = me.reverse, i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path, startX, idx; ln = bounds.xValues.length; for (i = 0; i < ln; i++) { xValue = bounds.xValues[i]; idx = reverse ? ln - i - 1 : i; yValue = bounds.yValues[idx]; x = bbox.x + (xValue - bounds.minX) * bounds.xScale; if (startX === undefined) { startX = x; } acumY = 0; count = 0; for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) { if (me.__excludes[areaIndex]) { continue; } if (!componentPaths[areaIndex]) { componentPaths[areaIndex] = []; } areaElem = yValue[count]; acumY += areaElem; y = bbox.y + bbox.height - (acumY - bounds.minY) * bounds.yScale; if (!paths[areaIndex]) { paths[areaIndex] = ['M', x, y]; componentPaths[areaIndex].push(['L', x, y]); } else { paths[areaIndex].push('L', x, y); componentPaths[areaIndex].push(['L', x, y]); } if (!items[areaIndex]) { items[areaIndex] = { pointsUp: [], pointsDown: [], series: me }; } items[areaIndex].pointsUp.push([x, y]); count++; } } for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) { if (me.__excludes[areaIndex]) { continue; } path = paths[areaIndex]; if (areaIndex == 0 || first) { first = false; path.push('L', x, bbox.y + bbox.height, 'L', startX, bbox.y + bbox.height, 'Z'); } else { componentPath = componentPaths[prevAreaIndex]; componentPath.reverse(); path.push('L', x, componentPath[0][2]); for (i = 0; i < ln; i++) { path.push(componentPath[i][0], componentPath[i][1], componentPath[i][2]); items[areaIndex].pointsDown[ln -i -1] = [componentPath[i][1], componentPath[i][2]]; } path.push('L', startX, path[2], 'Z'); } prevAreaIndex = areaIndex; } return { paths: paths, areasLen: bounds.areasLen }; }, drawSeries: function() { var me = this, chart = me.chart, store = chart.getChartStore(), surface = chart.surface, animate = chart.animate, group = me.group, endLineStyle = Ext.apply(me.seriesStyle, me.style), colorArrayStyle = me.colorArrayStyle, colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0, themeIndex = me.themeIdx, areaIndex, areaElem, paths, path, rendererAttributes, idx; me.unHighlightItem(); me.cleanHighlights(); if (!store || !store.getCount() || me.seriesIsHidden) { me.hide(); me.items = []; return; } paths = me.getPaths(); if (!me.areas) { me.areas = []; } for (areaIndex = 0; areaIndex < paths.areasLen; areaIndex++) { if (me.__excludes[areaIndex]) { continue; } idx = themeIndex + areaIndex; if (!me.areas[areaIndex]) { me.items[areaIndex].sprite = me.areas[areaIndex] = surface.add(Ext.apply({}, { type: 'path', group: group, path: paths.paths[areaIndex], stroke: endLineStyle.stroke || colorArrayStyle[idx % colorArrayLength], fill: colorArrayStyle[idx % colorArrayLength] }, endLineStyle || {})); } areaElem = me.areas[areaIndex]; path = paths.paths[areaIndex]; if (animate) { rendererAttributes = me.renderer(areaElem, false, { path: path, fill: colorArrayStyle[areaIndex % colorArrayLength], stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % colorArrayLength] }, areaIndex, store); me.animation = me.onAnimate(areaElem, { to: rendererAttributes }); } else { rendererAttributes = me.renderer(areaElem, false, { path: path, hidden: false, fill: colorArrayStyle[idx % colorArrayLength], stroke: endLineStyle.stroke || colorArrayStyle[idx % colorArrayLength] }, areaIndex, store); me.areas[areaIndex].setAttributes(rendererAttributes, true); } } me.renderLabels(); me.renderCallouts(); }, onAnimate: function(sprite, attr) { sprite.show(); return this.callParent(arguments); }, onCreateLabel: function(storeItem, item, i, display) { return null; var me = this, group = me.labelsGroup, config = me.label, bbox = me.bbox, endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle || {}); return me.chart.surface.add(Ext.apply({ 'type': 'text', 'text-anchor': 'middle', 'group': group, 'x': Number(item.point[0]), 'y': bbox.y + bbox.height / 2 }, endLabelStyle || {})); }, onPlaceLabel: function(label, storeItem, item, i, display, animate, index) { var me = this, chart = me.chart, resizing = chart.resizing, config = me.label, format = config.renderer, field = config.field, bbox = me.bbox, x = Number(item.point[i][0]), y = Number(item.point[i][1]), labelBox, width, height; label.setAttributes({ text: format(storeItem.get(field[index]), label, storeItem, item, i, display, animate, index), hidden: true }, true); labelBox = label.getBBox(); width = labelBox.width / 2; height = labelBox.height / 2; if (x < bbox.x + width) { x = bbox.x + width; } else if (x + width > bbox.x + bbox.width) { x = bbox.x + bbox.width - width; } y = y - height; if (y < bbox.y + height) { y += 2 * height; } else if (y + height > bbox.y + bbox.height) { y -= 2 * height; } if (me.chart.animate && !me.chart.resizing) { label.show(true); me.onAnimate(label, { to: { x: x, y: y } }); } else { label.setAttributes({ x: x, y: y }, true); if (resizing && me.animation) { me.animation.on('afteranimate', function() { label.show(true); }); } else { label.show(true); } } }, onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) { var me = this, chart = me.chart, surface = chart.surface, resizing = chart.resizing, config = me.callouts, items = me.items, prev = (i == 0) ? false : items[i -1].point, next = (i == items.length -1) ? false : items[i +1].point, cur = item.point, dir, norm, normal, a, aprev, anext, bbox = (callout && callout.label ? callout.label.getBBox() : {width:0,height:0}), offsetFromViz = 30, offsetToSide = 10, offsetBox = 3, boxx, boxy, boxw, boxh, p, clipRect = me.clipRect, x, y; if (!bbox.width || !bbox.height) { return; } if (!prev) { prev = cur; } if (!next) { next = cur; } a = (next[1] - prev[1]) / (next[0] - prev[0]); aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]); anext = (next[1] - cur[1]) / (next[0] - cur[0]); norm = Math.sqrt(1 + a * a); dir = [1 / norm, a / norm]; normal = [-dir[1], dir[0]]; if (aprev > 0 && anext < 0 && normal[1] < 0 || aprev < 0 && anext > 0 && normal[1] > 0) { normal[0] *= -1; normal[1] *= -1; } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0 || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) { normal[0] *= -1; normal[1] *= -1; } x = cur[0] + normal[0] * offsetFromViz; y = cur[1] + normal[1] * offsetFromViz; boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox)); boxy = y - bbox.height /2 - offsetBox; boxw = bbox.width + 2 * offsetBox; boxh = bbox.height + 2 * offsetBox; if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) { normal[0] *= -1; } if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) { normal[1] *= -1; } x = cur[0] + normal[0] * offsetFromViz; y = cur[1] + normal[1] * offsetFromViz; boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox)); boxy = y - bbox.height /2 - offsetBox; boxw = bbox.width + 2 * offsetBox; boxh = bbox.height + 2 * offsetBox; callout.lines.setAttributes({ path: ["M", cur[0], cur[1], "L", x, y, "Z"] }, true); callout.box.setAttributes({ x: boxx, y: boxy, width: boxw, height: boxh }, true); callout.label.setAttributes({ x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)), y: y }, true); for (p in callout) { callout[p].show(true); } }, isItemInPoint: function(x, y, item, i) { var me = this, pointsUp = item.pointsUp, pointsDown = item.pointsDown, abs = Math.abs, distChanged = false, last = false, reverse = me.reverse, dist = Infinity, p, pln, point; for (p = 0, pln = pointsUp.length; p < pln; p++) { point = [pointsUp[p][0], pointsUp[p][1]]; distChanged = false; last = p == pln -1; if (dist > abs(x - point[0])) { dist = abs(x - point[0]); distChanged = true; if (last) { ++p; } } if (!distChanged || (distChanged && last)) { point = pointsUp[p -1]; if (y >= point[1] && (!pointsDown.length || y <= (pointsDown[p -1][1]))) { idx = reverse ? pln - p : p - 1; item.storeIndex = idx; item.storeField = me.yField[i]; item.storeItem = me.chart.getChartStore().getAt(idx); item._points = pointsDown.length? [point, pointsDown[p - 1]] : [point]; return true; } else { break; } } } return false; }, highlightSeries: function() { var area, to, fillColor; if (this._index !== undefined) { area = this.areas[this._index]; if (area.__highlightAnim) { area.__highlightAnim.paused = true; } area.__highlighted = true; area.__prevOpacity = area.__prevOpacity || area.attr.opacity || 1; area.__prevFill = area.__prevFill || area.attr.fill; area.__prevLineWidth = area.__prevLineWidth || area.attr.lineWidth; fillColor = Ext.draw.Color.fromString(area.__prevFill); to = { lineWidth: (area.__prevLineWidth || 0) + 2 }; if (fillColor) { to.fill = fillColor.getLighter(0.2).toString(); } else { to.opacity = Math.max(area.__prevOpacity - 0.3, 0); } if (this.chart.animate) { area.__highlightAnim = new Ext.fx.Anim(Ext.apply({ target: area, to: to }, this.chart.animate)); } else { area.setAttributes(to, true); } } }, unHighlightSeries: function() { var area; if (this._index !== undefined) { area = this.areas[this._index]; if (area.__highlightAnim) { area.__highlightAnim.paused = true; } if (area.__highlighted) { area.__highlighted = false; area.__highlightAnim = new Ext.fx.Anim({ target: area, to: { fill: area.__prevFill, opacity: area.__prevOpacity, lineWidth: area.__prevLineWidth } }); } } }, highlightItem: function(item) { var me = this, points, path; if (!item) { this.highlightSeries(); return; } points = item._points; if (points.length === 2) { path = ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]; } else { path = ['M', points[0][0], points[0][1], 'L', points[0][0], me.bbox.y + me.bbox.height]; } me.highlightSprite.setAttributes({ path: path, hidden: false }, true); }, unHighlightItem: function(item) { if (!item) { this.unHighlightSeries(); } if (this.highlightSprite) { this.highlightSprite.hide(true); } }, hideAll: function(index) { var me = this; index = (isNaN(me._index) ? index : me._index) || 0; me.__excludes[index] = true; me.areas[index].hide(true); me.redraw(); }, showAll: function(index) { var me = this; index = (isNaN(me._index) ? index : me._index) || 0; me.__excludes[index] = false; me.areas[index].show(true); me.redraw(); }, redraw: function() { var me = this, prevLegendConfig; prevLegendConfig = me.chart.legend.rebuild; me.chart.legend.rebuild = false; me.chart.redraw(); me.chart.legend.rebuild = prevLegendConfig; }, hide: function() { if (this.areas) { var me = this, areas = me.areas, i, j, l, ln, shadows; if (areas && areas.length) { for (i = 0, ln = areas.length; i < ln; ++i) { if (areas[i]) { areas[i].hide(true); } } me.hideLabels(); } } }, getLegendColor: function(index) { var me = this; index += me.themeIdx; return me.colorArrayStyle[index % me.colorArrayStyle.length]; } }); Ext.define('Ext.chart.series.Bar', { extend: Ext.chart.series.Cartesian , alternateClassName: ['Ext.chart.BarSeries', 'Ext.chart.BarChart', 'Ext.chart.StackedBarChart'], type: 'bar', alias: 'series.bar', column: false, style: {}, gutter: 38.2, groupGutter: 38.2, xPadding: 0, yPadding: 10, defaultRotate: { x: 0, y: 0, degrees: 0 }, constructor: function(config) { this.callParent(arguments); var me = this, surface = me.chart.surface, shadow = me.chart.shadow, i, l; config.highlightCfg = Ext.Object.merge({ lineWidth: 3, stroke: '#55c', opacity: 0.8, color: '#f00' }, config.highlightCfg); Ext.apply(me, config, { shadowAttributes: [{ "stroke-width": 6, "stroke-opacity": 0.05, stroke: 'rgb(200, 200, 200)', translate: { x: 1.2, y: 1.2 } }, { "stroke-width": 4, "stroke-opacity": 0.1, stroke: 'rgb(150, 150, 150)', translate: { x: 0.9, y: 0.9 } }, { "stroke-width": 2, "stroke-opacity": 0.15, stroke: 'rgb(100, 100, 100)', translate: { x: 0.6, y: 0.6 } }] }); me.group = surface.getGroup(me.seriesId + '-bars'); if (shadow) { for (i = 0, l = me.shadowAttributes.length; i < l; i++) { me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i)); } } }, getPadding: function() { var me = this, xPadding = me.xPadding, yPadding = me.yPadding, padding = { }; if (Ext.isNumber(xPadding)) { padding.left = xPadding; padding.right = xPadding; } else if (Ext.isObject(xPadding)) { padding.left = xPadding.left; padding.right = xPadding.right; } else { padding.left = 0; padding.right = 0; } padding.width = padding.left + padding.right; if (Ext.isNumber(yPadding)) { padding.bottom = yPadding; padding.top = yPadding; } else if (Ext.isObject(yPadding)) { padding.bottom = yPadding.bottom; padding.top = yPadding.top; } else { padding.bottom = 0; padding.top = 0; } padding.height = padding.bottom + padding.top; return padding; }, getBarGirth: function() { var me = this, store = me.chart.getChartStore(), column = me.column, ln = store.getCount(), gutter = me.gutter / 100, padding, property; property = (column ? 'width' : 'height'); if (me.style && me.style[property]) { me.configuredColumnGirth = true; return +me.style[property]; } padding = me.getPadding(); return (me.chart.chartBBox[property] - padding[property]) / (ln * (gutter + 1) - gutter); }, getGutters: function() { var me = this, column = me.column, padding = me.getPadding(), halfBarGirth = me.getBarGirth() / 2, lowerGutter = Math.ceil((column ? padding.left : padding.bottom) + halfBarGirth), upperGutter = Math.ceil((column ? padding.right : padding.top) + halfBarGirth); return { lower: lowerGutter, upper: upperGutter, verticalAxis: !column }; }, getBounds: function() { var me = this, chart = me.chart, store = chart.getChartStore(), data = store.data.items, i, ln, record, bars = [].concat(me.yField), barsLoc = [], barsLen = bars.length, groupBarsLen = barsLen, groupGutter = me.groupGutter / 100, column = me.column, padding = me.getPadding(), stacked = me.stacked, barWidth = me.getBarGirth(), barWidthProperty = column ? 'width' : 'height', math = Math, mmin = math.min, mmax = math.max, mabs = math.abs, boundAxes = me.getAxesForXAndYFields(), boundYAxis = boundAxes.yAxis, minX, maxX, colsScale, colsZero, gutters, ends, shrunkBarWidth, groupBarWidth, bbox, minY, maxY, axis, out, scale, zero, total, rec, j, plus, minus, inflections, tick, loc; me.setBBox(true); bbox = me.bbox; if (me.__excludes) { for (j = 0, total = me.__excludes.length; j < total; j++) { if (me.__excludes[j]) { groupBarsLen--; } } } axis = chart.axes.get(boundYAxis); if (axis) { ends = axis.applyData(); minY = ends.from; maxY = ends.to; } if (me.yField && !Ext.isNumber(minY)) { out = me.getMinMaxYValues(); minY = out[0]; maxY = out[1]; } if (!Ext.isNumber(minY)) { minY = 0; } if (!Ext.isNumber(maxY)) { maxY = 0; } scale = (column ? bbox.height - padding.height : bbox.width - padding.width) / (maxY - minY); shrunkBarWidth = barWidth; groupBarWidth = (barWidth / ((stacked ? 1 : groupBarsLen) * (groupGutter + 1) - groupGutter)); if (barWidthProperty in me.style) { groupBarWidth = mmin(groupBarWidth, me.style[barWidthProperty]); shrunkBarWidth = groupBarWidth * ((stacked ? 1 : groupBarsLen) * (groupGutter + 1) - groupGutter); } zero = (column) ? bbox.y + bbox.height - padding.bottom : bbox.x + padding.left; if (stacked) { total = [[], []]; for (i = 0, ln = data.length; i < ln; i++) { record = data[i]; total[0][i] = total[0][i] || 0; total[1][i] = total[1][i] || 0; for (j = 0; j < barsLen; j++) { if (me.__excludes && me.__excludes[j]) { continue; } rec = record.get(bars[j]); total[+(rec > 0)][i] += mabs(rec); } } total[+(maxY > 0)].push(mabs(maxY)); total[+(minY > 0)].push(mabs(minY)); minus = mmax.apply(math, total[0]); plus = mmax.apply(math, total[1]); scale = (column ? bbox.height - padding.height : bbox.width - padding.width) / (plus + minus); zero = zero + minus * scale * (column ? -1 : 1); } else if (minY / maxY < 0) { zero = zero - minY * scale * (column ? -1 : 1); } if (me.boundColumn) { axis = chart.axes.get(boundAxes.xAxis); if (axis) { ends = axis.applyData(); minX = ends.from; maxX = ends.to; } if (me.xField && !Ext.isNumber(minX)) { out = me.getMinMaxYValues(); minX = out[0]; maxX = out[1]; } if (!Ext.isNumber(minX)) { minX = 0; } if (!Ext.isNumber(maxX)) { maxX = 0; } gutters = me.getGutters(); colsScale = (bbox.width - (gutters.lower + gutters.upper)) / ((maxX - minX) || 1); colsZero = bbox.x + gutters.lower; barsLoc = []; for (i = 0, ln = data.length; i < ln; i++) { record = data[i]; rec = record.get(me.xField); barsLoc[i] = colsZero + (rec - minX) * colsScale - (groupBarWidth / 2); } } else if (me.configuredColumnGirth) { axis = chart.axes.get(boundAxes.xAxis); if (axis) { inflections = axis.inflections; if (axis.isCategoryAxis || inflections.length == data.length) { barsLoc = []; for (i = 0, ln = data.length; i < ln; i++) { tick = inflections[i]; loc = column ? tick[0] : tick[1]; barsLoc[i] = loc - (shrunkBarWidth / 2); } } } } return { bars: bars, barsLoc: barsLoc, bbox: bbox, shrunkBarWidth: shrunkBarWidth, barsLen: barsLen, groupBarsLen: groupBarsLen, barWidth: barWidth, groupBarWidth: groupBarWidth, scale: scale, zero: zero, padding: padding, signed: minY / maxY < 0, minY: minY, maxY: maxY }; }, getPaths: function() { var me = this, chart = me.chart, store = chart.getChartStore(), data = store.data.items, i, total, record, bounds = me.bounds = me.getBounds(), items = me.items = [], yFields = Ext.isArray(me.yField) ? me.yField : [me.yField], gutter = me.gutter / 100, groupGutter = me.groupGutter / 100, animate = chart.animate, column = me.column, group = me.group, enableShadows = chart.shadow, shadowGroups = me.shadowGroups, shadowAttributes = me.shadowAttributes, shadowGroupsLn = shadowGroups.length, bbox = bounds.bbox, barWidth = bounds.barWidth, shrunkBarWidth = bounds.shrunkBarWidth, padding = me.getPadding(), stacked = me.stacked, barsLen = bounds.barsLen, colors = me.colorArrayStyle, colorLength = colors && colors.length || 0, themeIndex = me.themeIdx, reverse = me.reverse, math = Math, mmax = math.max, mmin = math.min, mabs = math.abs, j, yValue, height, totalDim, totalNegDim, bottom, top, hasShadow, barAttr, attrs, counter, totalPositiveValues, totalNegativeValues, shadowIndex, shadow, sprite, offset, floorY, idx, itemIdx, xPos, yPos, width, usedWidth, barIdx; for (i = 0, total = data.length; i < total; i++) { record = data[i]; bottom = bounds.zero; top = bounds.zero; totalDim = 0; totalNegDim = 0; totalPositiveValues = totalNegativeValues = 0; hasShadow = false; usedWidth = 0; for (j = 0, counter = 0; j < barsLen; j++) { if (me.__excludes && me.__excludes[j]) { continue; } yValue = record.get(bounds.bars[j]); if (yValue >= 0) { totalPositiveValues += yValue; } else { totalNegativeValues += yValue; } height = Math.round((yValue - mmax(bounds.minY, 0)) * bounds.scale); idx = themeIndex + (barsLen > 1 ? j : 0); barAttr = { fill: colors[idx % colorLength] }; if (column) { idx = reverse ? (total - i - 1) : i; barIdx = reverse ? (barsLen - counter - 1) : counter; if (me.boundColumn) { xPos = bounds.barsLoc[idx]; } else if (me.configuredColumnGirth && bounds.barsLoc.length) { xPos = bounds.barsLoc[idx] + barIdx * bounds.groupBarWidth * (1 + groupGutter) * !stacked; } else { xPos = bbox.x + padding.left + (barWidth - shrunkBarWidth) * 0.5 + idx * barWidth * (1 + gutter) + barIdx * bounds.groupBarWidth * (1 + groupGutter) * !stacked; } Ext.apply(barAttr, { height: height, width: mmax(bounds.groupBarWidth, 0), x: xPos, y: bottom - height }); } else { offset = (total - 1) - i; width = height + (bottom == bounds.zero); xPos = bottom + (bottom != bounds.zero); if (reverse) { xPos = bounds.zero + bbox.width - width - (usedWidth === 0 ? 1 : 0); if (stacked) { xPos -= usedWidth; usedWidth += width; } } if (me.configuredColumnGirth && bounds.barsLoc.length) { yPos = bounds.barsLoc[i] + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked; } else { yPos = bbox.y + padding.top + (barWidth - shrunkBarWidth) * 0.5 + offset * barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked + 1; } Ext.apply(barAttr, { height: mmax(bounds.groupBarWidth, 0), width: width, x: xPos, y: yPos }); } if (height < 0) { if (column) { barAttr.y = top; barAttr.height = mabs(height); } else { barAttr.x = top + height; barAttr.width = mabs(height); } } if (stacked) { if (height < 0) { top += height * (column ? -1 : 1); } else { bottom += height * (column ? -1 : 1); } totalDim += mabs(height); if (height < 0) { totalNegDim += mabs(height); } } barAttr.x = Math.floor(barAttr.x) + 1; floorY = Math.floor(barAttr.y); if (Ext.isIE8m && barAttr.y > floorY) { floorY--; } barAttr.y = floorY; barAttr.width = Math.floor(barAttr.width); barAttr.height = Math.floor(barAttr.height); items.push({ series: me, yField: yFields[j], storeItem: record, value: [record.get(me.xField), yValue], attr: barAttr, point: column ? [barAttr.x + barAttr.width / 2, yValue >= 0 ? barAttr.y : barAttr.y + barAttr.height] : [yValue >= 0 ? barAttr.x + barAttr.width : barAttr.x, barAttr.y + barAttr.height / 2] }); if (animate && chart.resizing) { attrs = column ? { x: barAttr.x, y: bounds.zero, width: barAttr.width, height: 0 } : { x: bounds.zero, y: barAttr.y, width: 0, height: barAttr.height }; if (enableShadows && (stacked && !hasShadow || !stacked)) { hasShadow = true; for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) { shadow = shadowGroups[shadowIndex].getAt(stacked ? i : (i * barsLen + j)); if (shadow) { shadow.setAttributes(attrs, true); } } } sprite = group.getAt(i * barsLen + j); if (sprite) { sprite.setAttributes(attrs, true); } } counter++; } if (stacked && items.length) { items[i * counter].totalDim = totalDim; items[i * counter].totalNegDim = totalNegDim; items[i * counter].totalPositiveValues = totalPositiveValues; items[i * counter].totalNegativeValues = totalNegativeValues; } } if (stacked && counter == 0) { for (i = 0, total = data.length; i < total; i++) { for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) { shadow = shadowGroups[shadowIndex].getAt(i); if (shadow) { shadow.hide(true); } } } } }, renderShadows: function(i, barAttr, baseAttrs, bounds) { var me = this, chart = me.chart, surface = chart.surface, animate = chart.animate, stacked = me.stacked, shadowGroups = me.shadowGroups, shadowAttributes = me.shadowAttributes, shadowGroupsLn = shadowGroups.length, store = chart.getChartStore(), column = me.column, items = me.items, shadows = [], reverse = me.reverse, zero = bounds.zero, shadowIndex, shadowBarAttr, shadow, totalDim, totalNegDim, j, rendererAttributes; if ((stacked && (i % bounds.groupBarsLen === 0)) || !stacked) { j = i / bounds.groupBarsLen; for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) { shadowBarAttr = Ext.apply({}, shadowAttributes[shadowIndex]); shadow = shadowGroups[shadowIndex].getAt(stacked ? j : i); Ext.copyTo(shadowBarAttr, barAttr, 'x,y,width,height'); if (!shadow) { shadow = surface.add(Ext.apply({ type: 'rect', group: shadowGroups[shadowIndex] }, Ext.apply({}, baseAttrs, shadowBarAttr))); } if (stacked) { totalDim = items[i].totalDim; totalNegDim = items[i].totalNegDim; if (column) { shadowBarAttr.y = zero + totalNegDim - totalDim - 1; shadowBarAttr.height = totalDim; } else { if (reverse) { shadowBarAttr.x = zero + bounds.bbox.width - totalDim; } else { shadowBarAttr.x = zero - totalNegDim; } shadowBarAttr.width = totalDim; } } rendererAttributes = me.renderer(shadow, store.getAt(j), shadowBarAttr, i, store); rendererAttributes.hidden = !!barAttr.hidden; if (animate) { me.onAnimate(shadow, { zero: bounds.zero + bounds.bbox.width, to: rendererAttributes }); } else { shadow.setAttributes(rendererAttributes, true); } shadows.push(shadow); } } return shadows; }, drawSeries: function() { var me = this, chart = me.chart, store = chart.getChartStore(), surface = chart.surface, animate = chart.animate, stacked = me.stacked, column = me.column, chartAxes = chart.axes, boundAxes = me.getAxesForXAndYFields(), boundXAxis = boundAxes.xAxis, boundYAxis = boundAxes.yAxis, enableShadows = chart.shadow, shadowGroups = me.shadowGroups, shadowGroupsLn = shadowGroups.length, group = me.group, seriesStyle = me.seriesStyle, items, ln, i, j, baseAttrs, sprite, rendererAttributes, shadowIndex, shadowGroup, bounds, endSeriesStyle, barAttr, attrs, anim; if (!store || !store.getCount() || me.seriesIsHidden) { me.hide(); me.items = []; return; } endSeriesStyle = Ext.apply({}, this.style, seriesStyle); delete endSeriesStyle.fill; delete endSeriesStyle.x; delete endSeriesStyle.y; delete endSeriesStyle.width; delete endSeriesStyle.height; me.unHighlightItem(); me.cleanHighlights(); me.boundColumn = (boundXAxis && Ext.Array.contains(me.axis,boundXAxis) && chartAxes.get(boundXAxis) && chartAxes.get(boundXAxis).isNumericAxis); me.getPaths(); bounds = me.bounds; items = me.items; baseAttrs = column ? { y: bounds.zero, height: 0 } : { x: bounds.zero, width: 0 }; ln = items.length; for (i = 0; i < ln; i++) { sprite = group.getAt(i); barAttr = items[i].attr; if (enableShadows) { items[i].shadows = me.renderShadows(i, barAttr, baseAttrs, bounds); } if (!sprite) { attrs = Ext.apply({}, baseAttrs, barAttr); attrs = Ext.apply(attrs, endSeriesStyle || {}); sprite = surface.add(Ext.apply({}, { type: 'rect', group: group }, attrs)); } if (animate) { rendererAttributes = me.renderer(sprite, store.getAt(i), barAttr, i, store); sprite._to = rendererAttributes; anim = me.onAnimate(sprite, { zero: bounds.zero + bounds.bbox.width, to: Ext.apply(rendererAttributes, endSeriesStyle) }); if (enableShadows && stacked && (i % bounds.barsLen === 0)) { j = i / bounds.barsLen; for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) { anim.on('afteranimate', function() { this.show(true); }, shadowGroups[shadowIndex].getAt(j)); } } } else { rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(barAttr, { hidden: false }), i, store); sprite.setAttributes(Ext.apply(rendererAttributes, endSeriesStyle), true); } items[i].sprite = sprite; } ln = group.getCount(); for (j = i; j < ln; j++) { group.getAt(j).hide(true); } if (me.stacked) { i = store.getCount(); } if (enableShadows) { for (shadowIndex = 0; shadowIndex < shadowGroupsLn; shadowIndex++) { shadowGroup = shadowGroups[shadowIndex]; ln = shadowGroup.getCount(); for (j = i; j < ln; j++) { shadowGroup.getAt(j).hide(true); } } } me.renderLabels(); }, onCreateLabel: function(storeItem, item, i, display) { var me = this, surface = me.chart.surface, group = me.labelsGroup, config = me.label, endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle || {}), sprite; return surface.add(Ext.apply({ type: 'text', group: group }, endLabelStyle || {})); }, onPlaceLabel: function(label, storeItem, item, i, display, animate, index) { var me = this, opt = me.bounds, groupBarWidth = opt.groupBarWidth, column = me.column, chart = me.chart, chartBBox = chart.chartBBox, resizing = chart.resizing, xValue = item.value[0], yValue = item.value[1], attr = item.attr, config = me.label, stacked = me.stacked, stackedDisplay = config.stackedDisplay, rotate = (config.orientation == 'vertical'), field = [].concat(config.field), format = config.renderer, text, size, width, height, zero = opt.zero, insideStart = 'insideStart', insideEnd = 'insideEnd', outside = 'outside', over = 'over', under = 'under', labelMarginX = 4, labelMarginY = 2, signed = opt.signed, reverse = me.reverse, x, y, finalAttr; if (display == insideStart || display == insideEnd || display == outside) { if (stacked && (display == outside)) { label.hide(true); return; } label.setAttributes({ style: undefined }); text = (Ext.isNumber(index) ? format(storeItem.get(field[index]), label, storeItem, item, i, display, animate, index) : ''); label.setAttributes({ text: text }); size = me.getLabelSize(text, label.attr.style); width = size.width; height = size.height; if (column) { if (!width || !height || (stacked && (attr.height < height))) { label.hide(true); return; } x = attr.x + (rotate ? groupBarWidth/2 : (groupBarWidth - width)/2); if (display == outside) { var free = (yValue >= 0 ? (attr.y - chartBBox.y) : (chartBBox.y + chartBBox.height - attr.y - attr.height)); if (free < height + labelMarginY) { display = insideEnd; } } if (!stacked && (display != outside)) { if (height + labelMarginY > attr.height) { display = outside; } } if (!y) { y = attr.y; if (yValue >= 0) { switch (display) { case insideStart: y += attr.height + (rotate ? -labelMarginY : -height/2); break; case insideEnd: y += (rotate ? height + labelMarginX : height/2); break; case outside: y += (rotate ? -labelMarginY : -height/2); break; } } else { switch (display) { case insideStart: y += (rotate ? height + labelMarginY : height/2); break; case insideEnd: y += (rotate ? attr.height - labelMarginY : attr.height - height/2); break; case outside: y += (rotate ? attr.height + height + labelMarginY : attr.height + height/2); break; } } } } else { if (!width || !height || (stacked && !attr.width)) { label.hide(true); return; } y = attr.y + (rotate ? (groupBarWidth + height)/2 : groupBarWidth/2); if (display == outside) { var free = (yValue >= 0 ? (chartBBox.x + chartBBox.width - attr.x - attr.width) : (attr.x - chartBBox.x)); if (free < width + labelMarginX) { display = insideEnd; } } if ((display != outside) && !rotate) { if (width + labelMarginX * 2 >= attr.width) { if (stacked) { if (height > attr.width) { label.hide(true); return; } x = attr.x + attr.width/2; rotate = true; } else { display = outside; } } } if (!x) { x = attr.x; if (yValue >= 0) { switch (display) { case insideStart: if (reverse) { x += attr.width + (rotate ? -width/2 : -width - labelMarginX); } else { x += (rotate ? width/2 : labelMarginX); } break; case insideEnd: if (reverse) { x -= rotate ? -width/2 : -width - labelMarginX; } else { x += attr.width + (rotate ? -width/2 : -width - labelMarginX); } break; case outside: if (reverse) { x -= width + (rotate ? width/2 : labelMarginX); } else { x += attr.width + (rotate ? width/2 : labelMarginX); } break; } } else { switch (display) { case insideStart: if (reverse) { x -= rotate ? -width/2 : -width - labelMarginX; } else { x += attr.width + (rotate ? -width/2 : -width - labelMarginX); } break; case insideEnd: if (reverse) { x += attr.width + (rotate ? -width/2 : -width - labelMarginX); } else { x += (rotate ? width/2 : labelMarginX); } break; case outside: if (reverse) { x -= width + (rotate ? width/2 : labelMarginX); } else { x += (rotate ? -width/2 : -width - labelMarginX); } break; } } } } } else if (display == over || display == under) { if (stacked && stackedDisplay) { text = label.attr.text; label.setAttributes({ style: Ext.applyIf((label.attr && label.attr.style) || {}, { 'font-weight':'bold', 'font-size':'14px' } ) }); size = me.getLabelSize(text, label.attr.style); width = size.width; height = size.height; switch (display) { case over: if (column) { x = attr.x + (rotate ? groupBarWidth/2 : (groupBarWidth - width)/2); y = zero - (item.totalDim - item.totalNegDim) - height/2 - labelMarginY; } else { x = zero + (item.totalDim - item.totalNegDim) + labelMarginX; y = attr.y + (rotate ? (groupBarWidth + height)/2 : groupBarWidth/2); } break; case under: if (column) { x = attr.x + (rotate ? groupBarWidth/2 : (groupBarWidth - width)/2); y = zero + item.totalNegDim + height/2; } else { x = zero - item.totalNegDim - width - labelMarginX; y = attr.y + (rotate ? (groupBarWidth + height)/2 : groupBarWidth/2); } break; } } } if (x == undefined || y == undefined) { label.hide(true); return; } label.isOutside = (display == outside); label.setAttributes({ text: text }); finalAttr = { x: x, y: y }; finalAttr.rotate = rotate ? { x: x, y: y, degrees: 270 } : me.defaultRotate; if (animate && resizing) { if (column) { x = attr.x + attr.width / 2; y = zero; } else { x = zero; y = attr.y + attr.height / 2; } label.setAttributes({ x: x, y: y }, true); if (rotate) { label.setAttributes({ rotate: { x: x, y: y, degrees: 270 } }, true); } } if (animate) { me.onAnimate(label, { zero: item.point[0], to: finalAttr }); } else { label.setAttributes(Ext.apply(finalAttr, { hidden: false }), true); } }, getLabelSize: function(value, labelStyle) { var tester = this.testerLabel, config = this.label, endLabelStyle = Ext.apply({}, config, labelStyle, this.seriesLabelStyle || {}), rotated = config.orientation === 'vertical', bbox, w, h, undef; if (!tester) { tester = this.testerLabel = this.chart.surface.add(Ext.apply({ type: 'text', opacity: 0 }, endLabelStyle)); } tester.setAttributes({ style: labelStyle, text: value }, true); bbox = tester.getBBox(); w = bbox.width; h = bbox.height; return { width: rotated ? h : w, height: rotated ? w : h }; }, onAnimate: function(sprite, attr) { var me = this, to = attr.to; sprite.show(); if (me.reverse && !me.column) { attr.from = { x: (me.stacked || sprite.type == 'text') ? attr.zero : to.x + to.width, width: 0 }; if (me.inHighlight) { delete attr.from.x; } } return this.callParent(arguments); }, isItemInPoint: function(x, y, item) { var bbox = item.sprite.getBBox(); return bbox.x <= x && bbox.y <= y && (bbox.x + bbox.width) >= x && (bbox.y + bbox.height) >= y; }, hideAll: function(index) { var axes = this.chart.axes, axesItems = axes.items, ln = axesItems.length, i = 0; index = (isNaN(this._index) ? index : this._index) || 0; if (!this.__excludes) { this.__excludes = []; } this.__excludes[index] = true; this.drawSeries(); for (i; i < ln; i++) { axesItems[i].drawAxis(); } }, showAll: function(index) { var axes = this.chart.axes, axesItems = axes.items, ln = axesItems.length, i = 0; index = (isNaN(this._index) ? index : this._index) || 0; if (!this.__excludes) { this.__excludes = []; } this.__excludes[index] = false; this.drawSeries(); for (i; i < ln; i++) { axesItems[i].drawAxis(); } }, getLegendColor: function(index) { var me = this, colors = me.colorArrayStyle, colorLength = colors && colors.length; if (me.style && me.style.fill) { return me.style.fill; } else { return (colors ? colors[(me.themeIdx + index) % colorLength] : '#000'); } }, highlightItem: function(item) { this.callParent(arguments); this.inHighlight = true; this.renderLabels(); delete this.inHighlight; }, unHighlightItem: function() { this.callParent(arguments); this.inHighlight = true; this.renderLabels(); delete this.inHighlight; }, cleanHighlights: function() { this.callParent(arguments); this.inHighlight = true; this.renderLabels(); delete this.inHighlight; } }); Ext.define('Ext.chart.series.Column', { alternateClassName: ['Ext.chart.ColumnSeries', 'Ext.chart.ColumnChart', 'Ext.chart.StackedColumnChart'], extend: Ext.chart.series.Bar , type: 'column', alias: 'series.column', column: true, boundColumn: false, xPadding: 10, yPadding: 0 }); Ext.define('Ext.chart.series.Gauge', { extend: Ext.chart.series.Series , type: "gauge", alias: 'series.gauge', rad: Math.PI / 180, highlightDuration: 150, angleField: false, needle: false, donut: false, showInLegend: false, style: {}, constructor: function(config) { this.callParent(arguments); var me = this, chart = me.chart, surface = chart.surface, store = chart.store, shadow = chart.shadow, i, l, cfg; Ext.apply(me, config, { shadowAttributes: [{ "stroke-width": 6, "stroke-opacity": 1, stroke: 'rgb(200, 200, 200)', translate: { x: 1.2, y: 2 } }, { "stroke-width": 4, "stroke-opacity": 1, stroke: 'rgb(150, 150, 150)', translate: { x: 0.9, y: 1.5 } }, { "stroke-width": 2, "stroke-opacity": 1, stroke: 'rgb(100, 100, 100)', translate: { x: 0.6, y: 1 } }] }); me.group = surface.getGroup(me.seriesId); if (shadow) { for (i = 0, l = me.shadowAttributes.length; i < l; i++) { me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i)); } } surface.customAttributes.segment = function(opt) { return me.getSegment(opt); }; }, initialize: function() { var me = this, store = me.chart.getChartStore(), data = store.data.items, label = me.label, ln = data.length; me.yField = []; if (label && label.field && ln > 0) { me.yField.push(data[0].get(label.field)); } }, getSegment: function(opt) { var me = this, rad = me.rad, cos = Math.cos, sin = Math.sin, abs = Math.abs, x = me.centerX, y = me.centerY, x1 = 0, x2 = 0, x3 = 0, x4 = 0, y1 = 0, y2 = 0, y3 = 0, y4 = 0, delta = 1e-2, r = opt.endRho - opt.startRho, startAngle = opt.startAngle, endAngle = opt.endAngle, midAngle = (startAngle + endAngle) / 2 * rad, margin = opt.margin || 0, flag = abs(endAngle - startAngle) > 180, a1 = Math.min(startAngle, endAngle) * rad, a2 = Math.max(startAngle, endAngle) * rad, singleSlice = false; x += margin * cos(midAngle); y += margin * sin(midAngle); x1 = x + opt.startRho * cos(a1); y1 = y + opt.startRho * sin(a1); x2 = x + opt.endRho * cos(a1); y2 = y + opt.endRho * sin(a1); x3 = x + opt.startRho * cos(a2); y3 = y + opt.startRho * sin(a2); x4 = x + opt.endRho * cos(a2); y4 = y + opt.endRho * sin(a2); if (abs(x1 - x3) <= delta && abs(y1 - y3) <= delta) { singleSlice = true; } if (singleSlice) { return { path: [ ["M", x1, y1], ["L", x2, y2], ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4], ["Z"]] }; } else { return { path: [ ["M", x1, y1], ["L", x2, y2], ["A", opt.endRho, opt.endRho, 0, +flag, 1, x4, y4], ["L", x3, y3], ["A", opt.startRho, opt.startRho, 0, +flag, 0, x1, y1], ["Z"]] }; } }, calcMiddle: function(item) { var me = this, rad = me.rad, slice = item.slice, x = me.centerX, y = me.centerY, startAngle = slice.startAngle, endAngle = slice.endAngle, radius = Math.max(('rho' in slice) ? slice.rho: me.radius, me.label.minMargin), donut = +me.donut, a1 = Math.min(startAngle, endAngle) * rad, a2 = Math.max(startAngle, endAngle) * rad, midAngle = -(a1 + (a2 - a1) / 2), xm = x + (item.endRho + item.startRho) / 2 * Math.cos(midAngle), ym = y - (item.endRho + item.startRho) / 2 * Math.sin(midAngle); item.middle = { x: xm, y: ym }; }, drawSeries: function() { var me = this, chart = me.chart, store = chart.getChartStore(), group = me.group, animate = me.chart.animate, axis = me.chart.axes.get(0), minimum = axis && axis.minimum || me.minimum || 0, maximum = axis && axis.maximum || me.maximum || 0, field = me.angleField || me.field || me.xField, surface = chart.surface, chartBBox = chart.chartBBox, rad = me.rad, donut = +me.donut, values = {}, items = [], seriesStyle = me.seriesStyle, seriesLabelStyle = me.seriesLabelStyle, colorArrayStyle = me.colorArrayStyle, colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0, cos = Math.cos, sin = Math.sin, defaultStart = -180, reverse = me.reverse, rendererAttributes, centerX, centerY, slice, slices, sprite, value, item, ln, record, i, j, startAngle, endAngle, middleAngle, sliceLength, path, p, spriteOptions, bbox, splitAngle, sliceA, sliceB; Ext.apply(seriesStyle, me.style || {}); me.setBBox(); bbox = me.bbox; if (me.colorSet) { colorArrayStyle = me.colorSet; colorArrayLength = colorArrayStyle.length; } if (!store || !store.getCount() || me.seriesIsHidden) { me.hide(); me.items = []; return; } centerX = me.centerX = chartBBox.x + (chartBBox.width / 2); centerY = me.centerY = chartBBox.y + chartBBox.height; me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y); me.slices = slices = []; me.items = items = []; if (!me.value) { record = store.getAt(0); me.value = record.get(field); } value = reverse ? maximum - me.value : me.value; if (me.needle) { sliceA = { series: me, value: value, startAngle: defaultStart, endAngle: 0, rho: me.radius }; splitAngle = defaultStart * (1 - (value - minimum) / (maximum - minimum)); slices.push(sliceA); } else { splitAngle = defaultStart * (1 - (value - minimum) / (maximum - minimum)); sliceA = { series: me, value: value, startAngle: defaultStart, endAngle: splitAngle, rho: me.radius }; sliceB = { series: me, value: maximum - value, startAngle: splitAngle, endAngle: 0, rho: me.radius }; if (reverse) { slices.push(sliceB, sliceA); } else { slices.push(sliceA, sliceB); } } for (i = 0, ln = slices.length; i < ln; i++) { slice = slices[i]; sprite = group.getAt(i); rendererAttributes = Ext.apply({ segment: { startAngle: slice.startAngle, endAngle: slice.endAngle, margin: 0, rho: slice.rho, startRho: slice.rho * +donut / 100, endRho: slice.rho } }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {})); item = Ext.apply({}, rendererAttributes.segment, { slice: slice, series: me, storeItem: record, index: i }); items[i] = item; if (!sprite) { spriteOptions = Ext.apply({ type: "path", group: group }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[i % colorArrayLength] } || {})); sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes)); } slice.sprite = slice.sprite || []; item.sprite = sprite; slice.sprite.push(sprite); if (animate) { rendererAttributes = me.renderer(sprite, record, rendererAttributes, i, store); sprite._to = rendererAttributes; me.onAnimate(sprite, { to: rendererAttributes }); } else { rendererAttributes = me.renderer(sprite, record, Ext.apply(rendererAttributes, { hidden: false }), i, store); sprite.setAttributes(rendererAttributes, true); } } if (me.needle) { splitAngle = splitAngle * Math.PI / 180; if (!me.needleSprite) { me.needleSprite = me.chart.surface.add({ type: 'path', path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle), centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)), 'L', centerX + me.radius * cos(splitAngle), centerY + -Math.abs(me.radius * sin(splitAngle))], 'stroke-width': 4, 'stroke': '#222' }); } else { if (animate) { me.onAnimate(me.needleSprite, { to: { path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle), centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)), 'L', centerX + me.radius * cos(splitAngle), centerY + -Math.abs(me.radius * sin(splitAngle))] } }); } else { me.needleSprite.setAttributes({ type: 'path', path: ['M', centerX + (me.radius * +donut / 100) * cos(splitAngle), centerY + -Math.abs((me.radius * +donut / 100) * sin(splitAngle)), 'L', centerX + me.radius * cos(splitAngle), centerY + -Math.abs(me.radius * sin(splitAngle))] }); } } me.needleSprite.setAttributes({ hidden: false }, true); } delete me.value; }, setValue: function (value) { this.value = value; this.drawSeries(); }, onCreateLabel: function(storeItem, item, i, display) {}, onPlaceLabel: function(label, storeItem, item, i, display, animate, index) {}, onPlaceCallout: function() {}, onAnimate: function(sprite, attr) { sprite.show(); return this.callParent(arguments); }, isItemInPoint: function(x, y, item, i) { var me = this, cx = me.centerX, cy = me.centerY, abs = Math.abs, dx = abs(x - cx), dy = abs(y - cy), startAngle = item.startAngle, endAngle = item.endAngle, rho = Math.sqrt(dx * dx + dy * dy), angle = Math.atan2(y - cy, x - cx) / me.rad; return (i === 0) && (angle >= startAngle && angle < endAngle && rho >= item.startRho && rho <= item.endRho); }, getLegendColor: function(index) { var colors = this.colorSet || this.colorArrayStyle; return colors[index % colors.length]; } }); Ext.define('Ext.chart.series.Line', { extend: Ext.chart.series.Cartesian , alternateClassName: ['Ext.chart.LineSeries', 'Ext.chart.LineChart'], type: 'line', alias: 'series.line', selectionTolerance: 20, showMarkers: true, markerConfig: {}, style: {}, smooth: false, defaultSmoothness: 3, fill: false, constructor: function(config) { this.callParent(arguments); var me = this, surface = me.chart.surface, shadow = me.chart.shadow, i, l; config.highlightCfg = Ext.Object.merge({ 'stroke-width': 3 }, config.highlightCfg); Ext.apply(me, config, { shadowAttributes: [{ "stroke-width": 6, "stroke-opacity": 0.05, stroke: 'rgb(0, 0, 0)', translate: { x: 1, y: 1 } }, { "stroke-width": 4, "stroke-opacity": 0.1, stroke: 'rgb(0, 0, 0)', translate: { x: 1, y: 1 } }, { "stroke-width": 2, "stroke-opacity": 0.15, stroke: 'rgb(0, 0, 0)', translate: { x: 1, y: 1 } }] }); me.group = surface.getGroup(me.seriesId); if (me.showMarkers) { me.markerGroup = surface.getGroup(me.seriesId + '-markers'); } if (shadow) { for (i = 0, l = me.shadowAttributes.length; i < l; i++) { me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i)); } } }, shrink: function(xValues, yValues, size) { var len = xValues.length, ratio = Math.floor(len / size), i = 1, xSum = 0, ySum = 0, xRes = [+xValues[0]], yRes = [+yValues[0]]; for (; i < len; ++i) { xSum += +xValues[i] || 0; ySum += +yValues[i] || 0; if (i % ratio == 0) { xRes.push(xSum/ratio); yRes.push(ySum/ratio); xSum = 0; ySum = 0; } } return { x: xRes, y: yRes }; }, drawSeries: function() { var me = this, chart = me.chart, chartAxes = chart.axes, store = chart.getChartStore(), data = store.data.items, record, storeCount = store.getCount(), surface = me.chart.surface, bbox = {}, group = me.group, showMarkers = me.showMarkers, markerGroup = me.markerGroup, enableShadows = chart.shadow, shadowGroups = me.shadowGroups, shadowAttributes = me.shadowAttributes, smooth = me.smooth, lnsh = shadowGroups.length, dummyPath = ["M"], path = ["M"], renderPath = ["M"], smoothPath = ["M"], markerIndex = chart.markerIndex, axes = [].concat(me.axis), shadowBarAttr, xValues = [], yValues = [], onbreak = false, reverse = me.reverse, storeIndices = [], markerStyle = Ext.apply({}, me.markerStyle), seriesStyle = me.seriesStyle, colorArrayStyle = me.colorArrayStyle, colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0, isNumber = Ext.isNumber, seriesIdx = me.seriesIdx, boundAxes = me.getAxesForXAndYFields(), boundXAxis = boundAxes.xAxis, boundYAxis = boundAxes.yAxis, xAxis = chartAxes && chartAxes.get(boundXAxis), yAxis = chartAxes && chartAxes.get(boundYAxis), xAxisType = boundXAxis ? xAxis && xAxis.type : '', yAxisType = boundYAxis ? yAxis && yAxis.type : '', shadows, shadow, shindex, fromPath, fill, fillPath, rendererAttributes, x, y, prevX, prevY, firstX, firstY, markerCount, i, j, ln, axis, ends, marker, markerAux, item, xValue, yValue, coords, xScale, yScale, minX, maxX, minY, maxY, line, animation, endMarkerStyle, endLineStyle, type, count, opacity, lineOpacity, fillOpacity, fillDefaultValue; if (me.fireEvent('beforedraw', me) === false) { return; } if (!storeCount || me.seriesIsHidden) { me.hide(); me.items = []; if (me.line) { me.line.hide(true); if (me.line.shadows) { shadows = me.line.shadows; for (j = 0, lnsh = shadows.length; j < lnsh; j++) { shadow = shadows[j]; shadow.hide(true); } } if (me.fillPath) { me.fillPath.hide(true); } } me.line = null; me.fillPath = null; return; } endMarkerStyle = Ext.apply(markerStyle || {}, me.markerConfig, { fill: me.seriesStyle.fill || colorArrayStyle[me.themeIdx % colorArrayStyle.length] }); type = endMarkerStyle.type; delete endMarkerStyle.type; endLineStyle = seriesStyle; if (!endLineStyle['stroke-width']) { endLineStyle['stroke-width'] = 0.5; } opacity = 'opacity' in endLineStyle ? endLineStyle.opacity : 1; fillDefaultValue = 'opacity' in endLineStyle ? endLineStyle.opacity : 0.3; lineOpacity = 'lineOpacity' in endLineStyle ? endLineStyle.lineOpacity : opacity; fillOpacity = 'fillOpacity' in endLineStyle ? endLineStyle.fillOpacity : fillDefaultValue; if (markerIndex && markerGroup && markerGroup.getCount()) { for (i = 0; i < markerIndex; i++) { marker = markerGroup.getAt(i); markerGroup.remove(marker); markerGroup.add(marker); markerAux = markerGroup.getAt(markerGroup.getCount() - 2); marker.setAttributes({ x: 0, y: 0, translate: { x: markerAux.attr.translation.x, y: markerAux.attr.translation.y } }, true); } } me.unHighlightItem(); me.cleanHighlights(); me.setBBox(); bbox = me.bbox; me.clipRect = [bbox.x, bbox.y, bbox.width, bbox.height]; if (xAxis) { ends = xAxis.applyData(); minX = ends.from; maxX = ends.to; } if (yAxis) { ends = yAxis.applyData(); minY = ends.from; maxY = ends.to; } if (me.xField && !Ext.isNumber(minX)) { axis = me.getMinMaxXValues(); minX = axis[0]; maxX = axis[1]; } if (me.yField && !Ext.isNumber(minY)) { axis = me.getMinMaxYValues(); minY = axis[0]; maxY = axis[1]; } if (isNaN(minX)) { minX = 0; xScale = bbox.width / ((storeCount - 1) || 1); } else { xScale = bbox.width / ((maxX - minX) || (storeCount -1) || 1); } if (isNaN(minY)) { minY = 0; yScale = bbox.height / ((storeCount - 1) || 1); } else { yScale = bbox.height / ((maxY - minY) || (storeCount - 1) || 1); } for (i = 0, ln = data.length; i < ln; i++) { record = data[i]; xValue = record.get(me.xField); if (xAxisType === 'Time' && typeof xValue === "string") { xValue = Date.parse(xValue); } if (typeof xValue === 'string' || typeof xValue === 'object' && !Ext.isDate(xValue) || xAxisType === 'Category') { xValue = i; } yValue = record.get(me.yField); if (yAxisType === 'Time' && typeof yValue === "string") { yValue = Date.parse(yValue); } if (typeof yValue === 'undefined' || (typeof yValue === 'string' && !yValue)) { continue; } if (typeof yValue === 'string' || typeof yValue === 'object' && !Ext.isDate(yValue) || yAxisType === 'Category') { yValue = i; } storeIndices.push(i); xValues.push(xValue); yValues.push(yValue); } ln = xValues.length; if (ln > bbox.width) { coords = me.shrink(xValues, yValues, bbox.width); xValues = coords.x; yValues = coords.y; } me.items = []; count = 0; ln = xValues.length; for (i = 0; i < ln; i++) { xValue = xValues[i]; yValue = yValues[i]; if (yValue === false) { if (path.length == 1) { path = []; } onbreak = true; me.items.push(false); continue; } else { if (reverse) { x = bbox.x + bbox.width - ((xValue - minX) * xScale); } else { x = (bbox.x + (xValue - minX) * xScale); } x = Ext.Number.toFixed(x, 2); y = Ext.Number.toFixed((bbox.y + bbox.height) - (yValue - minY) * yScale, 2); if (onbreak) { onbreak = false; path.push('M'); } path = path.concat([x, y]); } if ((typeof firstY == 'undefined') && (typeof y != 'undefined')) { firstY = y; firstX = x; } if (!me.line || chart.resizing) { dummyPath = dummyPath.concat([x, bbox.y + bbox.height / 2]); } if (chart.animate && chart.resizing && me.line) { me.line.setAttributes({ path: dummyPath, opacity: lineOpacity }, true); if (me.fillPath) { me.fillPath.setAttributes({ path: dummyPath, opacity: fillOpacity }, true); } if (me.line.shadows) { shadows = me.line.shadows; for (j = 0, lnsh = shadows.length; j < lnsh; j++) { shadow = shadows[j]; shadow.setAttributes({ path: dummyPath }, true); } } } if (showMarkers) { marker = markerGroup.getAt(count++); if (!marker) { marker = Ext.chart.Shape[type](surface, Ext.apply({ group: [group, markerGroup], x: 0, y: 0, translate: { x: +(prevX || x), y: prevY || (bbox.y + bbox.height / 2) }, value: '"' + xValue + ', ' + yValue + '"', zIndex: 4000 }, endMarkerStyle)); marker._to = { translate: { x: +x, y: +y } }; } else { marker.setAttributes({ value: '"' + xValue + ', ' + yValue + '"', x: 0, y: 0, hidden: false }, true); marker._to = { translate: { x: +x, y: +y } }; } } me.items.push({ series: me, value: [xValue, yValue], point: [x, y], sprite: marker, storeItem: store.getAt(storeIndices[i]) }); prevX = x; prevY = y; } if (path.length <= 1) { return; } if (me.smooth) { smoothPath = Ext.draw.Draw.smooth(path, isNumber(smooth) ? smooth : me.defaultSmoothness); } renderPath = smooth ? smoothPath : path; if (chart.markerIndex && me.previousPath) { fromPath = me.previousPath; if (!smooth) { Ext.Array.erase(fromPath, 1, 2); } } else { fromPath = path; } if (!me.line) { me.line = surface.add(Ext.apply({ type: 'path', group: group, path: dummyPath, stroke: endLineStyle.stroke || endLineStyle.fill }, endLineStyle || {})); me me.line.setAttributes({ opacity: lineOpacity }, true); if (enableShadows) { me.line.setAttributes(Ext.apply({}, me.shadowOptions), true); } me.line.setAttributes({ fill: 'none', zIndex: 3000 }); if (!endLineStyle.stroke && colorArrayLength) { me.line.setAttributes({ stroke: colorArrayStyle[me.themeIdx % colorArrayLength] }, true); } if (enableShadows) { shadows = me.line.shadows = []; for (shindex = 0; shindex < lnsh; shindex++) { shadowBarAttr = shadowAttributes[shindex]; shadowBarAttr = Ext.apply({}, shadowBarAttr, { path: dummyPath }); shadow = surface.add(Ext.apply({}, { type: 'path', group: shadowGroups[shindex] }, shadowBarAttr)); shadows.push(shadow); } } } if (me.fill) { fillPath = renderPath.concat([ ["L", x, bbox.y + bbox.height], ["L", firstX, bbox.y + bbox.height], ["L", firstX, firstY] ]); if (!me.fillPath) { me.fillPath = surface.add({ group: group, type: 'path', fill: endLineStyle.fill || colorArrayStyle[me.themeIdx % colorArrayLength], path: dummyPath }); } } markerCount = showMarkers && markerGroup.getCount(); if (chart.animate) { fill = me.fill; line = me.line; rendererAttributes = me.renderer(line, false, { path: renderPath }, i, store); Ext.apply(rendererAttributes, endLineStyle || {}, { stroke: endLineStyle.stroke || endLineStyle.fill }); delete rendererAttributes.fill; line.show(true); if (chart.markerIndex && me.previousPath) { me.animation = animation = me.onAnimate(line, { to: rendererAttributes, from: { path: fromPath } }); } else { me.animation = animation = me.onAnimate(line, { to: rendererAttributes }); } if (enableShadows) { shadows = line.shadows; for(j = 0; j < lnsh; j++) { shadows[j].show(true); if (chart.markerIndex && me.previousPath) { me.onAnimate(shadows[j], { to: { path: renderPath }, from: { path: fromPath } }); } else { me.onAnimate(shadows[j], { to: { path: renderPath } }); } } } if (fill) { me.fillPath.show(true); me.onAnimate(me.fillPath, { to: Ext.apply({}, { path: fillPath, fill: endLineStyle.fill || colorArrayStyle[me.themeIdx % colorArrayLength], 'stroke-width': 0, opacity: fillOpacity }, endLineStyle || {}) }); } if (showMarkers) { count = 0; for(i = 0; i < ln; i++) { if (me.items[i]) { item = markerGroup.getAt(count++); if (item) { rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store); me.onAnimate(item, { to: Ext.applyIf(rendererAttributes, endMarkerStyle || {}) }); item.show(true); } } } for(; count < markerCount; count++) { item = markerGroup.getAt(count); item.hide(true); } } } else { rendererAttributes = me.renderer(me.line, false, { path: renderPath, hidden: false }, i, store); Ext.apply(rendererAttributes, endLineStyle || {}, { stroke: endLineStyle.stroke || endLineStyle.fill }); delete rendererAttributes.fill; me.line.setAttributes(rendererAttributes, true); me.line.setAttributes({ opacity: lineOpacity }, true); if (enableShadows) { shadows = me.line.shadows; for(j = 0; j < lnsh; j++) { shadows[j].setAttributes({ path: renderPath, hidden: false }, true); } } if (me.fill) { me.fillPath.setAttributes({ path: fillPath, hidden: false, opacity: fillOpacity }, true); } if (showMarkers) { count = 0; for(i = 0; i < ln; i++) { if (me.items[i]) { item = markerGroup.getAt(count++); if (item) { rendererAttributes = me.renderer(item, store.getAt(i), item._to, i, store); item.setAttributes(Ext.apply(endMarkerStyle || {}, rendererAttributes || {}), true); if (!item.attr.hidden) { item.show(true); } } } } for(; count < markerCount; count++) { item = markerGroup.getAt(count); item.hide(true); } } } if (chart.markerIndex) { if (me.smooth) { Ext.Array.erase(path, 1, 2); } else { Ext.Array.splice(path, 1, 0, path[1], path[2]); } me.previousPath = path; } me.renderLabels(); me.renderCallouts(); me.fireEvent('draw', me); }, onCreateLabel: function(storeItem, item, i, display) { var me = this, group = me.labelsGroup, config = me.label, bbox = me.bbox, endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle || {}); return me.chart.surface.add(Ext.apply({ 'type': 'text', 'text-anchor': 'middle', 'group': group, 'x': Number(item.point[0]), 'y': bbox.y + bbox.height / 2 }, endLabelStyle || {})); }, onPlaceLabel: function(label, storeItem, item, i, display, animate, index) { var me = this, chart = me.chart, resizing = chart.resizing, config = me.label, format = config.renderer, field = config.field, bbox = me.bbox, x = Number(item.point[0]), y = Number(item.point[1]), radius = item.sprite.attr.radius, labelBox, markerBox, width, height, xOffset, yOffset; label.setAttributes({ text: format(storeItem.get(field), label, storeItem, item, i, display, animate, index), hidden: true }, true); markerBox = item.sprite.getBBox(); markerBox.width = markerBox.width || (radius * 2); markerBox.height = markerBox.height || (radius * 2); labelBox = label.getBBox(); width = labelBox.width/2; height = labelBox.height/2; if (display == 'rotate') { xOffset = markerBox.width/2 + width + height/2; if (x + xOffset + width > bbox.x + bbox.width) { x -= xOffset; } else { x += xOffset; } label.setAttributes({ 'rotation': { x: x, y: y, degrees: -45 } }, true); } else if (display == 'under' || display == 'over') { label.setAttributes({ 'rotation': { degrees: 0 } }, true); if (x < bbox.x + width) { x = bbox.x + width; } else if (x + width > bbox.x + bbox.width) { x = bbox.x + bbox.width - width; } yOffset = markerBox.height/2 + height; y = y + (display == 'over' ? -yOffset : yOffset); if (y < bbox.y + height) { y += 2 * yOffset; } else if (y + height > bbox.y + bbox.height) { y -= 2 * yOffset; } } if (me.chart.animate && !me.chart.resizing) { label.show(true); me.onAnimate(label, { to: { x: x, y: y } }); } else { label.setAttributes({ x: x, y: y }, true); if (resizing && me.animation) { me.animation.on('afteranimate', function() { label.show(true); }); } else { label.show(true); } } }, highlightItem: function() { var me = this, line = me.line; me.callParent(arguments); if (line && !me.highlighted) { if (!('__strokeWidth' in line)) { line.__strokeWidth = parseFloat(line.attr['stroke-width']) || 0; } if (line.__anim) { line.__anim.paused = true; } line.__anim = new Ext.fx.Anim({ target: line, to: { 'stroke-width': line.__strokeWidth + 3 } }); me.highlighted = true; } }, unHighlightItem: function() { var me = this, line = me.line, width; me.callParent(arguments); if (line && me.highlighted) { width = line.__strokeWidth || parseFloat(line.attr['stroke-width']) || 0; line.__anim = new Ext.fx.Anim({ target: line, to: { 'stroke-width': width } }); me.highlighted = false; } }, onPlaceCallout : function(callout, storeItem, item, i, display, animate, index) { if (!display) { return; } var me = this, chart = me.chart, surface = chart.surface, resizing = chart.resizing, config = me.callouts, items = me.items, prev = i == 0? false : items[i -1].point, next = (i == items.length -1)? false : items[i +1].point, cur = [+item.point[0], +item.point[1]], dir, norm, normal, a, aprev, anext, offsetFromViz = config.offsetFromViz || 30, offsetToSide = config.offsetToSide || 10, offsetBox = config.offsetBox || 3, boxx, boxy, boxw, boxh, p, clipRect = me.clipRect, bbox = { width: config.styles.width || 10, height: config.styles.height || 10 }, x, y; if (!prev) { prev = cur; } if (!next) { next = cur; } a = (next[1] - prev[1]) / (next[0] - prev[0]); aprev = (cur[1] - prev[1]) / (cur[0] - prev[0]); anext = (next[1] - cur[1]) / (next[0] - cur[0]); norm = Math.sqrt(1 + a * a); dir = [1 / norm, a / norm]; normal = [-dir[1], dir[0]]; if (aprev > 0 && anext < 0 && normal[1] < 0 || aprev < 0 && anext > 0 && normal[1] > 0) { normal[0] *= -1; normal[1] *= -1; } else if (Math.abs(aprev) < Math.abs(anext) && normal[0] < 0 || Math.abs(aprev) > Math.abs(anext) && normal[0] > 0) { normal[0] *= -1; normal[1] *= -1; } x = cur[0] + normal[0] * offsetFromViz; y = cur[1] + normal[1] * offsetFromViz; boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox)); boxy = y - bbox.height /2 - offsetBox; boxw = bbox.width + 2 * offsetBox; boxh = bbox.height + 2 * offsetBox; if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) { normal[0] *= -1; } if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) { normal[1] *= -1; } x = cur[0] + normal[0] * offsetFromViz; y = cur[1] + normal[1] * offsetFromViz; boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox)); boxy = y - bbox.height /2 - offsetBox; boxw = bbox.width + 2 * offsetBox; boxh = bbox.height + 2 * offsetBox; if (chart.animate) { me.onAnimate(callout.lines, { to: { path: ["M", cur[0], cur[1], "L", x, y, "Z"] } }); if (callout.panel) { callout.panel.setPosition(boxx, boxy, true); } } else { callout.lines.setAttributes({ path: ["M", cur[0], cur[1], "L", x, y, "Z"] }, true); if (callout.panel) { callout.panel.setPosition(boxx, boxy); } } for (p in callout) { callout[p].show(true); } }, isItemInPoint: function(x, y, item, i) { var me = this, items = me.items, tolerance = me.selectionTolerance, result = null, prevItem, nextItem, prevPoint, nextPoint, ln, x1, y1, x2, y2, xIntersect, yIntersect, dist1, dist2, dist, midx, midy, sqrt = Math.sqrt, abs = Math.abs; nextItem = items[i]; prevItem = i && items[i - 1]; if (i >= ln) { prevItem = items[ln - 1]; } prevPoint = prevItem && prevItem.point; nextPoint = nextItem && nextItem.point; x1 = prevItem ? prevPoint[0] : nextPoint[0] - tolerance; y1 = prevItem ? prevPoint[1] : nextPoint[1]; x2 = nextItem ? nextPoint[0] : prevPoint[0] + tolerance; y2 = nextItem ? nextPoint[1] : prevPoint[1]; dist1 = sqrt((x - x1) * (x - x1) + (y - y1) * (y - y1)); dist2 = sqrt((x - x2) * (x - x2) + (y - y2) * (y - y2)); dist = Math.min(dist1, dist2); if (dist <= tolerance) { return dist == dist1? prevItem : nextItem; } return false; }, toggleAll: function(show) { var me = this, i, ln, shadow, shadows; if (!show) { Ext.chart.series.Cartesian.prototype.hideAll.call(me); } else { Ext.chart.series.Cartesian.prototype.showAll.call(me); } if (me.line) { me.line.setAttributes({ hidden: !show }, true); if (me.line.shadows) { for (i = 0, shadows = me.line.shadows, ln = shadows.length; i < ln; i++) { shadow = shadows[i]; shadow.setAttributes({ hidden: !show }, true); } } } if (me.fillPath) { me.fillPath.setAttributes({ hidden: !show }, true); } }, hideAll: function() { this.toggleAll(false); }, showAll: function() { this.toggleAll(true); } }); Ext.define('Ext.chart.series.Pie', { alternateClassName: ['Ext.chart.PieSeries', 'Ext.chart.PieChart'], extend: Ext.chart.series.Series , type: "pie", alias: 'series.pie', accuracy: 100000, rad: Math.PI * 2 / 100000, highlightDuration: 150, angleField: false, lengthField: false, donut: false, showInLegend: false, style: {}, constructor: function(config) { this.callParent(arguments); var me = this, chart = me.chart, surface = chart.surface, store = chart.store, shadow = chart.shadow, i, l, cfg; config.highlightCfg = Ext.merge({ segment: { margin: 20 } }, config.highlight); Ext.apply(me, config, { shadowAttributes: [{ "stroke-width": 6, "stroke-opacity": 1, stroke: 'rgb(200, 200, 200)', translate: { x: 1.2, y: 2 } }, { "stroke-width": 4, "stroke-opacity": 1, stroke: 'rgb(150, 150, 150)', translate: { x: 0.9, y: 1.5 } }, { "stroke-width": 2, "stroke-opacity": 1, stroke: 'rgb(100, 100, 100)', translate: { x: 0.6, y: 1 } }] }); me.group = surface.getGroup(me.seriesId); if (shadow) { for (i = 0, l = me.shadowAttributes.length; i < l; i++) { me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i)); } } surface.customAttributes.segment = function(opt) { var ans = me.getSegment(opt); if (!ans.path || ans.path.length === 0) { ans.path = ['M', 0, 0]; } return ans; }; me.__excludes = me.__excludes || []; }, onRedraw: function(){ this.initialize(); }, initialize: function() { var me = this, store = me.chart.getChartStore(), data = store.data.items, i, ln, rec; me.callParent(); me.yField = []; if (me.label.field) { for (i = 0, ln = data.length; i < ln; i++) { rec = data[i]; me.yField.push(rec.get(me.label.field)); } } }, getSegment: function(opt) { var me = this, rad = me.rad, cos = Math.cos, sin = Math.sin, x = me.centerX, y = me.centerY, x1 = 0, x2 = 0, x3 = 0, x4 = 0, y1 = 0, y2 = 0, y3 = 0, y4 = 0, x5 = 0, y5 = 0, x6 = 0, y6 = 0, delta = 1e-2, startAngle = opt.startAngle, endAngle = opt.endAngle, midAngle = (startAngle + endAngle) / 2 * rad, margin = opt.margin || 0, a1 = Math.min(startAngle, endAngle) * rad, a2 = Math.max(startAngle, endAngle) * rad, c1 = cos(a1), s1 = sin(a1), c2 = cos(a2), s2 = sin(a2), cm = cos(midAngle), sm = sin(midAngle), flag = 0, hsqr2 = 0.7071067811865476; if (a2 - a1 < delta) { return {path: ""}; } if (margin !== 0) { x += margin * cm; y += margin * sm; } x2 = x + opt.endRho * c1; y2 = y + opt.endRho * s1; x4 = x + opt.endRho * c2; y4 = y + opt.endRho * s2; x6 = x + opt.endRho * cm; y6 = y + opt.endRho * sm; if (opt.startRho !== 0) { x1 = x + opt.startRho * c1; y1 = y + opt.startRho * s1; x3 = x + opt.startRho * c2; y3 = y + opt.startRho * s2; x5 = x + opt.startRho * cm; y5 = y + opt.startRho * sm; return { path: [ ["M", x2, y2], ["A", opt.endRho, opt.endRho, 0, 0, 1, x6, y6], ["L", x6, y6], ["A", opt.endRho, opt.endRho, 0, flag, 1, x4, y4], ["L", x4, y4], ["L", x3, y3], ["A", opt.startRho, opt.startRho, 0, flag, 0, x5, y5], ["L", x5, y5], ["A", opt.startRho, opt.startRho, 0, 0, 0, x1, y1], ["L", x1, y1], ["Z"] ] }; } else { return { path: [ ["M", x, y], ["L", x2, y2], ["A", opt.endRho, opt.endRho, 0, 0, 1, x6, y6], ["L", x6, y6], ["A", opt.endRho, opt.endRho, 0, flag, 1, x4, y4], ["L", x4, y4], ["L", x, y], ["Z"] ] }; } }, calcMiddle: function(item) { var me = this, rad = me.rad, slice = item.slice, x = me.centerX, y = me.centerY, startAngle = slice.startAngle, endAngle = slice.endAngle, donut = +me.donut, midAngle = -(startAngle + endAngle) * rad / 2, r = (item.endRho + item.startRho) / 2, xm = x + r * Math.cos(midAngle), ym = y - r * Math.sin(midAngle); item.middle = { x: xm, y: ym }; }, drawSeries: function() { var me = this, store = me.chart.getChartStore(), data = store.data.items, record, group = me.group, animate = me.chart.animate, field = me.angleField || me.field || me.xField, lenField = [].concat(me.lengthField), totalLenField = 0, chart = me.chart, surface = chart.surface, chartBBox = chart.chartBBox, enableShadows = chart.shadow, shadowGroups = me.shadowGroups, shadowAttributes = me.shadowAttributes, lnsh = shadowGroups.length, layers = lenField.length, rhoAcum = 0, donut = +me.donut, layerTotals = [], items = [], totalField = 0, maxLenField = 0, angle = 0, seriesStyle = me.seriesStyle, colorArrayStyle = me.colorArrayStyle, colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0, rendererAttributes, shadowAttr, shadows, shadow, shindex, centerX, centerY, deltaRho, first = 0, slice, slices, sprite, value, item, lenValue, ln, i, j, endAngle, path, p, spriteOptions, bbox; Ext.apply(seriesStyle, me.style || {}); me.setBBox(); bbox = me.bbox; if (me.colorSet) { colorArrayStyle = me.colorSet; colorArrayLength = colorArrayStyle.length; } if (!store || !store.getCount() || me.seriesIsHidden) { me.hide(); me.items = []; return; } me.unHighlightItem(); me.cleanHighlights(); centerX = me.centerX = chartBBox.x + (chartBBox.width / 2); centerY = me.centerY = chartBBox.y + (chartBBox.height / 2); me.radius = Math.min(centerX - chartBBox.x, centerY - chartBBox.y); me.slices = slices = []; me.items = items = []; for (i = 0, ln = data.length; i < ln; i++) { record = data[i]; if (this.__excludes && this.__excludes[i]) { continue; } totalField += +record.get(field); if (lenField[0]) { for (j = 0, totalLenField = 0; j < layers; j++) { totalLenField += +record.get(lenField[j]); } layerTotals[i] = totalLenField; maxLenField = Math.max(maxLenField, totalLenField); } } totalField = totalField || 1; for (i = 0, ln = data.length; i < ln; i++) { record = data[i]; if (this.__excludes && this.__excludes[i]) { value = 0; } else { value = record.get(field); if (first === 0) { first = 1; } } if (first == 1) { first = 2; me.firstAngle = angle = me.accuracy * value / totalField / 2; for (j = 0; j < i; j++) { slices[j].startAngle = slices[j].endAngle = me.firstAngle; } } endAngle = angle - me.accuracy * value / totalField; slice = { series: me, value: value, startAngle: angle, endAngle: endAngle, storeItem: record }; if (lenField[0]) { lenValue = +layerTotals[i]; slice.rho = Math.floor(me.radius / maxLenField * lenValue); } else { slice.rho = me.radius; } slices[i] = slice; (function () { angle = endAngle; })(); } if (enableShadows) { for (i = 0, ln = slices.length; i < ln; i++) { slice = slices[i]; slice.shadowAttrs = []; for (j = 0, rhoAcum = 0, shadows = []; j < layers; j++) { sprite = group.getAt(i * layers + j); deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho; rendererAttributes = { segment: { startAngle: slice.startAngle, endAngle: slice.endAngle, margin: 0, rho: slice.rho, startRho: rhoAcum + (deltaRho * donut / 100), endRho: rhoAcum + deltaRho }, hidden: !slice.value && (slice.startAngle % me.accuracy) == (slice.endAngle % me.accuracy) }; for (shindex = 0, shadows = []; shindex < lnsh; shindex++) { shadowAttr = shadowAttributes[shindex]; shadow = shadowGroups[shindex].getAt(i); if (!shadow) { shadow = chart.surface.add(Ext.apply({}, { type: 'path', group: shadowGroups[shindex], strokeLinejoin: "round" }, rendererAttributes, shadowAttr)); } shadowAttr = me.renderer(shadow, store.getAt(i), Ext.apply({}, rendererAttributes, shadowAttr), i, store); if (animate) { me.onAnimate(shadow, { to: shadowAttr }); } else { shadow.setAttributes(shadowAttr, true); } shadows.push(shadow); } slice.shadowAttrs[j] = shadows; } } } for (i = 0, ln = slices.length; i < ln; i++) { slice = slices[i]; for (j = 0, rhoAcum = 0; j < layers; j++) { sprite = group.getAt(i * layers + j); deltaRho = lenField[j] ? store.getAt(i).get(lenField[j]) / layerTotals[i] * slice.rho: slice.rho; rendererAttributes = Ext.apply({ segment: { startAngle: slice.startAngle, endAngle: slice.endAngle, margin: 0, rho: slice.rho, startRho: rhoAcum + (deltaRho * donut / 100), endRho: rhoAcum + deltaRho }, hidden: (!slice.value && (slice.startAngle % me.accuracy) == (slice.endAngle % me.accuracy)) }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {})); item = Ext.apply({}, rendererAttributes.segment, { slice: slice, series: me, storeItem: slice.storeItem, index: i }); me.calcMiddle(item); if (enableShadows) { item.shadows = slice.shadowAttrs[j]; } items[i] = item; if (!sprite) { spriteOptions = Ext.apply({ type: "path", group: group, middle: item.middle }, Ext.apply(seriesStyle, colorArrayStyle && { fill: colorArrayStyle[(layers > 1? j : i) % colorArrayLength] } || {})); sprite = surface.add(Ext.apply(spriteOptions, rendererAttributes)); } slice.sprite = slice.sprite || []; item.sprite = sprite; slice.sprite.push(sprite); slice.point = [item.middle.x, item.middle.y]; if (animate) { rendererAttributes = me.renderer(sprite, store.getAt(i), rendererAttributes, i, store); sprite._to = rendererAttributes; sprite._animating = true; me.onAnimate(sprite, { to: rendererAttributes, listeners: { afteranimate: { fn: function() { this._animating = false; }, scope: sprite } } }); } else { rendererAttributes = me.renderer(sprite, store.getAt(i), Ext.apply(rendererAttributes, { hidden: false }), i, store); sprite.setAttributes(rendererAttributes, true); } rhoAcum += deltaRho; } } ln = group.getCount(); for (i = 0; i < ln; i++) { if (!slices[(i / layers) >> 0] && group.getAt(i)) { group.getAt(i).hide(true); } } if (enableShadows) { lnsh = shadowGroups.length; for (shindex = 0; shindex < ln; shindex++) { if (!slices[(shindex / layers) >> 0]) { for (j = 0; j < lnsh; j++) { if (shadowGroups[j].getAt(shindex)) { shadowGroups[j].getAt(shindex).hide(true); } } } } } me.renderLabels(); me.renderCallouts(); }, setSpriteAttributes: function(sprite, attrs, animate) { var me = this; if (animate) { sprite.stopAnimation(); sprite.animate({ to: attrs, duration: me.highlightDuration }); } else { sprite.setAttributes(attrs, true); } }, createLabelLine: function(i) { var me = this; calloutLine = me.label.calloutLine, line = me.chart.surface.add({ type: 'path', stroke: (i === undefined ? '#555' : ((calloutLine && calloutLine.color) || me.getLegendColor(i))), lineWidth: (calloutLine && calloutLine.width) || 2, path: 'M0,0Z' }); return line; }, drawLabelLine: function(label, from, to, animate) { var me = this, line = label.lineSprite, path = 'M' + from.x + ' ' + from.y + 'L' + to.x + ' ' + to.y + 'Z'; me.setSpriteAttributes(line, { 'path': path }, animate); }, onCreateLabel: function(storeItem, item, i, display) { var me = this, group = me.labelsGroup, config = me.label, centerX = me.centerX, centerY = me.centerY, middle = item.middle, endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config || {}); return me.chart.surface.add(Ext.apply({ 'type': 'text', 'text-anchor': 'middle', 'group': group, 'x': middle.x, 'y': middle.y }, endLabelStyle)); }, onPlaceLabel: function(label, storeItem, item, i, display, animate, index) { var me = this, chart = me.chart, resizing = chart.resizing, config = me.label, format = config.renderer, field = config.field, centerX = me.centerX, centerY = me.centerY, middle = item.middle, opt = { x: middle.x, y: middle.y }, x = middle.x - centerX, y = middle.y - centerY, from = {}, rho = 1, theta = Math.atan2(y, x || 1), dg = Ext.draw.Draw.degrees(theta), prevDg, labelBox, width, height, isOutside = (display === 'outside'), calloutLine = label.attr.calloutLine, lineWidth = (calloutLine && calloutLine.width) || 2, labelPadding = (label.attr.padding || 20) + (isOutside ? lineWidth/2 + 4 : 0), labelPaddingX = 0, labelPaddingY = 0; opt.hidden = false; if (this.__excludes && this.__excludes[i]) { opt.hidden = true; } label.setAttributes({ opacity: (opt.hidden ? 0 : 1), text: format(storeItem.get(field), label, storeItem, item, i, display, animate, index) }, true); if (label.lineSprite) { var attrs = { opacity: (opt.hidden ? 0 : 1) }; if (opt.hidden) { attrs.translate = {x:0, y:0}; } me.setSpriteAttributes(label.lineSprite, attrs, false); } switch (display) { case 'outside': label.isOutside = true; rho = item.endRho; labelPaddingX = (Math.abs(dg) <= 90 ? labelPadding : -labelPadding); labelPaddingY = (dg >= 0 ? labelPadding : -labelPadding); label.setAttributes({rotation:{degrees: 0}}, true); labelBox = label.getBBox(); width = labelBox.width/2 * Math.cos(theta); height = labelBox.height/2 * Math.sin(theta); width += labelPaddingX; height += labelPaddingY; rho += Math.sqrt(width*width + height*height); opt.x = rho * Math.cos(theta) + centerX; opt.y = rho * Math.sin(theta) + centerY; break; case 'rotate': dg = Ext.draw.Draw.normalizeDegrees(dg); dg = (dg > 90 && dg < 270) ? dg + 180: dg; prevDg = label.attr.rotation.degrees; if (prevDg != null && Math.abs(prevDg - dg) > 180 * 0.5) { if (dg > prevDg) { dg -= 360; } else { dg += 360; } dg = dg % 360; } else { dg = Ext.draw.Draw.normalizeDegrees(dg); } opt.rotate = { degrees: dg, x: opt.x, y: opt.y }; break; default: break; } opt.translate = { x: 0, y: 0 }; if (animate && !resizing && (display != 'rotate' || prevDg != null)) { me.onAnimate(label, { to: opt }); } else { label.setAttributes(opt, true); } label._from = from; if (label.isOutside && calloutLine) { var line = label.lineSprite, animateLine = animate, fromPoint = { x: (item.endRho - lineWidth/2) * Math.cos(theta) + centerX, y: (item.endRho - lineWidth/2) * Math.sin(theta) + centerY }, labelCenter = { x: opt.x, y: opt.y }, toPoint = {}; function sign(x) { return x ? x < 0 ? -1 : 1 : 0; } if (calloutLine && calloutLine.length) { toPoint = { x: (item.endRho + calloutLine.length) * Math.cos(theta) + centerX, y: (item.endRho + calloutLine.length) * Math.sin(theta) + centerY } } else { var normalTheta = Ext.draw.Draw.normalizeRadians(-theta), cos = Math.cos(normalTheta), sin = Math.sin(normalTheta), labelWidth = (labelBox.width + lineWidth + 4)/2, labelHeight = (labelBox.height + lineWidth + 4)/2; if (Math.abs(cos) * labelHeight > Math.abs(sin) * labelWidth) { toPoint.x = labelCenter.x - labelWidth * sign(cos); toPoint.y = labelCenter.y + labelWidth * sin/cos * sign(cos); } else { toPoint.x = labelCenter.x - labelHeight * cos/sin * sign(sin); toPoint.y = labelCenter.y + labelHeight * sign(sin); } } if (!line) { line = label.lineSprite = me.createLabelLine(i); animateLine = false; } me.drawLabelLine(label, fromPoint, toPoint, animateLine); } else { delete label.lineSprite; } }, onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) { var me = this, chart = me.chart, centerX = me.centerX, centerY = me.centerY, middle = item.middle, opt = { x: middle.x, y: middle.y }, x = middle.x - centerX, y = middle.y - centerY, rho = 1, rhoCenter, theta = Math.atan2(y, x || 1), bbox = (callout && callout.label ? callout.label.getBBox() : {width:0,height:0}), offsetFromViz = 20, offsetToSide = 10, offsetBox = 10, p; if (!bbox.width || !bbox.height) { return; } rho = item.endRho + offsetFromViz; rhoCenter = (item.endRho + item.startRho) / 2 + (item.endRho - item.startRho) / 3; opt.x = rho * Math.cos(theta) + centerX; opt.y = rho * Math.sin(theta) + centerY; x = rhoCenter * Math.cos(theta); y = rhoCenter * Math.sin(theta); if (chart.animate) { me.onAnimate(callout.lines, { to: { path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"] } }); me.onAnimate(callout.box, { to: { x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)), y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)), width: bbox.width + 2 * offsetBox, height: bbox.height + 2 * offsetBox } }); me.onAnimate(callout.label, { to: { x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)), y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4) } }); } else { callout.lines.setAttributes({ path: ["M", x + centerX, y + centerY, "L", opt.x, opt.y, "Z", "M", opt.x, opt.y, "l", x > 0 ? offsetToSide: -offsetToSide, 0, "z"] }, true); callout.box.setAttributes({ x: opt.x + (x > 0 ? offsetToSide: -(offsetToSide + bbox.width + 2 * offsetBox)), y: opt.y + (y > 0 ? ( - bbox.height - offsetBox / 2) : ( - bbox.height - offsetBox / 2)), width: bbox.width + 2 * offsetBox, height: bbox.height + 2 * offsetBox }, true); callout.label.setAttributes({ x: opt.x + (x > 0 ? (offsetToSide + offsetBox) : -(offsetToSide + bbox.width + offsetBox)), y: opt.y + (y > 0 ? -bbox.height / 4: -bbox.height / 4) }, true); } for (p in callout) { callout[p].show(true); } }, onAnimate: function(sprite, attr) { sprite.show(); return this.callParent(arguments); }, isItemInPoint: function(x, y, item, i) { var me = this, cx = me.centerX, cy = me.centerY, abs = Math.abs, dx = abs(x - cx), dy = abs(y - cy), startAngle = item.startAngle, endAngle = item.endAngle, rho = Math.sqrt(dx * dx + dy * dy), angle = Math.atan2(y - cy, x - cx) / me.rad; if (angle > me.firstAngle) { angle -= me.accuracy; } return (angle <= startAngle && angle > endAngle && rho >= item.startRho && rho <= item.endRho); }, hideAll: function(index) { var i, l, shadow, shadows, sh, lsh, sprite; index = (isNaN(this._index) ? index : this._index) || 0; this.__excludes = this.__excludes || []; this.__excludes[index] = true; sprite = this.slices[index].sprite; for (sh = 0, lsh = sprite.length; sh < lsh; sh++) { sprite[sh].setAttributes({ hidden: true }, true); var line = sprite[sh].lineSprite; if (line) { line.setAttributes({ hidden: true }, true); } } if (this.slices[index].shadowAttrs) { for (i = 0, shadows = this.slices[index].shadowAttrs, l = shadows.length; i < l; i++) { shadow = shadows[i]; for (sh = 0, lsh = shadow.length; sh < lsh; sh++) { shadow[sh].setAttributes({ hidden: true }, true); } } } this.drawSeries(); }, showAll: function(index) { index = (isNaN(this._index) ? index : this._index) || 0; this.__excludes[index] = false; this.drawSeries(); }, highlightItem: function(item) { var me = this, rad = me.rad, highlightSegment, animate, attrs, i, shadows, shadow, ln, to, itemHighlightSegment, prop, group, display, label, middle, r, x, y, line; item = item || this.items[this._index]; this.unHighlightItem(); if (!item || me.animating || (item.sprite && item.sprite._animating)) { return; } me.callParent([item]); if (!me.highlight) { return; } if ('segment' in me.highlightCfg) { highlightSegment = me.highlightCfg.segment; animate = me.chart.animate; if (me.labelsGroup) { group = me.labelsGroup; display = me.label.display; label = group.getAt(item.index); middle = (item.startAngle + item.endAngle) / 2 * rad; r = highlightSegment.margin || 0; x = r * Math.cos(middle); y = r * Math.sin(middle); if (Math.abs(x) < 1e-10) { x = 0; } if (Math.abs(y) < 1e-10) { y = 0; } me.setSpriteAttributes(label, { translate: {x:x, y:y}}, animate); line = label.lineSprite; if (line) { me.setSpriteAttributes(line, { translate: {x:x, y:y}}, animate); } } if (me.chart.shadow && item.shadows) { i = 0; shadows = item.shadows; ln = shadows.length; for (; i < ln; i++) { shadow = shadows[i]; to = {}; itemHighlightSegment = item.sprite._from.segment; for (prop in itemHighlightSegment) { if (! (prop in highlightSegment)) { to[prop] = itemHighlightSegment[prop]; } } attrs = { segment: Ext.applyIf(to, me.highlightCfg.segment) }; me.setSpriteAttributes(shadow, attrs, animate); } } } }, unHighlightItem: function() { var me = this, items, animate, shadowsEnabled, group, len, i, j, display, shadowLen, p, to, ihs, hs, sprite, shadows, shadow, item, label, attrs; if (!me.highlight) { return; } if (('segment' in me.highlightCfg) && me.items) { items = me.items; animate = me.chart.animate; shadowsEnabled = !!me.chart.shadow; group = me.labelsGroup; len = items.length; i = 0; j = 0; display = me.label.display; for (; i < len; i++) { item = items[i]; if (!item) { continue; } sprite = item.sprite; if (sprite && sprite._highlighted) { if (group) { label = group.getAt(item.index); attrs = Ext.apply({ translate: { x: 0, y: 0 } }, display == 'rotate' ? { rotate: { x: label.attr.x, y: label.attr.y, degrees: label.attr.rotation.degrees } }: {}); me.setSpriteAttributes(label, attrs, animate); var line = label.lineSprite; if (line) { me.setSpriteAttributes(line, { translate: {x:0, y:0}}, animate); } } if (shadowsEnabled) { shadows = item.shadows; shadowLen = shadows.length; for (; j < shadowLen; j++) { to = {}; ihs = item.sprite._to.segment; hs = item.sprite._from.segment; Ext.apply(to, hs); for (p in ihs) { if (! (p in hs)) { to[p] = ihs[p]; } } shadow = shadows[j]; me.setSpriteAttributes(shadow, { segment: to }, animate); } } } } } me.callParent(arguments); }, getLegendColor: function(index) { var me = this; return (me.colorSet && me.colorSet[index % me.colorSet.length]) || me.colorArrayStyle[index % me.colorArrayStyle.length]; } }); Ext.define('Ext.chart.series.Radar', { extend: Ext.chart.series.Series , type: "radar", alias: 'series.radar', rad: Math.PI / 180, showInLegend: false, style: {}, constructor: function(config) { this.callParent(arguments); var me = this, surface = me.chart.surface; me.group = surface.getGroup(me.seriesId); if (me.showMarkers) { me.markerGroup = surface.getGroup(me.seriesId + '-markers'); } }, drawSeries: function() { var me = this, store = me.chart.getChartStore(), data = store.data.items, d, record, group = me.group, chart = me.chart, seriesItems = chart.series.items, s, sLen, series, field = me.field || me.yField, surface = chart.surface, chartBBox = chart.chartBBox, colorArrayStyle = me.colorArrayStyle, centerX, centerY, items, radius, maxValue = 0, fields = [], max = Math.max, cos = Math.cos, sin = Math.sin, pi2 = Math.PI * 2, l = store.getCount(), startPath, path, x, y, rho, i, nfields, seriesStyle = me.seriesStyle, axis = chart.axes && chart.axes.get(0), aggregate = !(axis && axis.maximum); me.setBBox(); maxValue = aggregate? 0 : (axis.maximum || 0); Ext.apply(seriesStyle, me.style || {}); if (!store || !store.getCount() || me.seriesIsHidden) { me.hide(); me.items = []; if (me.radar) { me.radar.hide(true); } me.radar = null; return; } if(!seriesStyle['stroke']){ seriesStyle['stroke'] = colorArrayStyle[me.themeIdx % colorArrayStyle.length]; } me.unHighlightItem(); me.cleanHighlights(); centerX = me.centerX = chartBBox.x + (chartBBox.width / 2); centerY = me.centerY = chartBBox.y + (chartBBox.height / 2); me.radius = radius = Math.min(chartBBox.width, chartBBox.height) /2; me.items = items = []; if (aggregate) { for (s = 0, sLen = seriesItems.length; s < sLen; s++) { series = seriesItems[s]; fields.push(series.yField); } for (d = 0; d < l; d++) { record = data[d]; for (i = 0, nfields = fields.length; i < nfields; i++) { maxValue = max(+record.get(fields[i]), maxValue); } } } maxValue = maxValue || 1; startPath = []; path = []; for (i = 0; i < l; i++) { record = data[i]; rho = radius * record.get(field) / maxValue; x = rho * cos(i / l * pi2); y = rho * sin(i / l * pi2); if (i == 0) { path.push('M', x + centerX, y + centerY); startPath.push('M', 0.01 * x + centerX, 0.01 * y + centerY); } else { path.push('L', x + centerX, y + centerY); startPath.push('L', 0.01 * x + centerX, 0.01 * y + centerY); } items.push({ sprite: false, point: [centerX + x, centerY + y], storeItem: record, series: me }); } path.push('Z'); if (!me.radar) { me.radar = surface.add(Ext.apply({ type: 'path', group: group, path: startPath }, seriesStyle || {})); } if (chart.resizing) { me.radar.setAttributes({ path: startPath }, true); } if (chart.animate) { me.onAnimate(me.radar, { to: Ext.apply({ path: path }, seriesStyle || {}) }); } else { me.radar.setAttributes(Ext.apply({ path: path }, seriesStyle || {}), true); } if (me.showMarkers) { me.drawMarkers(); } me.renderLabels(); me.renderCallouts(); }, drawMarkers: function() { var me = this, chart = me.chart, surface = chart.surface, store = chart.getChartStore(), markerStyle = Ext.apply({}, me.markerStyle || {}), endMarkerStyle = Ext.apply(markerStyle, me.markerConfig, { fill: me.colorArrayStyle[me.themeIdx % me.colorArrayStyle.length] }), items = me.items, type = endMarkerStyle.type, markerGroup = me.markerGroup, centerX = me.centerX, centerY = me.centerY, item, i, l, marker, rendererAttributes; delete endMarkerStyle.type; for (i = 0, l = items.length; i < l; i++) { item = items[i]; marker = markerGroup.getAt(i); if (!marker) { marker = Ext.chart.Shape[type](surface, Ext.apply({ group: markerGroup, x: 0, y: 0, translate: { x: centerX, y: centerY } }, endMarkerStyle)); } else { marker.show(); } item.sprite = marker; if (chart.resizing) { marker.setAttributes({ x: 0, y: 0, translate: { x: centerX, y: centerY } }, true); } marker._to = { translate: { x: item.point[0], y: item.point[1] } }; rendererAttributes = me.renderer(marker, store.getAt(i), marker._to, i, store); rendererAttributes = Ext.applyIf(rendererAttributes || {}, endMarkerStyle || {}); if (chart.animate) { me.onAnimate(marker, { to: rendererAttributes }); } else { marker.setAttributes(rendererAttributes, true); } } }, isItemInPoint: function(x, y, item) { var point, tolerance = 10, abs = Math.abs; point = item.point; return (abs(point[0] - x) <= tolerance && abs(point[1] - y) <= tolerance); }, onCreateLabel: function(storeItem, item, i, display) { var me = this, group = me.labelsGroup, config = me.label, centerX = me.centerX, centerY = me.centerY, endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle || {}); return me.chart.surface.add(Ext.apply({ 'type': 'text', 'text-anchor': 'middle', 'group': group, 'x': centerX, 'y': centerY }, endLabelStyle || {})); }, onPlaceLabel: function(label, storeItem, item, i, display, animate, index) { var me = this, chart = me.chart, resizing = chart.resizing, config = me.label, format = config.renderer, field = config.field, centerX = me.centerX, centerY = me.centerY, opt = { x: Number(item.point[0]), y: Number(item.point[1]) }, x = opt.x - centerX, y = opt.y - centerY, theta = Math.atan2(y, x || 1), deg = theta * 180 / Math.PI, labelBox, direction; function fixAngle(a) { if (a < 0) { a += 360; } return a % 360; } label.setAttributes({ text: format(storeItem.get(field), label, storeItem, item, i, display, animate, index), hidden: true }, true); labelBox = label.getBBox(); deg = fixAngle(deg); if ((deg > 45 && deg < 135) || (deg > 225 && deg < 315)) { direction = (deg > 45 && deg < 135 ? 1 : -1); opt.y += direction * labelBox.height/2; } else { direction = (deg >= 135 && deg <= 225 ? -1 : 1); opt.x += direction * labelBox.width/2; } if (resizing) { label.setAttributes({ x: centerX, y: centerY }, true); } if (animate) { label.show(true); me.onAnimate(label, { to: opt }); } else { label.setAttributes(opt, true); label.show(true); } }, toggleAll: function(show) { var me = this, i, ln, shadow, shadows; if (!show) { Ext.chart.series.Radar.superclass.hideAll.call(me); } else { Ext.chart.series.Radar.superclass.showAll.call(me); } if (me.radar) { me.radar.setAttributes({ hidden: !show }, true); if (me.radar.shadows) { for (i = 0, shadows = me.radar.shadows, ln = shadows.length; i < ln; i++) { shadow = shadows[i]; shadow.setAttributes({ hidden: !show }, true); } } } }, hideAll: function() { this.toggleAll(false); this.hideMarkers(0); }, showAll: function() { this.toggleAll(true); }, hideMarkers: function(index) { var me = this, count = me.markerGroup && me.markerGroup.getCount() || 0, i = index || 0; for (; i < count; i++) { me.markerGroup.getAt(i).hide(true); } }, getAxesForXAndYFields: function() { var me = this, chart = me.chart, axes = chart.axes, axis = [].concat(axes && axes.get(0)); return { yAxis: axis }; } }); Ext.define('Ext.chart.series.Scatter', { extend: Ext.chart.series.Cartesian , type: 'scatter', alias: 'series.scatter', constructor: function(config) { this.callParent(arguments); var me = this, shadow = me.chart.shadow, surface = me.chart.surface, i, l; Ext.apply(me, config, { style: {}, markerConfig: {}, shadowAttributes: [{ "stroke-width": 6, "stroke-opacity": 0.05, stroke: 'rgb(0, 0, 0)' }, { "stroke-width": 4, "stroke-opacity": 0.1, stroke: 'rgb(0, 0, 0)' }, { "stroke-width": 2, "stroke-opacity": 0.15, stroke: 'rgb(0, 0, 0)' }] }); me.group = surface.getGroup(me.seriesId); if (shadow) { for (i = 0, l = me.shadowAttributes.length; i < l; i++) { me.shadowGroups.push(surface.getGroup(me.seriesId + '-shadows' + i)); } } }, getBounds: function() { var me = this, chart = me.chart, store = chart.getChartStore(), chartAxes = chart.axes, boundAxes = me.getAxesForXAndYFields(), boundXAxis = boundAxes.xAxis, boundYAxis = boundAxes.yAxis, bbox, xScale, yScale, ln, minX, minY, maxX, maxY, i, axis, ends; me.setBBox(); bbox = me.bbox; if (axis = chartAxes.get(boundXAxis)) { ends = axis.applyData(); minX = ends.from; maxX = ends.to; } if (axis = chartAxes.get(boundYAxis)) { ends = axis.applyData(); minY = ends.from; maxY = ends.to; } if (me.xField && !Ext.isNumber(minX)) { axis = me.getMinMaxXValues(); minX = axis[0]; maxX = axis[1]; } if (me.yField && !Ext.isNumber(minY)) { axis = me.getMinMaxYValues(); minY = axis[0]; maxY = axis[1]; } if (isNaN(minX)) { minX = 0; maxX = store.getCount() - 1; xScale = bbox.width / (store.getCount() - 1); } else { xScale = bbox.width / (maxX - minX); } if (isNaN(minY)) { minY = 0; maxY = store.getCount() - 1; yScale = bbox.height / (store.getCount() - 1); } else { yScale = bbox.height / (maxY - minY); } return { bbox: bbox, minX: minX, minY: minY, xScale: xScale, yScale: yScale }; }, getPaths: function() { var me = this, chart = me.chart, enableShadows = chart.shadow, store = chart.getChartStore(), data = store.data.items, i, ln, record, group = me.group, bounds = me.bounds = me.getBounds(), bbox = me.bbox, xScale = bounds.xScale, yScale = bounds.yScale, minX = bounds.minX, minY = bounds.minY, boxX = bbox.x, boxY = bbox.y, boxHeight = bbox.height, items = me.items = [], attrs = [], reverse = me.reverse, x, y, xValue, yValue, sprite; for (i = 0, ln = data.length; i < ln; i++) { record = data[i]; xValue = record.get(me.xField); yValue = record.get(me.yField); if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue) || xValue == null || yValue == null) { continue; } if (typeof xValue == 'string' || typeof xValue == 'object' && !Ext.isDate(xValue)) { xValue = i; } if (typeof yValue == 'string' || typeof yValue == 'object' && !Ext.isDate(yValue)) { yValue = i; } if (reverse) { x = boxX + bbox.width - ((xValue - minX) * xScale); } else { x = boxX + (xValue - minX) * xScale; } y = boxY + boxHeight - (yValue - minY) * yScale; attrs.push({ x: x, y: y }); me.items.push({ series: me, value: [xValue, yValue], point: [x, y], storeItem: record }); if (chart.animate && chart.resizing) { sprite = group.getAt(i); if (sprite) { me.resetPoint(sprite); if (enableShadows) { me.resetShadow(sprite); } } } } return attrs; }, resetPoint: function(sprite) { var bbox = this.bbox; sprite.setAttributes({ translate: { x: (bbox.x + bbox.width) / 2, y: (bbox.y + bbox.height) / 2 } }, true); }, resetShadow: function(sprite) { var me = this, shadows = sprite.shadows, shadowAttributes = me.shadowAttributes, ln = me.shadowGroups.length, bbox = me.bbox, i, attr; for (i = 0; i < ln; i++) { attr = Ext.apply({}, shadowAttributes[i]); if (attr.translate) { attr.translate.x += (bbox.x + bbox.width) / 2; attr.translate.y += (bbox.y + bbox.height) / 2; } else { attr.translate = { x: (bbox.x + bbox.width) / 2, y: (bbox.y + bbox.height) / 2 }; } shadows[i].setAttributes(attr, true); } }, createPoint: function(attr, type) { var me = this, chart = me.chart, group = me.group, bbox = me.bbox; return Ext.chart.Shape[type](chart.surface, Ext.apply({}, { x: 0, y: 0, group: group, translate: { x: (bbox.x + bbox.width) / 2, y: (bbox.y + bbox.height) / 2 } }, attr)); }, createShadow: function(sprite, endMarkerStyle, type) { var me = this, chart = me.chart, shadowGroups = me.shadowGroups, shadowAttributes = me.shadowAttributes, lnsh = shadowGroups.length, bbox = me.bbox, i, shadow, shadows, attr; sprite.shadows = shadows = []; for (i = 0; i < lnsh; i++) { attr = Ext.apply({}, shadowAttributes[i]); if (attr.translate) { attr.translate.x += (bbox.x + bbox.width) / 2; attr.translate.y += (bbox.y + bbox.height) / 2; } else { Ext.apply(attr, { translate: { x: (bbox.x + bbox.width) / 2, y: (bbox.y + bbox.height) / 2 } }); } Ext.apply(attr, endMarkerStyle); shadow = Ext.chart.Shape[type](chart.surface, Ext.apply({}, { x: 0, y: 0, group: shadowGroups[i] }, attr)); shadows.push(shadow); } }, drawSeries: function() { var me = this, chart = me.chart, store = chart.getChartStore(), group = me.group, enableShadows = chart.shadow, shadowGroups = me.shadowGroups, shadowAttributes = me.shadowAttributes, lnsh = shadowGroups.length, sprite, attrs, attr, ln, i, endMarkerStyle, shindex, type, shadows, rendererAttributes, shadowAttribute; endMarkerStyle = Ext.apply(me.markerStyle, me.markerConfig); type = endMarkerStyle.type || 'circle'; delete endMarkerStyle.type; if (!store || !store.getCount()) { me.hide(); me.items = []; return; } me.unHighlightItem(); me.cleanHighlights(); attrs = me.getPaths(); ln = attrs.length; for (i = 0; i < ln; i++) { attr = attrs[i]; sprite = group.getAt(i); Ext.apply(attr, endMarkerStyle); if (!sprite) { sprite = me.createPoint(attr, type); if (enableShadows) { me.createShadow(sprite, endMarkerStyle, type); } } shadows = sprite.shadows; if (chart.animate) { rendererAttributes = me.renderer(sprite, store.getAt(i), { translate: attr }, i, store); sprite._to = rendererAttributes; me.onAnimate(sprite, { to: rendererAttributes }); for (shindex = 0; shindex < lnsh; shindex++) { shadowAttribute = Ext.apply({}, shadowAttributes[shindex]); rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({}, { hidden: false, translate: { x: attr.x + (shadowAttribute.translate? shadowAttribute.translate.x : 0), y: attr.y + (shadowAttribute.translate? shadowAttribute.translate.y : 0) } }, shadowAttribute), i, store); me.onAnimate(shadows[shindex], { to: rendererAttributes }); } } else { rendererAttributes = me.renderer(sprite, store.getAt(i), { translate: attr }, i, store); sprite._to = rendererAttributes; sprite.setAttributes(rendererAttributes, true); for (shindex = 0; shindex < lnsh; shindex++) { shadowAttribute = Ext.apply({}, shadowAttributes[shindex]); rendererAttributes = me.renderer(shadows[shindex], store.getAt(i), Ext.apply({}, { hidden: false, translate: { x: attr.x + (shadowAttribute.translate? shadowAttribute.translate.x : 0), y: attr.y + (shadowAttribute.translate? shadowAttribute.translate.y : 0) } }, shadowAttribute), i, store); shadows[shindex].setAttributes(rendererAttributes, true); } } me.items[i].sprite = sprite; } ln = group.getCount(); for (i = attrs.length; i < ln; i++) { group.getAt(i).hide(true); } me.renderLabels(); me.renderCallouts(); }, onCreateLabel: function(storeItem, item, i, display) { var me = this, group = me.labelsGroup, config = me.label, endLabelStyle = Ext.apply({}, config, me.seriesLabelStyle), bbox = me.bbox; return me.chart.surface.add(Ext.apply({ type: 'text', 'text-anchor': 'middle', group: group, x: Number(item.point[0]), y: bbox.y + bbox.height / 2 }, endLabelStyle)); }, onPlaceLabel: function(label, storeItem, item, i, display, animate, index) { var me = this, chart = me.chart, resizing = chart.resizing, config = me.label, format = config.renderer, field = config.field, bbox = me.bbox, x = Number(item.point[0]), y = Number(item.point[1]), radius = item.sprite.attr.radius, labelBox, markerBox, width, height, xOffset, yOffset, anim; label.setAttributes({ text: format(storeItem.get(field), label, storeItem, item, i, display, animate, index), hidden: true }, true); markerBox = item.sprite.getBBox(); markerBox.width = markerBox.width || (radius * 2); markerBox.height = markerBox.height || (radius * 2); labelBox = label.getBBox(); width = labelBox.width/2; height = labelBox.height/2; if (display == 'rotate') { xOffset = markerBox.width/2 + width + height/2; if (x + xOffset + width > bbox.x + bbox.width) { x -= xOffset; } else { x += xOffset; } label.setAttributes({ 'rotation': { x: x, y: y, degrees: -45 } }, true); } else if (display == 'under' || display == 'over') { label.setAttributes({ 'rotation': { degrees: 0 } }, true); if (x < bbox.x + width) { x = bbox.x + width; } else if (x + width > bbox.x + bbox.width) { x = bbox.x + bbox.width - width; } yOffset = markerBox.height/2 + height; y = y + (display == 'over' ? -yOffset : yOffset); if (y < bbox.y + height) { y += 2 * yOffset; } else if (y + height > bbox.y + bbox.height) { y -= 2 * yOffset; } } if (!chart.animate) { label.setAttributes({ x: x, y: y }, true); label.show(true); } else { if (resizing) { anim = item.sprite.getActiveAnimation(); if (anim) { anim.on('afteranimate', function() { label.setAttributes({ x: x, y: y }, true); label.show(true); }); } else { label.show(true); } } else { me.onAnimate(label, { to: { x: x, y: y } }); } } }, onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) { var me = this, chart = me.chart, surface = chart.surface, resizing = chart.resizing, config = me.callouts, items = me.items, cur = item.point, normal, bbox = callout.label.getBBox(), offsetFromViz = 30, offsetToSide = 10, offsetBox = 3, boxx, boxy, boxw, boxh, p, clipRect = me.bbox, x, y; normal = [Math.cos(Math.PI /4), -Math.sin(Math.PI /4)]; x = cur[0] + normal[0] * offsetFromViz; y = cur[1] + normal[1] * offsetFromViz; boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox)); boxy = y - bbox.height /2 - offsetBox; boxw = bbox.width + 2 * offsetBox; boxh = bbox.height + 2 * offsetBox; if (boxx < clipRect[0] || (boxx + boxw) > (clipRect[0] + clipRect[2])) { normal[0] *= -1; } if (boxy < clipRect[1] || (boxy + boxh) > (clipRect[1] + clipRect[3])) { normal[1] *= -1; } x = cur[0] + normal[0] * offsetFromViz; y = cur[1] + normal[1] * offsetFromViz; boxx = x + (normal[0] > 0? 0 : -(bbox.width + 2 * offsetBox)); boxy = y - bbox.height /2 - offsetBox; boxw = bbox.width + 2 * offsetBox; boxh = bbox.height + 2 * offsetBox; if (chart.animate) { me.onAnimate(callout.lines, { to: { path: ["M", cur[0], cur[1], "L", x, y, "Z"] } }, true); me.onAnimate(callout.box, { to: { x: boxx, y: boxy, width: boxw, height: boxh } }, true); me.onAnimate(callout.label, { to: { x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)), y: y } }, true); } else { callout.lines.setAttributes({ path: ["M", cur[0], cur[1], "L", x, y, "Z"] }, true); callout.box.setAttributes({ x: boxx, y: boxy, width: boxw, height: boxh }, true); callout.label.setAttributes({ x: x + (normal[0] > 0? offsetBox : -(bbox.width + offsetBox)), y: y }, true); } for (p in callout) { callout[p].show(true); } }, onAnimate: function(sprite, attr) { sprite.show(); return this.callParent(arguments); }, isItemInPoint: function(x, y, item) { var point, tolerance = 10, abs = Math.abs; function dist(point) { var dx = abs(point[0] - x), dy = abs(point[1] - y); return Math.sqrt(dx * dx + dy * dy); } point = item.point; return (point[0] - tolerance <= x && point[0] + tolerance >= x && point[1] - tolerance <= y && point[1] + tolerance >= y); } }); Ext.define('Ext.layout.container.Table', { alias: ['layout.table'], extend: Ext.layout.container.Container , alternateClassName: 'Ext.layout.TableLayout', monitorResize:false, type: 'table', createsInnerCt: true, targetCls: Ext.baseCSSPrefix + 'table-layout-ct', tableCls: Ext.baseCSSPrefix + 'table-layout', cellCls: Ext.baseCSSPrefix + 'table-layout-cell', tableAttrs: null, getItemSizePolicy: function (item) { return this.autoSizePolicy; }, initHierarchyState: function (hierarchyStateInner) { hierarchyStateInner.inShrinkWrapTable = true; }, getLayoutItems: function() { var me = this, result = [], items = me.callParent(), item, len = items.length, i; for (i = 0; i < len; i++) { item = items[i]; if (!item.hidden) { result.push(item); } } return result; }, getHiddenItems: function(){ var result = [], items = this.owner.items.items, len = items.length, i = 0, item; for (; i < len; ++i) { item = items[i]; if (item.rendered && item.hidden) { result.push(item); } } return result; }, renderChildren: function() { var me = this, items = me.getLayoutItems(), tbody = me.owner.getTargetEl().child('table', true).tBodies[0], rows = tbody.rows, i = 0, len = items.length, hiddenItems = me.getHiddenItems(), cells, curCell, rowIdx, cellIdx, item, trEl, tdEl, itemCt, el; cells = me.calculateCells(items); for (; i < len; i++) { curCell = cells[i]; rowIdx = curCell.rowIdx; cellIdx = curCell.cellIdx; item = items[i]; trEl = rows[rowIdx]; if (!trEl) { trEl = tbody.insertRow(rowIdx); if (me.trAttrs) { trEl.set(me.trAttrs); } } itemCt = tdEl = Ext.get(trEl.cells[cellIdx] || trEl.insertCell(cellIdx)); if (me.needsDivWrap()) { itemCt = tdEl.first() || tdEl.createChild({ tag: 'div', role: 'presentation' }); itemCt.setWidth(null); } if (!item.rendered) { me.renderItem(item, itemCt, 0); } else if (!me.isValidParent(item, itemCt, rowIdx, cellIdx, tbody)) { me.moveItem(item, itemCt, 0); } if (me.tdAttrs) { tdEl.set(me.tdAttrs); } if (item.tdAttrs) { tdEl.set(item.tdAttrs); } tdEl.set({ colSpan: item.colspan || 1, rowSpan: item.rowspan || 1, id: item.cellId || '', cls: me.cellCls + ' ' + (item.cellCls || '') }); if (!cells[i + 1] || cells[i + 1].rowIdx !== rowIdx) { cellIdx++; while (trEl.cells[cellIdx]) { trEl.deleteCell(cellIdx); } } } rowIdx++; while (tbody.rows[rowIdx]) { tbody.deleteRow(rowIdx); } for (i = 0, len = hiddenItems.length; i < len; ++i) { me.ensureInDocument(hiddenItems[i].getEl()); } }, ensureInDocument: function(el){ var dom = el.dom.parentNode; while (dom) { if (dom.tagName.toUpperCase() == 'BODY') { return; } dom = dom.parentNode; } Ext.getDetachedBody().appendChild(el); }, calculate: function (ownerContext) { if (!ownerContext.hasDomProp('containerChildrenSizeDone')) { this.done = false; } else { var targetContext = ownerContext.targetContext, widthShrinkWrap = ownerContext.widthModel.shrinkWrap, heightShrinkWrap = ownerContext.heightModel.shrinkWrap, shrinkWrap = heightShrinkWrap || widthShrinkWrap, table = shrinkWrap && targetContext.el.child('table', true), targetPadding = shrinkWrap && targetContext.getPaddingInfo(); if (widthShrinkWrap) { ownerContext.setContentWidth(table.offsetWidth + targetPadding.width, true); } if (heightShrinkWrap) { ownerContext.setContentHeight(table.offsetHeight + targetPadding.height, true); } } }, finalizeLayout: function() { if (this.needsDivWrap()) { var items = this.getLayoutItems(), i, iLen = items.length, item; for (i = 0; i < iLen; i++) { item = items[i]; Ext.fly(item.el.dom.parentNode).setWidth(item.getWidth()); } } if (Ext.isIE6 || Ext.isIEQuirks) { this.owner.getTargetEl().child('table').repaint(); } }, calculateCells: function(items) { var cells = [], rowIdx = 0, colIdx = 0, cellIdx = 0, totalCols = this.columns || Infinity, rowspans = [], i = 0, j, len = items.length, item; for (; i < len; i++) { item = items[i]; while (colIdx >= totalCols || rowspans[colIdx] > 0) { if (colIdx >= totalCols) { colIdx = 0; cellIdx = 0; rowIdx++; for (j = 0; j < totalCols; j++) { if (rowspans[j] > 0) { rowspans[j]--; } } } else { colIdx++; } } cells.push({ rowIdx: rowIdx, cellIdx: cellIdx }); for (j = item.colspan || 1; j; --j) { rowspans[colIdx] = item.rowspan || 1; ++colIdx; } ++cellIdx; } return cells; }, getRenderTree: function() { var me = this, items = me.getLayoutItems(), cells, rows = [], result = Ext.apply({ tag: 'table', role: 'presentation', cls: me.tableCls, cellspacing: 0, cellpadding: 0, cn: { tag: 'tbody', role: 'presentation', cn: rows } }, me.tableAttrs), tdAttrs = me.tdAttrs, needsDivWrap = me.needsDivWrap(), i, len = items.length, item, curCell, tr, rowIdx, cellIdx, cell; cells = me.calculateCells(items); for (i = 0; i < len; i++) { item = items[i]; curCell = cells[i]; rowIdx = curCell.rowIdx; cellIdx = curCell.cellIdx; tr = rows[rowIdx]; if (!tr) { tr = rows[rowIdx] = { tag: 'tr', role: 'presentation', cn: [] }; if (me.trAttrs) { Ext.apply(tr, me.trAttrs); } } cell = tr.cn[cellIdx] = { tag: 'td', role: 'presentation' }; if (tdAttrs) { Ext.apply(cell, tdAttrs); } Ext.apply(cell, { colSpan: item.colspan || 1, rowSpan: item.rowspan || 1, id: item.cellId || '', cls: me.cellCls + ' ' + (item.cellCls || '') }); if (needsDivWrap) { cell = cell.cn = { tag: 'div', role: 'presentation' }; } me.configureItem(item); cell.cn = item.getRenderTree(); } return result; }, isValidParent: function(item, target, rowIdx, cellIdx) { var tbody, correctCell, table; if (arguments.length === 3) { table = item.el.up('table'); return table && table.dom.parentNode === target.dom; } tbody = this.owner.getTargetEl().child('table', true).tBodies[0]; correctCell = tbody.rows[rowIdx].cells[cellIdx]; return item.el.dom.parentNode === correctCell; }, needsDivWrap: function() { return Ext.isOpera10_5; } }); Ext.define('Ext.container.ButtonGroup', { extend: Ext.panel.Panel , alias: 'widget.buttongroup', alternateClassName: 'Ext.ButtonGroup', baseCls: Ext.baseCSSPrefix + 'btn-group', layout: { type: 'table' }, defaultType: 'button', frame: true, frameHeader: false, titleAlign: 'center', noTitleCls: 'notitle', ariaRole: 'group', initComponent : function() { var me = this, cols = me.columns; if (cols) { me.layout = Ext.apply({}, {columns: cols}, me.layout); } if (!me.title) { me.addClsWithUI(me.noTitleCls); } me.callParent(arguments); }, onBeforeAdd: function(component) { if (component.isButton) { if (this.defaultButtonUI && component.ui === 'default' && !component.hasOwnProperty('ui')) { component.ui = this.defaultButtonUI; } else { component.ui = component.ui + '-toolbar'; } } this.callParent(arguments); }, applyDefaults: function(c) { if (!Ext.isString(c)) { c = this.callParent(arguments); } return c; } }); Ext.define('Ext.container.Monitor', { target: null, selector: '', scope: null, addHandler: null, removeHandler: null, disabled: 0, constructor: function(config){ Ext.apply(this, config); }, bind: function(target){ var me = this; me.target = target; target.on('beforedestroy', me.disable, me); me.onContainerAdd(target); }, unbind: function() { var me = this, target = me.target; if (target) { target.un('beforedestroy', me.disable, me); } me.items = null; }, disable: function(){ ++this.disabled; }, enable: function(){ if (this.disabled > 0) { --this.disabled; } }, handleAdd: function(ct, comp) { if (!this.disabled) { if (comp.is(this.selector)) { this.onItemAdd(comp.ownerCt, comp); } if (comp.isQueryable) { this.onContainerAdd(comp); } } }, onItemAdd: function(ct, comp){ var me = this, items = me.items, handler = me.addHandler; if (!me.disabled) { if (handler) { handler.call(me.scope || comp, comp); } if (items) { items.add(comp); } } }, onItemRemove: function(ct, comp){ var me = this, items = me.items, handler = me.removeHandler; if (!me.disabled) { if (handler) { handler.call(me.scope || comp, comp); } if (items) { items.remove(comp); } } }, onContainerAdd: function(ct, preventChildren) { var me = this, items, len, handleAdd = me.handleAdd, handleRemove = me.handleRemove, i, comp; if (ct.isContainer) { ct.on('add', handleAdd, me); ct.on('dockedadd', handleAdd, me); ct.on('remove', handleRemove, me); ct.on('dockedremove', handleRemove, me); } if (preventChildren !== true) { items = ct.query(me.selector); for (i = 0, len = items.length; i < len; ++i) { comp = items[i]; me.onItemAdd(comp.ownerCt, comp); } } items = ct.query('>container'); for (i = 0, len = items.length; i < len; ++i) { me.onContainerAdd(items[i], true); } }, handleRemove: function(ct, comp) { var me = this; if (!me.disabled) { if (comp.is(me.selector)) { me.onItemRemove(ct, comp); } if (comp.isQueryable) { me.onContainerRemove(ct, comp); } } }, onContainerRemove: function(ct, comp){ var me = this, items, i, len, item; if (!comp.isDestroyed && !comp.destroying && comp.isContainer) { me.removeCtListeners(comp); items = comp.query(me.selector); for (i = 0, len = items.length; i < len; ++i) { item = items[i]; me.onItemRemove(item.ownerCt, item); } items = comp.query('container'); for (i = 0, len = items.length; i < len; ++i) { me.removeCtListeners(items[i]); } } else { me.invalidateItems(); } }, removeCtListeners: function(comp){ var me = this; comp.un('add', me.handleAdd, me); comp.un('dockedadd', me.handleAdd, me); comp.un('remove', me.handleRemove, me); comp.un('dockedremove', me.handleRemove, me); }, getItems: function(){ var me = this, items = me.items; if (!items) { items = me.items = new Ext.util.MixedCollection(); items.addAll(me.target.query(me.selector)); } return items; }, invalidateItems: function(){ this.items = null; } }); Ext.define('Ext.container.Viewport', { extend: Ext.container.Container , alias: 'widget.viewport', alternateClassName: 'Ext.Viewport', isViewport: true, ariaRole: 'application', preserveElOnDestroy: true, viewportCls: Ext.baseCSSPrefix + 'viewport', initComponent : function() { var me = this, html = document.body.parentNode, el = me.el = Ext.getBody(); Ext.getScrollbarSize(); me.width = me.height = undefined; me.callParent(arguments); Ext.fly(html).addCls(me.viewportCls); if (me.autoScroll) { Ext.fly(html).setStyle(me.getOverflowStyle()); delete me.autoScroll; } el.setHeight = el.setWidth = Ext.emptyFn; el.dom.scroll = 'no'; me.allowDomMove = false; me.renderTo = me.el; }, applyTargetCls: function(targetCls) { this.el.addCls(targetCls); }, onRender: function() { var me = this; me.callParent(arguments); me.width = Ext.Element.getViewportWidth(); me.height = Ext.Element.getViewportHeight(); }, afterFirstLayout: function() { var me = this; me.callParent(arguments); setTimeout(function() { Ext.EventManager.onWindowResize(me.fireResize, me); }, 1); }, fireResize : function(width, height){ if (width != this.width || height != this.height) { this.setSize(width, height); } }, initHierarchyState: function(hierarchyState) { this.callParent([this.hierarchyState = Ext.rootHierarchyState]); }, beforeDestroy: function(){ var me = this; me.removeUIFromElement(); me.el.removeCls(me.baseCls); Ext.fly(document.body.parentNode).removeCls(me.viewportCls); me.callParent(); } }); Ext.define('Ext.data.IdGenerator', { isGenerator: true, constructor: function(config) { var me = this; Ext.apply(me, config); if (me.id) { Ext.data.IdGenerator.all[me.id] = me; } }, getRecId: function (rec) { return rec.modelName + '-' + rec.internalId; }, statics: { all: {}, get: function (config) { var generator, id, type; if (typeof config == 'string') { id = type = config; config = null; } else if (config.isGenerator) { return config; } else { id = config.id || config.type; type = config.type; } generator = this.all[id]; if (!generator) { generator = Ext.create('idgen.' + type, config); } return generator; } } }); Ext.define('Ext.data.SortTypes', { singleton: true, none : Ext.identityFn, stripTagsRE : /<\/?[^>]+>/gi, asText : function(s) { return String(s).replace(this.stripTagsRE, ""); }, asUCText : function(s) { return String(s).toUpperCase().replace(this.stripTagsRE, ""); }, asUCString : function(s) { return String(s).toUpperCase(); }, asDate : function(s) { if(!s){ return 0; } if(Ext.isDate(s)){ return s.getTime(); } return Date.parse(String(s)); }, asFloat : function(s) { var val = parseFloat(String(s).replace(/,/g, "")); return isNaN(val) ? 0 : val; }, asInt : function(s) { var val = parseInt(String(s).replace(/,/g, ""), 10); return isNaN(val) ? 0 : val; } }); Ext.define('Ext.data.Types', { singleton: true }, function() { var st = Ext.data.SortTypes; Ext.apply(Ext.data.Types, { stripRe: /[\$,%]/g, AUTO: { sortType: st.none, type: 'auto' }, STRING: { convert: function(v) { var defaultValue = this.useNull ? null : ''; return (v === undefined || v === null) ? defaultValue : String(v); }, sortType: st.asUCString, type: 'string' }, INT: { convert: function(v) { if (typeof v == 'number') { return parseInt(v); } return v !== undefined && v !== null && v !== '' ? parseInt(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0); }, sortType: st.none, type: 'int' }, FLOAT: { convert: function(v) { if (typeof v === 'number') { return v; } return v !== undefined && v !== null && v !== '' ? parseFloat(String(v).replace(Ext.data.Types.stripRe, ''), 10) : (this.useNull ? null : 0); }, sortType: st.none, type: 'float' }, BOOL: { convert: function(v) { if (typeof v === 'boolean') { return v; } if (this.useNull && (v === undefined || v === null || v === '')) { return null; } return v === 'true' || v == 1; }, sortType: st.none, type: 'bool' }, DATE: { convert: function(v) { var df = this.dateReadFormat || this.dateFormat, parsed; if (!v) { return null; } if (v instanceof Date) { return v; } if (df) { return Ext.Date.parse(v, df); } parsed = Date.parse(v); return parsed ? new Date(parsed) : null; }, sortType: st.asDate, type: 'date' } }); Ext.apply(Ext.data.Types, { BOOLEAN: this.BOOL, INTEGER: this.INT, NUMBER: this.FLOAT }); }); Ext.define('Ext.data.Field', { alias: 'data.field', isField: true, constructor : function(config) { var me = this, types = Ext.data.Types, st; if (Ext.isString(config)) { config = {name: config}; } Ext.apply(me, config); st = me.sortType; if (me.type) { if (Ext.isString(me.type)) { me.type = types[me.type.toUpperCase()] || types.AUTO; } } else { me.type = types.AUTO; } if (Ext.isString(st)) { me.sortType = Ext.data.SortTypes[st]; } else if(Ext.isEmpty(st)) { me.sortType = me.type.sortType; } if (!config.hasOwnProperty('convert')) { me.convert = me.type.convert; } else if (!me.convert && me.type.convert && !config.hasOwnProperty('defaultValue')) { me.defaultValue = me.type.convert(me.defaultValue); } if (config.convert) { me.hasCustomConvert = true; } }, dateFormat: null, dateReadFormat: null, dateWriteFormat: null, useNull: false, defaultValue: "", mapping: null, sortType : null, sortDir : "ASC", allowBlank : true, persist: true }); Ext.define('Ext.data.Errors', { extend: Ext.util.MixedCollection , isValid: function() { return this.length === 0; }, getByField: function(fieldName) { var errors = [], error, i; for (i = 0; i < this.length; i++) { error = this.items[i]; if (error.field == fieldName) { errors.push(error); } } return errors; } }); Ext.define('Ext.data.validations', { singleton: true, presenceMessage: 'must be present', lengthMessage: 'is the wrong length', formatMessage: 'is the wrong format', inclusionMessage: 'is not included in the list of acceptable values', exclusionMessage: 'is not an acceptable value', emailMessage: 'is not a valid email address', emailRe: /^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/, presence: function(config, value) { if (arguments.length === 1) { value = config; } return !!value || value === 0 || value === false; }, length: function(config, value) { if (value === undefined || value === null) { return false; } var length = value.length, min = config.min, max = config.max; if ((min && length < min) || (max && length > max)) { return false; } else { return true; } }, email: function(config, email) { return Ext.data.validations.emailRe.test(email); }, format: function(config, value) { return !!(config.matcher && config.matcher.test(value)); }, inclusion: function(config, value) { return config.list && Ext.Array.indexOf(config.list,value) != -1; }, exclusion: function(config, value) { return config.list && Ext.Array.indexOf(config.list,value) == -1; } }); Ext.define('Ext.data.Model', { alternateClassName: 'Ext.data.Record', mixins: { observable: Ext.util.Observable }, compareConvertFields: function(f1, f2) { var f1SpecialConvert = f1.convert && f1.type && f1.convert !== f1.type.convert, f2SpecialConvert = f2.convert && f2.type && f2.convert !== f2.type.convert; if (f1SpecialConvert && !f2SpecialConvert) { return 1; } if (!f1SpecialConvert && f2SpecialConvert) { return -1; } return 0; }, itemNameFn: function(item) { return item.name; }, onClassExtended: function(cls, data, hooks) { var onBeforeClassCreated = hooks.onBeforeCreated; hooks.onBeforeCreated = function(cls, data) { var me = this, name = Ext.getClassName(cls), prototype = cls.prototype, superCls = cls.prototype.superclass, validations = data.validations || [], fields = data.fields || [], field, associationsConfigs = data.associations || [], addAssociations = function(items, type) { var i = 0, len, item; if (items) { items = Ext.Array.from(items); for (len = items.length; i < len; ++i) { item = items[i]; if (!Ext.isObject(item)) { item = {model: item}; } item.type = type; associationsConfigs.push(item); } } }, idgen = data.idgen, fieldsMixedCollection = new Ext.util.MixedCollection(false, prototype.itemNameFn), associationsMixedCollection = new Ext.util.MixedCollection(false, prototype.itemNameFn), superValidations = superCls.validations, superFields = superCls.fields, superAssociations = superCls.associations, associationConfig, i, ln, dependencies = [], idProperty = 'idProperty' in data ? data.idProperty : prototype.idProperty, idField = idProperty ? (idProperty.isField ? idProperty : new Ext.data.Field(idProperty)) : null, idFieldDefined = false, onFieldAddReplace = function(arg0, arg1, arg2) { var newField, pos; if (fieldsMixedCollection.events.add.firing) { pos = arg0; newField = arg1; } else { newField = arg2; pos = arg1.originalIndex; } newField.originalIndex = pos; if (idField && ((newField.mapping && (newField.mapping === idField.mapping)) || (newField.name === idField.name))) { prototype.idField = newField; idFieldDefined = true; newField.defaultValue = undefined; } }, clsProxy = data.proxy, fieldConvertSortFn = function() { fieldsMixedCollection.sortBy(prototype.compareConvertFields); }; cls.modelName = name; prototype.modelName = name; if (superValidations) { validations = superValidations.concat(validations); } data.validations = validations; if (superFields) { fields = superFields.items.concat(fields); } fieldsMixedCollection.on({ add: onFieldAddReplace, replace: onFieldAddReplace }); for (i = 0, ln = fields.length; i < ln; ++i) { field = fields[i]; fieldsMixedCollection.add(field.isField ? field : new Ext.data.Field(field)); } if (idField && !idFieldDefined) { prototype.idField = idField; idField.defaultValue = undefined; fieldsMixedCollection.add(idField); } fieldConvertSortFn(); fieldsMixedCollection.on({ add: fieldConvertSortFn, replace: fieldConvertSortFn }); data.fields = fieldsMixedCollection; if (idgen) { data.idgen = Ext.data.IdGenerator.get(idgen); } addAssociations(data.belongsTo, 'belongsTo'); delete data.belongsTo; addAssociations(data.hasMany, 'hasMany'); delete data.hasMany; addAssociations(data.hasOne, 'hasOne'); delete data.hasOne; if (superAssociations) { associationsConfigs = superAssociations.items.concat(associationsConfigs); } for (i = 0, ln = associationsConfigs.length; i < ln; ++i) { dependencies.push('association.' + associationsConfigs[i].type.toLowerCase()); } if (clsProxy) { if (!clsProxy.isProxy) { dependencies.push('proxy.' + (clsProxy.type || clsProxy)); } } else if (!cls.prototype.proxy) { cls.prototype.proxy = cls.prototype.defaultProxyType; dependencies.push('proxy.' + cls.prototype.defaultProxyType); } Ext.require(dependencies, function() { Ext.ModelManager.registerType(name, cls); for (i = 0, ln = associationsConfigs.length; i < ln; ++i) { associationConfig = associationsConfigs[i]; if (associationConfig.isAssociation) { associationConfig = Ext.applyIf({ ownerModel: name, associatedModel: associationConfig.model }, associationConfig.initialConfig); } else { Ext.apply(associationConfig, { ownerModel: name, associatedModel: associationConfig.model }); } if (Ext.ModelManager.getModel(associationConfig.model) === undefined) { Ext.ModelManager.registerDeferredAssociation(associationConfig); } else { associationsMixedCollection.add(Ext.data.association.Association.create(associationConfig)); } } data.associations = associationsMixedCollection; onBeforeClassCreated.call(me, cls, data, hooks); if (clsProxy && clsProxy.isProxy) { cls.setProxy(clsProxy); } Ext.ModelManager.onModelDefined(cls); }); }; }, inheritableStatics: { setProxy: function(proxy) { if (!proxy.isProxy) { if (typeof proxy == "string") { proxy = { type: proxy }; } proxy = Ext.createByAlias("proxy." + proxy.type, proxy); } proxy.setModel(this); this.proxy = this.prototype.proxy = proxy; return proxy; }, getProxy: function() { var proxy = this.proxy; if (!proxy) { proxy = this.prototype.proxy; if (proxy.isProxy) { proxy = proxy.clone() } return this.setProxy(proxy); } return proxy; }, setFields: function(fields, idProperty, clientIdProperty) { var me = this, newField, idField, idFieldDefined = false, proto = me.prototype, prototypeFields = proto.fields, superFields = proto.superclass.fields, len, i; if (idProperty) { proto.idProperty = idProperty; idField = idProperty.isField ? idProperty : new Ext.data.Field(idProperty); } if (clientIdProperty) { proto.clientIdProperty = clientIdProperty; } if (prototypeFields) { prototypeFields.clear(); } else { prototypeFields = me.prototype.fields = new Ext.util.MixedCollection(false, function(field) { return field.name; }); } if (superFields) { fields = superFields.items.concat(fields); } for (i = 0, len = fields.length; i < len; i++) { newField = new Ext.data.Field(fields[i]); if (idField && ((newField.mapping && (newField.mapping === idField.mapping)) || (newField.name === idField.name))) { idFieldDefined = true; newField.defaultValue = undefined; } prototypeFields.add(newField); } if (idField && !idFieldDefined) { idField.defaultValue = undefined; prototypeFields.add(idField); } me.fields = prototypeFields; return prototypeFields; }, getFields: function() { return this.prototype.fields.items; }, load: function(id, config) { config = Ext.apply({}, config); config = Ext.applyIf(config, { action: 'read', id : id }); var operation = new Ext.data.Operation(config), scope = config.scope || this, callback; callback = function(operation) { var record = null, success = operation.wasSuccessful(); if (success) { record = operation.getRecords()[0]; if (!record.hasId()) { record.setId(id); } Ext.callback(config.success, scope, [record, operation]); } else { Ext.callback(config.failure, scope, [record, operation]); } Ext.callback(config.callback, scope, [record, operation, success]); }; this.getProxy().read(operation, callback, this); } }, statics: { PREFIX : 'ext-record', AUTO_ID: 1, EDIT : 'edit', REJECT : 'reject', COMMIT : 'commit', id: function(rec) { var id = [this.PREFIX, '-', this.AUTO_ID++].join(''); rec.phantom = true; rec.internalId = id; return id; } }, idgen: { isGenerator: true, type: 'default', generate: function () { return null; }, getRecId: function (rec) { return rec.modelName + '-' + rec.internalId; } }, editing : false, dirty : false, persistenceProperty: 'data', evented: false, isModel: true, phantom : false, idProperty: 'id', clientIdProperty: null, defaultProxyType: 'ajax', emptyData: [], constructor: function(data, id, raw, convertedData) { var me = this, passedId = (id || id === 0), hasId, fields, length, field, name, value, newId, persistenceProperty, idProperty = me.idProperty, idField = me.idField, i; me.raw = raw || data; me.modified = {}; persistenceProperty = me[me.persistenceProperty] = convertedData || {}; me.data = me[me.persistenceProperty]; me.mixins.observable.constructor.call(me); if (!convertedData) { if (data) { if (!passedId && idProperty) { id = data[idProperty]; hasId = (id || id === 0); } } else { data = me.emptyData; } fields = me.fields.items; length = fields.length; i = 0; if (Ext.isArray(data)) { for (; i < length; i++) { field = fields[i]; name = field.name; value = data[field.originalIndex]; if (value === undefined) { value = field.defaultValue; } if (field.convert) { value = field.convert(value, me); } if (value !== undefined) { persistenceProperty[name] = value; } } } else { for (; i < length; i++) { field = fields[i]; name = field.name; value = data[name]; if (value === undefined) { value = field.defaultValue; } if (field.convert) { value = field.convert(value, me); } if (value !== undefined) { persistenceProperty[name] = value; } } } } me.stores = []; if (passedId) { hasId = true; persistenceProperty[idProperty] = idField && idField.convert ? idField.convert(id) : id; } else if (!hasId) { newId = me.idgen.generate(); if (newId != null) { me.preventInternalUpdate = true; me.setId(newId); delete me.preventInternalUpdate; } } me.internalId = hasId ? id : Ext.data.Model.id(me); if (typeof me.init == 'function') { me.init(); } me.id = me.idgen.getRecId(me); }, get: function(field) { return this[this.persistenceProperty][field]; }, _singleProp: {}, set: function (fieldName, newValue) { var me = this, data = me[me.persistenceProperty], fields = me.fields, modified = me.modified, single = (typeof fieldName == 'string'), currentValue, field, idChanged, key, modifiedFieldNames, name, oldId, newId, value, values; if (single) { values = me._singleProp; values[fieldName] = newValue; } else { values = fieldName; } for (name in values) { if (values.hasOwnProperty(name)) { value = values[name]; if (fields && (field = fields.get(name)) && field.convert) { value = field.convert(value, me); } currentValue = data[name]; if (me.isEqual(currentValue, value)) { continue; } data[name] = value; (modifiedFieldNames || (modifiedFieldNames = [])).push(name); if (field && field.persist) { if (modified.hasOwnProperty(name)) { if (me.isEqual(modified[name], value)) { delete modified[name]; me.dirty = false; for (key in modified) { if (modified.hasOwnProperty(key)){ me.dirty = true; break; } } } } else { me.dirty = true; modified[name] = currentValue; } } if (name == me.idProperty) { idChanged = true; oldId = currentValue; newId = value; } } } if (single) { delete values[fieldName]; } if (idChanged) { me.changeId(oldId, newId); } if (!me.editing && modifiedFieldNames) { me.afterEdit(modifiedFieldNames); } return modifiedFieldNames || null; }, copyFrom: function(sourceRecord) { var me = this, fields = me.fields.items, fieldCount = fields.length, modifiedFieldNames = [], field, i = 0, myData, sourceData, idProperty = me.idProperty, name, value; if (sourceRecord) { myData = me[me.persistenceProperty]; sourceData = sourceRecord[sourceRecord.persistenceProperty]; for (; i < fieldCount; i++) { field = fields[i]; name = field.name; if (name != idProperty) { value = sourceData[name]; if (value !== undefined && !me.isEqual(myData[name], value)) { myData[name] = value; modifiedFieldNames.push(name); } } } if (me.phantom && !sourceRecord.phantom) { me.beginEdit(); me.setId(sourceRecord.getId()); me.endEdit(true); me.commit(true); } } return modifiedFieldNames; }, isEqual: function(a, b) { if (a instanceof Date && b instanceof Date) { return a.getTime() === b.getTime(); } return a === b; }, beginEdit : function(){ var me = this, key, data, o; if (!me.editing) { me.editing = true; me.dirtySave = me.dirty; o = me[me.persistenceProperty]; data = me.dataSave = {}; for (key in o) { if (o.hasOwnProperty(key)) { data[key] = o[key]; } } o = me.modified; data = me.modifiedSave = {}; for (key in o) { if (o.hasOwnProperty(key)) { data[key] = o[key]; } } } }, cancelEdit : function(){ var me = this; if (me.editing) { me.editing = false; me.modified = me.modifiedSave; me[me.persistenceProperty] = me.dataSave; me.dirty = me.dirtySave; me.modifiedSave = me.dataSave = me.dirtySave = null; } }, endEdit : function(silent, modifiedFieldNames){ var me = this, dataSave, changed; silent = silent === true; if (me.editing) { me.editing = false; dataSave = me.dataSave; me.modifiedSave = me.dataSave = me.dirtySave = null; if (!silent) { if (!modifiedFieldNames) { modifiedFieldNames = me.getModifiedFieldNames(dataSave); } changed = me.dirty || modifiedFieldNames.length > 0; if (changed) { me.afterEdit(modifiedFieldNames); } } } }, getModifiedFieldNames: function(saved){ var me = this, data = me[me.persistenceProperty], modified = [], key; saved = saved || me.dataSave; for (key in data) { if (data.hasOwnProperty(key)) { if (!me.isEqual(data[key], saved[key])) { modified.push(key); } } } return modified; }, getChanges : function(){ var modified = this.modified, changes = {}, field; for (field in modified) { if (modified.hasOwnProperty(field)){ changes[field] = this.get(field); } } return changes; }, isModified : function(fieldName) { return this.modified.hasOwnProperty(fieldName); }, setDirty : function() { var me = this, fields = me.fields.items, fLen = fields.length, field, name, f; me.dirty = true; for (f = 0; f < fLen; f++) { field = fields[f]; if (field.persist) { name = field.name; me.modified[name] = me.get(name); } } }, reject : function(silent) { var me = this, modified = me.modified, field; for (field in modified) { if (modified.hasOwnProperty(field)) { if (typeof modified[field] != "function") { me[me.persistenceProperty][field] = modified[field]; } } } me.dirty = false; me.editing = false; me.modified = {}; if (silent !== true) { me.afterReject(); } }, commit : function(silent, modifiedFieldNames) { var me = this; me.phantom = me.dirty = me.editing = false; me.modified = {}; if (silent !== true) { me.afterCommit(modifiedFieldNames); } }, copy : function(newId) { var me = this; return new me.self(me.raw, newId, null, Ext.apply({}, me[me.persistenceProperty])); }, setProxy: function(proxy) { if (!proxy.isProxy) { if (typeof proxy === "string") { proxy = { type: proxy }; } proxy = Ext.createByAlias("proxy." + proxy.type, proxy); } proxy.setModel(this.self); this.proxy = proxy; return proxy; }, getProxy: function() { return this.hasOwnProperty('proxy') ? this.proxy : this.self.getProxy(); }, validate: function() { var errors = new Ext.data.Errors(), validations = this.validations, validators = Ext.data.validations, length, validation, field, valid, type, i; if (validations) { length = validations.length; for (i = 0; i < length; i++) { validation = validations[i]; field = validation.field || validation.name; type = validation.type; valid = validators[type](validation, this.get(field)); if (!valid) { errors.add({ field : field, message: validation.message || validators[type + 'Message'] }); } } } return errors; }, isValid: function(){ return this.validate().isValid(); }, save: function(options) { options = Ext.apply({}, options); var me = this, action = me.phantom ? 'create' : 'update', scope = options.scope || me, stores = me.stores, i = 0, storeCount, store, operation, callback; Ext.apply(options, { records: [me], action : action }); operation = new Ext.data.Operation(options); callback = function(operation) { var success = operation.wasSuccessful(); if (success) { for(storeCount = stores.length; i < storeCount; i++) { store = stores[i]; store.fireEvent('write', store, operation); store.fireEvent('datachanged', store); } Ext.callback(options.success, scope, [me, operation]); } else { Ext.callback(options.failure, scope, [me, operation]); } Ext.callback(options.callback, scope, [me, operation, success]); }; me.getProxy()[action](operation, callback, me); return me; }, destroy: function(options) { options = Ext.apply({ records: [this], action : 'destroy' }, options); var me = this, isNotPhantom = me.phantom !== true, scope = options.scope || me, stores, i = 0, storeCount, store, args, operation, callback; operation = new Ext.data.Operation(options); callback = function(operation) { args = [me, operation]; stores = Ext.Array.clone(me.stores); if (operation.wasSuccessful()) { for (storeCount = stores.length; i < storeCount; i++) { store = stores[i]; if (store.remove) { store.remove(me, true); } else { store.fireEvent('bulkremove', store, [me], [store.indexOf(me)], false); } if (isNotPhantom) { store.fireEvent('write', store, operation); } } me.clearListeners(); Ext.callback(options.success, scope, args); } else { Ext.callback(options.failure, scope, args); } Ext.callback(options.callback, scope, args); }; if (isNotPhantom) { me.getProxy().destroy(operation, callback, me); } else { operation.complete = operation.success = true; operation.resultSet = me.getProxy().reader.nullResultSet; callback(operation); } return me; }, getId: function() { return this.get(this.idField.name); }, getObservableId: function() { return this.id; }, setId: function(id) { this.set(this.idProperty, id); }, changeId: function(oldId, newId) { var me = this, hasOldId, hasId, oldInternalId; if (!me.preventInternalUpdate) { hasOldId = me.hasId(oldId); hasId = me.hasId(newId); oldInternalId = me.internalId; me.phantom = !hasId; if (hasId !== hasOldId || (hasId && hasOldId)) { me.internalId = hasId ? newId : Ext.data.Model.id(me); } me.fireEvent('idchanged', me, oldId, newId, oldInternalId); me.callStore('onIdChanged', oldId, newId, oldInternalId); } }, hasId: function(id) { if (arguments.length === 0) { id = this.getId(); } return !!(id || id === 0); }, join : function(store) { var me = this; if (!me.stores.length) { me.stores[0] = store; } else { Ext.Array.include(this.stores, store); } this.store = this.stores[0]; }, unjoin: function(store) { Ext.Array.remove(this.stores, store); this.store = this.stores[0] || null; }, afterEdit : function(modifiedFieldNames) { this.callStore('afterEdit', modifiedFieldNames); }, afterReject : function() { this.callStore('afterReject'); }, afterCommit: function(modifiedFieldNames) { this.callStore('afterCommit', modifiedFieldNames); }, callStore: function(fn) { var args = Ext.Array.clone(arguments), stores = this.stores, i = 0, len = stores.length, store; args[0] = this; for (; i < len; ++i) { store = stores[i]; if (store && Ext.isFunction(store[fn])) { store[fn].apply(store, args); } } }, getData: function(includeAssociated){ var me = this, fields = me.fields.items, fLen = fields.length, data = {}, name, f; for (f = 0; f < fLen; f++) { name = fields[f].name; data[name] = me.get(name); } if (includeAssociated === true) { Ext.apply(data, me.getAssociatedData()); } return data; }, getAssociatedData: function(){ return this.prepareAssociatedData({}, 1); }, prepareAssociatedData: function(seenKeys, depth) { var me = this, associations = me.associations.items, associationCount = associations.length, associationData = {}, toRead = [], toReadKey = [], toReadIndex = [], associatedStore, associatedRecords, associatedRecord, o, index, result, seenDepth, associationId, associatedRecordCount, association, i, j, type, name; for (i = 0; i < associationCount; i++) { association = associations[i]; associationId = association.associationId; seenDepth = seenKeys[associationId]; if (seenDepth && seenDepth !== depth) { continue; } seenKeys[associationId] = depth; type = association.type; name = association.name; if (type == 'hasMany') { associatedStore = me[association.storeName]; associationData[name] = []; if (associatedStore && associatedStore.getCount() > 0) { associatedRecords = associatedStore.data.items; associatedRecordCount = associatedRecords.length; for (j = 0; j < associatedRecordCount; j++) { associatedRecord = associatedRecords[j]; associationData[name][j] = associatedRecord.getData(); toRead.push(associatedRecord); toReadKey.push(name); toReadIndex.push(j); } } } else if (type == 'belongsTo' || type == 'hasOne') { associatedRecord = me[association.instanceName]; if (associatedRecord !== undefined) { associationData[name] = associatedRecord.getData(); toRead.push(associatedRecord); toReadKey.push(name); toReadIndex.push(-1); } } } for (i = 0, associatedRecordCount = toRead.length; i < associatedRecordCount; ++i) { associatedRecord = toRead[i]; o = associationData[toReadKey[i]]; index = toReadIndex[i]; result = associatedRecord.prepareAssociatedData(seenKeys, depth + 1); if (index === -1) { Ext.apply(o, result); } else { Ext.apply(o[index], result); } } return associationData; } }); Ext.define('Ext.data.proxy.Server', { extend: Ext.data.proxy.Proxy , alias : 'proxy.server', alternateClassName: 'Ext.data.ServerProxy', pageParam: 'page', startParam: 'start', limitParam: 'limit', groupParam: 'group', groupDirectionParam: 'groupDir', sortParam: 'sort', filterParam: 'filter', directionParam: 'dir', idParam: 'id', simpleSortMode: false, simpleGroupMode: false, noCache : true, cacheString: "_dc", timeout : 30000, constructor: function(config) { var me = this; config = config || {}; me.callParent([config]); me.extraParams = config.extraParams || {}; me.api = Ext.apply({}, config.api || me.api); me.nocache = me.noCache; }, create: function() { return this.doRequest.apply(this, arguments); }, read: function() { return this.doRequest.apply(this, arguments); }, update: function() { return this.doRequest.apply(this, arguments); }, destroy: function() { return this.doRequest.apply(this, arguments); }, setExtraParam: function(name, value) { this.extraParams[name] = value; }, buildRequest: function(operation) { var me = this, params = operation.params = Ext.apply({}, operation.params, me.extraParams), request; Ext.applyIf(params, me.getParams(operation)); if (operation.id !== undefined && params[me.idParam] === undefined) { params[me.idParam] = operation.id; } request = new Ext.data.Request({ params : params, action : operation.action, records : operation.records, operation: operation, url : operation.url, proxy: me }); request.url = me.buildUrl(request); operation.request = request; return request; }, processResponse: function(success, operation, request, response, callback, scope) { var me = this, reader, result; if (success === true) { reader = me.getReader(); reader.applyDefaults = operation.action === 'read'; result = reader.read(me.extractResponseData(response)); if (result.success !== false) { Ext.apply(operation, { response: response, resultSet: result }); operation.commitRecords(result.records); operation.setCompleted(); operation.setSuccessful(); } else { operation.setException(result.message); me.fireEvent('exception', this, response, operation); } } else { me.setException(operation, response); me.fireEvent('exception', this, response, operation); } if (typeof callback == 'function') { callback.call(scope || me, operation); } me.afterRequest(request, success); }, setException: function(operation, response) { operation.setException({ status: response.status, statusText: response.statusText }); }, extractResponseData: Ext.identityFn, applyEncoding: function(value) { return Ext.encode(value); }, encodeSorters: function(sorters) { var min = [], length = sorters.length, i = 0; for (; i < length; i++) { min[i] = { property : sorters[i].property, direction: sorters[i].direction }; } return this.applyEncoding(min); }, encodeFilters: function(filters) { var min = [], length = filters.length, i = 0; for (; i < length; i++) { min[i] = { property: filters[i].property, value : filters[i].value }; } return this.applyEncoding(min); }, getParams: function(operation) { var me = this, params = {}, isDef = Ext.isDefined, groupers = operation.groupers, sorters = operation.sorters, filters = operation.filters, page = operation.page, start = operation.start, limit = operation.limit, simpleSortMode = me.simpleSortMode, simpleGroupMode = me.simpleGroupMode, pageParam = me.pageParam, startParam = me.startParam, limitParam = me.limitParam, groupParam = me.groupParam, groupDirectionParam = me.groupDirectionParam, sortParam = me.sortParam, filterParam = me.filterParam, directionParam = me.directionParam, hasGroups, index; if (pageParam && isDef(page)) { params[pageParam] = page; } if (startParam && isDef(start)) { params[startParam] = start; } if (limitParam && isDef(limit)) { params[limitParam] = limit; } hasGroups = groupParam && groupers && groupers.length > 0; if (hasGroups) { if (simpleGroupMode) { params[groupParam] = groupers[0].property; params[groupDirectionParam] = groupers[0].direction || 'ASC'; } else { params[groupParam] = me.encodeSorters(groupers); } } if (sortParam && sorters && sorters.length > 0) { if (simpleSortMode) { index = 0; if (sorters.length > 1 && hasGroups) { index = 1; } params[sortParam] = sorters[index].property; params[directionParam] = sorters[index].direction; } else { params[sortParam] = me.encodeSorters(sorters); } } if (filterParam && filters && filters.length > 0) { params[filterParam] = me.encodeFilters(filters); } return params; }, buildUrl: function(request) { var me = this, url = me.getUrl(request); if (me.noCache) { url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.cacheString, Ext.Date.now())); } return url; }, getUrl: function(request) { return request.url || this.api[request.action] || this.url; }, doRequest: function(operation, callback, scope) { }, afterRequest: Ext.emptyFn, onDestroy: function() { Ext.destroy(this.reader, this.writer); } }); Ext.define('Ext.data.proxy.Ajax', { extend: Ext.data.proxy.Server , alias: 'proxy.ajax', alternateClassName: ['Ext.data.HttpProxy', 'Ext.data.AjaxProxy'], actionMethods: { create : 'POST', read : 'GET', update : 'POST', destroy: 'POST' }, defaultActionMethods: { create : 'POST', read : 'GET', update : 'POST', destroy: 'POST' }, binary: false, paramsAsJson: false, doRequest: function(operation, callback, scope) { var me = this, writer = me.getWriter(), request = me.buildRequest(operation), method = me.getMethod(request); if (operation.allowWrite()) { request = writer.write(request); } Ext.apply(request, { binary : me.binary, headers : me.headers, timeout : me.timeout, scope : me, callback : me.createRequestCallback(request, operation, callback, scope), method : method, disableCaching: false }); if (method.toUpperCase() !== 'GET' && me.paramsAsJson) { request = Ext.apply({ jsonData: request.params }, request); delete request.params; } Ext.Ajax.request(request); return request; }, getMethod: function(request) { var actions = this.actionMethods, action = request.action, method; if (actions) { method = actions[action]; } return method || this.defaultActionMethods[action]; }, createRequestCallback: function(request, operation, callback, scope) { var me = this; return function(options, success, response) { me.processResponse(success, operation, request, response, callback, scope); }; } }); Ext.define('Ext.data.proxy.Client', { extend: Ext.data.proxy.Proxy , alternateClassName: 'Ext.data.ClientProxy', isSynchronous: true, clear: function() { } }); Ext.define('Ext.data.proxy.Memory', { extend: Ext.data.proxy.Client , alias: 'proxy.memory', alternateClassName: 'Ext.data.MemoryProxy', constructor: function(config) { this.callParent([config]); this.setReader(this.reader); }, updateOperation: function(operation, callback, scope) { var i = 0, recs = operation.getRecords(), len = recs.length; for (i; i < len; i++) { recs[i].commit(); } operation.setCompleted(); operation.setSuccessful(); Ext.callback(callback, scope || this, [operation]); }, create: function() { this.updateOperation.apply(this, arguments); }, update: function() { this.updateOperation.apply(this, arguments); }, destroy: function() { this.updateOperation.apply(this, arguments); }, read: function(operation, callback, scope) { var me = this, resultSet = operation.resultSet = me.getReader().read(me.data), records = resultSet.records, sorters = operation.sorters, groupers = operation.groupers, filters = operation.filters; operation.setCompleted(); if (resultSet.success) { if (filters && filters.length) { records = resultSet.records = Ext.Array.filter(records, Ext.util.Filter.createFilterFn(filters)); resultSet.total = records.length; } if (groupers && groupers.length) { sorters = sorters ? sorters.concat(groupers) : sorters; } if (sorters && sorters.length) { resultSet.records = Ext.Array.sort(records, Ext.util.Sortable.createComparator(sorters)); } if (me.enablePaging && operation.start !== undefined && operation.limit !== undefined) { if (operation.start >= resultSet.total) { resultSet.success = false; resultSet.count = 0; resultSet.records = []; } else { resultSet.records = Ext.Array.slice(resultSet.records, operation.start, operation.start + operation.limit); resultSet.count = resultSet.records.length; } } } if (resultSet.success) { operation.setSuccessful(); } else { me.fireEvent('exception', me, null, operation); } Ext.callback(callback, scope || me, [operation]); }, clear: Ext.emptyFn }); Ext.define('Ext.util.LruCache', { extend: Ext.util.HashMap , constructor: function(config) { Ext.apply(this, config); this.callParent([config]); }, add: function(key, newValue) { var me = this, existingKey = me.findKey(newValue), entry; if (existingKey) { me.unlinkEntry(entry = me.map[existingKey]); entry.prev = me.last; entry.next = null; } else { entry = { prev: me.last, next: null, key: key, value: newValue }; } if (me.last) { me.last.next = entry; } else { me.first = entry; } me.last = entry; me.callParent([key, entry]); me.prune(); return newValue; }, insertBefore: function(key, newValue, sibling) { var me = this, existingKey, entry; if (sibling = this.map[this.findKey(sibling)]) { existingKey = me.findKey(newValue); if (existingKey) { me.unlinkEntry(entry = me.map[existingKey]); } else { entry = { prev: sibling.prev, next: sibling, key: key, value: newValue }; } if (sibling.prev) { entry.prev.next = entry; } else { me.first = entry; } entry.next = sibling; sibling.prev = entry; me.prune(); return newValue; } else { return me.add(key, newValue); } }, get: function(key) { var entry = this.map[key]; if (entry) { if (entry.next) { this.moveToEnd(entry); } return entry.value; } }, removeAtKey: function(key) { this.unlinkEntry(this.map[key]); return this.callParent(arguments); }, clear: function( initial) { this.first = this.last = null; return this.callParent(arguments); }, unlinkEntry: function(entry) { if (entry) { if (entry.next) { entry.next.prev = entry.prev; } else { this.last = entry.prev; } if (entry.prev) { entry.prev.next = entry.next; } else { this.first = entry.next; } entry.prev = entry.next = null; } }, moveToEnd: function(entry) { this.unlinkEntry(entry); if (entry.prev = this.last) { this.last.next = entry; } else { this.first = entry; } this.last = entry; }, getArray: function(isKey) { var arr = [], entry = this.first; while (entry) { arr.push(isKey ? entry.key: entry.value); entry = entry.next; } return arr; }, each: function(fn, scope, reverse) { var me = this, entry = reverse ? me.last : me.first, length = me.length; scope = scope || me; while (entry) { if (fn.call(scope, entry.key, entry.value, length) === false) { break; } entry = reverse ? entry.prev : entry.next; } return me; }, findKey: function(value) { var key, map = this.map; for (key in map) { if (map.hasOwnProperty(key) && map[key].value === value) { return key; } } return undefined; }, clone: function() { var newCache = new this.self(this.initialConfig), map = this.map, key; newCache.suspendEvents(); for (key in map) { if (map.hasOwnProperty(key)) { newCache.add(key, map[key].value); } } newCache.resumeEvents(); return newCache; }, prune: function() { var me = this, purgeCount = me.maxSize ? (me.length - me.maxSize) : 0; if (purgeCount > 0) { for (; me.first && purgeCount; purgeCount--) { me.removeAtKey(me.first.key); } } } }); Ext.define('Ext.data.PageMap', { extend: Ext.util.LruCache , clear: function(initial) { var me = this; me.pageMapGeneration = (me.pageMapGeneration || 0) + 1; me.callParent(arguments); }, forEach: function(fn, scope) { var me = this, pageNumbers = Ext.Object.getKeys(me.map), pageCount = pageNumbers.length, i, j, pageNumber, page, pageSize; for (i = 0; i < pageCount; i++) { pageNumbers[i] = Number(pageNumbers[i]); } Ext.Array.sort(pageNumbers); scope = scope || me; for (i = 0; i < pageCount; i++) { pageNumber = pageNumbers[i]; page = me.getPage(pageNumber); pageSize = page.length; for (j = 0; j < pageSize; j++) { if (fn.call(scope, page[j], (pageNumber - 1) * me.pageSize + j) === false) { return; } } } }, findBy: function(fn, scope) { var me = this, result = null; scope = scope || me; me.forEach(function(rec, index) { if (fn.call(scope, rec, index)) { result = rec; return false; } }); return result; }, findIndexBy: function(fn, scope) { var me = this, result = -1; scope = scope || me; me.forEach(function(rec, index) { if (fn.call(scope, rec)) { result = index; return false; } }); return result; }, getPageFromRecordIndex: function() { return Ext.data.Store.prototype.getPageFromRecordIndex.apply(this, arguments); }, addAll: function(records) { this.addPage(1, records); }, addPage: function(pageNumber, records) { var me = this, lastPage = pageNumber + Math.floor((records.length - 1) / me.pageSize), startIdx, page; for (startIdx = 0; pageNumber <= lastPage; pageNumber++, startIdx += me.pageSize) { page = Ext.Array.slice(records, startIdx, startIdx + me.pageSize); me.add(pageNumber, page); me.fireEvent('pageAdded', pageNumber, page); } }, getCount: function() { var result = this.callParent(); if (result) { result = (result - 1) * this.pageSize + this.last.value.length; } return result; }, indexOf: function(record) { return record ? record.index : -1; }, insert: function() { }, remove: function() { }, removeAt: function() { }, getPage: function(pageNumber) { return this.get(pageNumber); }, hasRange: function(start, end) { var pageNumber = this.getPageFromRecordIndex(start), endPageNumber = this.getPageFromRecordIndex(end); for (; pageNumber <= endPageNumber; pageNumber++) { if (!this.hasPage(pageNumber)) { return false; } } return true; }, hasPage: function(pageNumber) { return !!this.get(pageNumber); }, getAt: function(index) { return this.getRange(index, index)[0]; }, getRange: function(start, end) { if (!this.hasRange(start, end)) { Ext.Error.raise('PageMap asked for range which it does not have'); } var me = this, startPageNumber = me.getPageFromRecordIndex(start), endPageNumber = me.getPageFromRecordIndex(end), dataStart = (startPageNumber - 1) * me.pageSize, dataEnd = (endPageNumber * me.pageSize) - 1, pageNumber = startPageNumber, result = [], sliceBegin, sliceEnd, doSlice, i = 0, len; for (; pageNumber <= endPageNumber; pageNumber++) { if (pageNumber == startPageNumber) { sliceBegin = start - dataStart; doSlice = true; } else { sliceBegin = 0; doSlice = false; } if (pageNumber == endPageNumber) { sliceEnd = me.pageSize - (dataEnd - end); doSlice = true; } if (doSlice) { Ext.Array.push(result, Ext.Array.slice(me.getPage(pageNumber), sliceBegin, sliceEnd)); } else { Ext.Array.push(result, me.getPage(pageNumber)); } } for (len = result.length; i < len; i++) { result[i].index = start++; } return result; } }); Ext.define('Ext.data.Group', { extend: Ext.util.Observable , key: undefined, dirty: true, constructor: function(){ this.callParent(arguments); this.records = []; }, contains: function(record){ return Ext.Array.indexOf(this.records, record) !== -1; }, add: function(records) { Ext.Array.push(this.records, records); this.dirty = true; }, remove: function(records) { if (!Ext.isArray(records)) { records = [records]; } var len = records.length, i; for (i = 0; i < len; ++i) { Ext.Array.remove(this.records, records[i]); } this.dirty = true; }, isDirty: function(){ return this.dirty; }, hasAggregate: function(){ return !!this.aggregate; }, setDirty: function(){ this.dirty = true; }, commit: function(){ this.dirty = false; }, isCollapsed: function(){ return this.collapsed; }, getAggregateRecord: function(forceNew){ var me = this, Model; if (forceNew === true || me.dirty || !me.aggregate) { Model = me.store.model; me.aggregate = new Model(); me.aggregate.isSummary = true; } return me.aggregate; } }); Ext.define('Ext.data.Store', { extend: Ext.data.AbstractStore , alias: 'store.store', remoteSort: false, remoteFilter: false, remoteGroup : false, groupField: undefined, groupDir: "ASC", trailingBufferZone: 25, leadingBufferZone: 200, pageSize: undefined, currentPage: 1, clearOnPageLoad: true, loading: false, sortOnFilter: true, buffered: false, purgePageCount: 5, clearRemovedOnLoad: true, defaultPageSize: 25, defaultViewSize: 100, addRecordsOptions: { addRecords: true }, statics: { recordIdFn: function(record) { return record.internalId; }, recordIndexFn: function(record) { return record.index; }, grouperIdFn: function(grouper) { return grouper.id || grouper.property; }, groupIdFn: function(group) { return group.key; } }, constructor: function(config) { config = Ext.apply({}, config); var me = this, groupers = config.groupers || me.groupers, groupField = config.groupField || me.groupField, proxy, data; data = config.data || me.data; if (data) { me.inlineData = data; delete config.data; } if (!groupers && groupField) { groupers = [{ property : groupField, direction: config.groupDir || me.groupDir }]; if (config.getGroupString || (me.getGroupString !== Ext.data.Store.prototype.getGroupString)) { groupers[0].getGroupString = function(record) { return me.getGroupString(record); } } } delete config.groupers; me.groupers = new Ext.util.MixedCollection(false, Ext.data.Store.grouperIdFn); me.groupers.addAll(me.decodeGroupers(groupers)); me.groups = new Ext.util.MixedCollection(false, Ext.data.Store.groupIdFn); me.callParent([config]); if (me.buffered) { me.data = new Ext.data.PageMap({ store: me, keyFn: Ext.data.Store.recordIdFn, pageSize: me.pageSize, maxSize: me.purgePageCount, listeners: { clear: me.onPageMapClear, scope: me } }); me.pageRequests = {}; me.remoteSort = me.remoteGroup = me.remoteFilter = true; me.sortOnLoad = false; me.filterOnLoad = false; } else { me.data = new Ext.util.MixedCollection({ getKey: Ext.data.Store.recordIdFn, maintainIndices: true }); } if (me.remoteGroup) { me.remoteSort = true; } me.sorters.insert(0, me.groupers.getRange()); proxy = me.proxy; data = me.inlineData; if (!me.buffered && !me.pageSize) { me.pageSize = me.defaultPageSize; } if (data) { if (proxy instanceof Ext.data.proxy.Memory) { proxy.data = data; me.read(); } else { me.add.apply(me, [data]); } if (me.sorters.items.length && !me.remoteSort) { me.group(null, null, true); } delete me.inlineData; } else if (me.autoLoad) { Ext.defer(me.load, 1, me, [ typeof me.autoLoad === 'object' ? me.autoLoad : undefined ]); } }, onBeforeSort: function() { var groupers = this.groupers; if (groupers.getCount() > 0) { this.sort(groupers.items, 'prepend', false); } }, decodeGroupers: function(groupers) { if (!Ext.isArray(groupers)) { if (groupers === undefined) { groupers = []; } else { groupers = [groupers]; } } var length = groupers.length, Grouper = Ext.util.Grouper, config, i, result = []; for (i = 0; i < length; i++) { config = groupers[i]; if (!(config instanceof Grouper)) { if (Ext.isString(config)) { config = { property: config }; } config = Ext.apply({ root : 'data', direction: "ASC" }, config); if (config.fn) { config.sorterFn = config.fn; } if (typeof config == 'function') { config = { sorterFn: config }; } result.push(new Grouper(config)); } else { result.push(config); } } return result; }, group: function(groupers, direction, suppressEvent) { var me = this, grouper, newGroupers; if (groupers) { me.sorters.removeAll(me.groupers.items); if (Ext.isArray(groupers)) { newGroupers = groupers; } else if (Ext.isObject(groupers)) { newGroupers = [groupers]; } else if (Ext.isString(groupers)) { grouper = me.groupers.get(groupers); if (!grouper) { grouper = { property : groupers, direction: direction || 'ASC' }; newGroupers = [grouper]; } else if (direction === undefined) { grouper.toggle(); } else { grouper.setDirection(direction); } } if (newGroupers && newGroupers.length) { me.groupers.clear(); me.groupers.addAll(me.decodeGroupers(newGroupers)); } me.sorters.insert(0, me.groupers.items); } if (me.remoteGroup) { if (me.buffered) { me.data.clear(); me.loadPage(1, { groupChange: true }); } else { me.load({ scope: me, callback: suppressEvent ? null : me.fireGroupChange }); } } else { me.doSort(me.generateComparator()); me.constructGroups(); if (!suppressEvent) { me.fireGroupChange(); } } }, getGroupField: function(){ var first = this.groupers.first(), group; if (first) { group = first.property; } return group; }, constructGroups: function(){ var me = this, data = this.data.items, len = data.length, groups = me.groups, groupValue, i, group, rec; groups.clear(); if (me.isGrouped()) { for (i = 0; i < len; ++i) { rec = data[i]; groupValue = me.getGroupString(rec); group = groups.get(groupValue); if (!group) { group = new Ext.data.Group({ key: groupValue, store: me }); groups.add(group); } group.add(rec); } } }, clearGrouping: function() { var me = this, groupers = me.groupers.items, gLen = groupers.length, g; for (g = 0; g < gLen; g++) { me.sorters.remove(groupers[g]); } me.groupers.clear(); if (me.remoteGroup) { if (me.buffered) { me.data.clear(); me.loadPage(1, { groupChange: true }); } else { me.load({ scope: me, callback: me.fireGroupChange }); } } else { me.groups.clear(); if (me.sorters.length) { me.sort(); } else { me.fireEvent('datachanged', me); me.fireEvent('refresh', me); } me.fireGroupChange(); } }, isGrouped: function() { return this.groupers.getCount() > 0; }, fireGroupChange: function() { this.fireEvent('groupchange', this, this.groupers); }, getGroups: function(requestGroupString) { var records = this.data.items, length = records.length, groups = [], pointers = {}, record, groupStr, group, i; for (i = 0; i < length; i++) { record = records[i]; groupStr = this.getGroupString(record); group = pointers[groupStr]; if (group === undefined) { group = { name: groupStr, children: [] }; groups.push(group); pointers[groupStr] = group; } group.children.push(record); } return requestGroupString ? pointers[requestGroupString] : groups; }, getGroupsForGrouper: function(records, grouper) { var length = records.length, groups = [], oldValue, newValue, record, group, i; for (i = 0; i < length; i++) { record = records[i]; newValue = grouper.getGroupString(record); if (newValue !== oldValue) { group = { name: newValue, grouper: grouper, records: [] }; groups.push(group); } group.records.push(record); oldValue = newValue; } return groups; }, getGroupsForGrouperIndex: function(records, grouperIndex) { var me = this, groupers = me.groupers, grouper = groupers.getAt(grouperIndex), groups = me.getGroupsForGrouper(records, grouper), length = groups.length, i; if (grouperIndex + 1 < groupers.length) { for (i = 0; i < length; i++) { groups[i].children = me.getGroupsForGrouperIndex(groups[i].records, grouperIndex + 1); } } for (i = 0; i < length; i++) { groups[i].depth = grouperIndex; } return groups; }, getGroupData: function(sort) { var me = this; if (sort !== false) { me.sort(); } return me.getGroupsForGrouperIndex(me.data.items, 0); }, getGroupString: function(instance) { var group = this.groupers.first(); if (group) { return group.getGroupString(instance); } return ''; }, insert: function(index, records) { var me = this, sync = false, i, len, record, defaults = me.modelDefaults, out; if (!Ext.isIterable(records)) { out = records = [records]; } else { out = []; } len = records.length; if (len) { for (i = 0; i < len; i++) { record = records[i]; if (!record.isModel) { record = me.createModel(record); } out[i] = record; if (defaults) { record.set(defaults); } record.join(me); sync = sync || record.phantom === true; } me.data.insert(index, out); if (me.snapshot) { me.snapshot.addAll(out); } if (me.requireSort) { me.suspendEvents(); me.sort(); me.resumeEvents(); } if (me.isGrouped()) { me.updateGroupsOnAdd(out); } me.fireEvent('add', me, out, index); me.fireEvent('datachanged', me); if (me.autoSync && sync && !me.autoSyncSuspended) { me.sync(); } } return out; }, updateGroupsOnAdd: function(records) { var me = this, groups = me.groups, len = records.length, i, groupName, group, rec; for (i = 0; i < len; ++i) { rec = records[i]; groupName = me.getGroupString(rec); group = groups.getByKey(groupName); if (!group) { group = groups.add(new Ext.data.Group({ key: groupName, store: me })); } group.add(rec); } }, updateGroupsOnRemove: function(records) { var me = this, groups = me.groups, len = records.length, i, groupName, group, rec; for (i = 0; i < len; ++i) { rec = records[i]; groupName = me.getGroupString(rec); group = groups.getByKey(groupName); if (group) { group.remove(rec); if (group.records.length === 0) { groups.remove(group); } } } }, updateGroupsOnUpdate: function(record, modifiedFieldNames){ var me = this, groupField = me.getGroupField(), groupName = me.getGroupString(record), groups = me.groups, len, i, items, group; if (modifiedFieldNames && Ext.Array.contains(modifiedFieldNames, groupField)) { if (me.buffered) { Ext.Error.raise({ msg: 'Cannot move records between groups in a buffered store record' }); } items = groups.items; for (i = 0, len = items.length; i < len; ++i) { group = items[i]; if (group.contains(record)) { group.remove(record); break; } } group = groups.getByKey(groupName); if (!group) { group = groups.add(new Ext.data.Group({ key: groupName, store: me })); } group.add(record); me.data.remove(record); me.data.insert(me.data.findInsertionIndex(record, me.generateComparator()), record); } else { groups.getByKey(groupName).setDirty(); } }, add: function(arg) { var me = this, records, length, isSorted; if (Ext.isArray(arg)) { records = arg; } else { records = arguments; } length = records.length; isSorted = !me.remoteSort && me.sorters && me.sorters.items.length; if (isSorted && length === 1) { return [ me.addSorted(me.createModel(records[0])) ]; } if (isSorted) { me.requireSort = true; } records = me.insert(me.data.length, records); delete me.requireSort; return records; }, addSorted: function(record) { var me = this, index = me.data.findInsertionIndex(record, me.generateComparator()); me.insert(index, record); return record; }, createModel: function(record) { if (!record.isModel) { record = Ext.ModelManager.create(record, this.model); } return record; }, onUpdate: function(record, type, modifiedFieldNames){ if (this.isGrouped()) { this.updateGroupsOnUpdate(record, modifiedFieldNames); } }, each: function(fn, scope) { var data = this.data.items, dLen = data.length, record, d; for (d = 0; d < dLen; d++) { record = data[d]; if (fn.call(scope || record, record, d, dLen) === false) { break; } } }, remove: function(records, isMove, silent) { isMove = isMove === true; var me = this, sync = false, snapshot = me.snapshot, data = me.data, i = 0, length, info = [], allRecords = [], indexes = [], item, isNotPhantom, index, record, removeRange, removeCount, fireRemoveEvent = !silent && me.hasListeners.remove; if (records.isModel) { records = [records]; length = 1; } else if (Ext.isIterable(records)) { length = records.length; } else if (typeof records === 'object') { removeRange = true; i = records.start; length = records.end + 1; removeCount = length - i; } if (!removeRange) { for (i = 0; i < length; ++i) { record = records[i]; if (typeof record == 'number') { index = record; record = data.getAt(index); } else { index = me.indexOf(record); } if (record && index > -1) { info.push({ record: record, index: index }); } if (snapshot) { snapshot.remove(record); } } info = Ext.Array.sort(info, function(o1, o2) { var index1 = o1.index, index2 = o2.index; return index1 === o2.index2 ? 0 : (index1 < index2 ? -1 : 1); }); i = 0; length = info.length; } if (!length) { return; } for (; i < length; i++) { if (removeRange) { record = data.getAt(i); index = i; } else { item = info[i]; record = item.record; index = item.index; } allRecords.push(record); indexes.push(index); isNotPhantom = record.phantom !== true; if (!isMove && isNotPhantom) { record.removedFrom = index; me.removed.push(record); } record.unjoin(me); index -= i; sync = sync || isNotPhantom; if (!removeRange) { data.removeAt(index); if (fireRemoveEvent) { me.fireEvent('remove', me, record, index, !!isMove); } } } if (removeRange) { data.removeRange(records.start, removeCount); } if (!silent) { me.fireEvent('bulkremove', me, allRecords, indexes, !!isMove); me.fireEvent('datachanged', me); } if (!isMove && me.autoSync && sync && !me.autoSyncSuspended) { me.sync(); } }, removeAt: function(index, count) { var me = this, storeCount = me.getCount(); if (index <= storeCount) { if (arguments.length === 1) { me.remove([ index ]); } else if (count) { me.remove({ start: index, end: Math.min(index + count, storeCount) - 1 }); } } }, removeAll: function(silent) { var me = this, snapshot = me.snapshot, data = me.data; if (snapshot) { snapshot.removeAll(data.getRange()); } if (me.buffered) { if (data) { if (silent) { me.suspendEvent('clear'); } data.clear(); if (silent) { me.resumeEvent('clear'); } } } else { me.remove({ start: 0, end: me.getCount() - 1 }, false, silent); if (silent !== true) { me.fireEvent('clear', me); } } }, load: function(options) { var me = this; if (typeof options == 'function') { options = { callback: options }; } else { options = Ext.apply({}, options); } if (me.remoteGroup && !options.groupers && me.groupers.items.length) { options.groupers = me.groupers.items; } options.page = options.page || me.currentPage; options.start = (options.start !== undefined) ? options.start : (options.page - 1) * me.pageSize; options.limit = options.limit || me.pageSize; options.addRecords = options.addRecords || false; if (me.buffered) { options.limit = me.viewSize || me.defaultViewSize; options.loadCallback = options.callback; delete options.callback; return me.loadToPrefetch(options); } return me.callParent([options]); }, reload: function(options) { var me = this, startIdx, endIdx, startPage, endPage, i, waitForReload, bufferZone, records; if (!options) { options = {}; } if (me.buffered) { delete me.totalCount; me.data.clear(true); waitForReload = function() { if (me.rangeCached(startIdx, endIdx)) { me.loading = false; me.data.un('pageAdded', waitForReload); records = me.data.getRange(startIdx, endIdx); me.fireEvent('load', me, records, true); } }; bufferZone = Math.ceil((me.leadingBufferZone + me.trailingBufferZone) / 2); if (!me.lastRequestStart) { startIdx = options.start || 0; endIdx = startIdx + (options.count || me.pageSize) - 1; } else { startIdx = me.lastRequestStart; endIdx = me.lastRequestEnd; } startPage = me.getPageFromRecordIndex(Math.max(startIdx - bufferZone, 0)); endPage = me.getPageFromRecordIndex(endIdx + bufferZone); if (me.fireEvent('beforeload', me, options) !== false) { me.loading = true; me.data.on('pageAdded', waitForReload); for (i = startPage; i <= endPage; i++) { me.prefetchPage(i, options); } } } else { return me.callParent(arguments); } }, onProxyLoad: function(operation) { var me = this, resultSet = operation.getResultSet(), records = operation.getRecords(), successful = operation.wasSuccessful(); if (me.isDestroyed) { return; } if (resultSet) { me.totalCount = resultSet.total; } me.loading = false; if (successful) { me.loadRecords(records, operation); } if (me.hasListeners.load) { me.fireEvent('load', me, records, successful); } if (me.hasListeners.read) { me.fireEvent('read', me, records, successful); } Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]); }, getNewRecords: function() { return (this.snapshot || this.data).filterBy(this.filterNew).items; }, getUpdatedRecords: function() { return (this.snapshot || this.data).filterBy(this.filterUpdated).items; }, filter: function(filters, value) { if (Ext.isString(filters)) { filters = { property: filters, value: value }; } var me = this, decoded = me.decodeFilters(filters), i, doLocalSort = me.sorters.length && me.sortOnFilter && !me.remoteSort, length = decoded.length; for (i = 0; i < length; i++) { me.filters.replace(decoded[i]); } filters = me.filters.items; if (filters.length) { if (me.remoteFilter) { delete me.totalCount; if (me.buffered) { me.data.clear(); me.loadPage(1); } else { me.currentPage = 1; me.load(); } } else { me.snapshot = me.snapshot || me.data.clone(); me.data = me.snapshot.filter(filters); me.constructGroups(); if (doLocalSort) { me.sort(); } else { me.fireEvent('datachanged', me); me.fireEvent('refresh', me); } } me.fireEvent('filterchange', me, filters); } }, clearFilter: function(suppressEvent) { var me = this; me.filters.clear(); if (me.remoteFilter) { if (suppressEvent) { return; } delete me.totalCount; if (me.buffered) { me.data.clear(); me.loadPage(1); } else { me.currentPage = 1; me.load(); } } else if (me.isFiltered()) { me.data = me.snapshot; delete me.snapshot; me.constructGroups(); if (suppressEvent !== true) { me.fireEvent('datachanged', me); me.fireEvent('refresh', me); } } me.fireEvent('filterchange', me, me.filters.items); }, removeFilter: function(toRemove, applyFilters) { var me = this; if (!me.remoteFilter && me.isFiltered()) { if (toRemove instanceof Ext.util.Filter) { me.filters.remove(toRemove); } else { me.filters.removeAtKey(toRemove); } if (applyFilters !== false) { if (me.filters.length) { me.filter(); } else { me.clearFilter(); } } else { me.fireEvent('filterchange', me, me.filters.items); } } }, addFilter: function(filters, applyFilters) { var me = this, decoded, i, length; decoded = me.decodeFilters(filters); length = decoded.length; for (i = 0; i < length; i++) { me.filters.replace(decoded[i]); } if (applyFilters !== false && me.filters.length) { me.filter(); } else { me.fireEvent('filterchange', me, me.filters.items); } }, isFiltered: function() { var snapshot = this.snapshot; return !!(snapshot && snapshot !== this.data); }, filterBy: function(fn, scope) { var me = this; me.snapshot = me.snapshot || me.data.clone(); me.data = me.queryBy(fn, scope || me); me.fireEvent('datachanged', me); me.fireEvent('refresh', me); }, queryBy: function(fn, scope) { var me = this; return (me.snapshot || me.data).filterBy(fn, scope || me); }, query: function(property, value, anyMatch, caseSensitive, exactMatch) { var me = this, queryFn = me.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch), results = me.queryBy(queryFn); if(!results) { results = new Ext.util.MixedCollection(); } return results; }, loadData: function(data, append) { var length = data.length, newData = [], i; for (i = 0; i < length; i++) { newData.push(this.createModel(data[i])); } this.loadRecords(newData, append ? this.addRecordsOptions : undefined); }, loadRawData : function(data, append) { var me = this, result = me.proxy.reader.read(data), records = result.records; if (result.success) { me.totalCount = result.total; me.loadRecords(records, append ? me.addRecordsOptions : undefined); } }, loadRecords: function(records, options) { var me = this, i = 0, length = records.length, start, addRecords, snapshot = me.snapshot; if (options) { start = options.start; addRecords = options.addRecords; } if (!addRecords) { delete me.snapshot; me.clearData(true); } else if (snapshot) { snapshot.addAll(records); } me.data.addAll(records); if (start !== undefined) { for (; i < length; i++) { records[i].index = start + i; records[i].join(me); } } else { for (; i < length; i++) { records[i].join(me); } } me.suspendEvents(); if (me.filterOnLoad && !me.remoteFilter) { me.filter(); } if (me.sortOnLoad && !me.remoteSort) { me.sort(undefined, undefined, undefined, true); } me.resumeEvents(); if (me.isGrouped()) { me.constructGroups(); } me.fireEvent('datachanged', me); me.fireEvent('refresh', me); }, loadPage: function(page, options) { var me = this; me.currentPage = page; options = Ext.apply({ page: page, start: (page - 1) * me.pageSize, limit: me.pageSize, addRecords: !me.clearOnPageLoad }, options); if (me.buffered) { options.limit = me.viewSize || me.defaultViewSize; options.loadCallback = options.callback; delete options.callback; return me.loadToPrefetch(options); } me.read(options); }, nextPage: function(options) { this.loadPage(this.currentPage + 1, options); }, previousPage: function(options) { this.loadPage(this.currentPage - 1, options); }, clearData: function(isLoad) { var me = this, records, i; if (!me.buffered && me.data) { records = me.data.items; i = records.length; while (i--) { records[i].unjoin(me); } } if (me.data) { me.data.clear(); } if (isLoad !== true || me.clearRemovedOnLoad) { me.removed.length = 0; } }, loadToPrefetch: function(options) { var me = this, i, records, dataSetSize, prefetchOptions = options, startIdx = options.start, endIdx = options.start + options.limit - 1, loadEndIdx = Math.min(endIdx, options.start + (me.viewSize || options.limit) - 1), startPage = me.getPageFromRecordIndex(Math.max(startIdx - me.trailingBufferZone, 0)), endPage = me.getPageFromRecordIndex(endIdx + me.leadingBufferZone), waitForRequestedRange = function() { if (me.rangeCached(startIdx, loadEndIdx)) { me.loading = false; records = me.data.getRange(startIdx, loadEndIdx); me.data.un('pageAdded', waitForRequestedRange); if (me.hasListeners.guaranteedrange) { me.guaranteeRange(startIdx, loadEndIdx, options.callback, options.scope); } if (options.loadCallback) { options.loadCallback.call(options.scope || me, records, operation, true); } if (options.callback) { options.callback.call(options.scope||me, records, startIdx, endIdx, options); } me.fireEvent('datachanged', me); me.fireEvent('refresh', me); me.fireEvent('load', me, records, true); if (options.groupChange) { me.fireGroupChange(); } } }, operation; if (me.fireEvent('beforeload', me, options) !== false) { delete me.totalCount; me.loading = true; if (options.callback) { prefetchOptions = Ext.apply({}, options); delete prefetchOptions.callback; } me.on('prefetch', function(store, records, successful, op) { if (successful) { operation = op; if ((dataSetSize = me.getTotalCount())) { me.data.on('pageAdded', waitForRequestedRange); loadEndIdx = Math.min(loadEndIdx, dataSetSize - 1); endPage = me.getPageFromRecordIndex(Math.min(loadEndIdx + me.leadingBufferZone, dataSetSize - 1)); for (i = startPage + 1; i <= endPage; ++i) { me.prefetchPage(i, prefetchOptions); } } else { me.fireEvent('datachanged', me); me.fireEvent('refresh', me); me.fireEvent('load', me, records, true); } } else { me.fireEvent('load', me, records, false); } }, null, {single: true}); me.prefetchPage(startPage, prefetchOptions); } }, prefetch: function(options) { var me = this, pageSize = me.pageSize, proxy, operation; if (pageSize) { if (me.lastPageSize && pageSize != me.lastPageSize) { Ext.Error.raise("pageSize cannot be dynamically altered"); } if (!me.data.pageSize) { me.data.pageSize = pageSize; } } else { me.pageSize = me.data.pageSize = pageSize = options.limit; } me.lastPageSize = pageSize; if (!options.page) { options.page = me.getPageFromRecordIndex(options.start); options.start = (options.page - 1) * pageSize; options.limit = Math.ceil(options.limit / pageSize) * pageSize; } if (!me.pageRequests[options.page]) { options = Ext.apply({ action : 'read', filters: me.filters.items, sorters: me.sorters.items, groupers: me.groupers.items, pageMapGeneration: me.data.pageMapGeneration }, options); operation = new Ext.data.Operation(options); if (me.fireEvent('beforeprefetch', me, operation) !== false) { proxy = me.proxy; me.pageRequests[options.page] = proxy.read(operation, me.onProxyPrefetch, me); if (proxy.isSynchronous) { delete me.pageRequests[options.page]; } } } return me; }, onPageMapClear: function() { var me = this, loadingFlag = me.wasLoading, reqs = me.pageRequests, req, page; if (me.data.events.pageadded) { me.data.events.pageadded.clearListeners(); } me.loading = true; me.totalCount = 0; for (page in reqs) { if (reqs.hasOwnProperty(page)) { req = reqs[page]; delete reqs[page]; delete req.callback; } } me.fireEvent('clear', me); me.loading = loadingFlag; }, prefetchPage: function(page, options) { var me = this, pageSize = me.pageSize || me.defaultPageSize, start = (page - 1) * me.pageSize, total = me.totalCount; if (total !== undefined && me.getCount() === total) { return; } me.prefetch(Ext.applyIf({ page : page, start : start, limit : pageSize }, options)); }, onProxyPrefetch: function(operation) { var me = this, resultSet = operation.getResultSet(), records = operation.getRecords(), successful = operation.wasSuccessful(), page = operation.page; if (operation.pageMapGeneration === me.data.pageMapGeneration) { if (resultSet) { me.totalCount = resultSet.total; me.fireEvent('totalcountchange', me.totalCount); } if (page !== undefined) { delete me.pageRequests[page]; } me.loading = false; me.fireEvent('prefetch', me, records, successful, operation); if (successful) { me.cachePage(records, operation.page); } Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]); } }, cachePage: function(records, page) { var me = this, len = records.length, i; if (!Ext.isDefined(me.totalCount)) { me.totalCount = records.length; me.fireEvent('totalcountchange', me.totalCount); } for (i = 0; i < len; i++) { records[i].join(me); } me.data.addPage(page, records); }, rangeCached: function(start, end) { return this.data && this.data.hasRange(start, end); }, pageCached: function(page) { return this.data && this.data.hasPage(page); }, pagePending: function(page) { return !!this.pageRequests[page]; }, rangeSatisfied: function(start, end) { return this.rangeCached(start, end); }, getPageFromRecordIndex: function(index) { return Math.floor(index / this.pageSize) + 1; }, onGuaranteedRange: function(options) { var me = this, totalCount = me.getTotalCount(), start = options.prefetchStart, end = (options.prefetchEnd > totalCount - 1) ? totalCount - 1 : options.prefetchEnd, range; end = Math.max(0, end); range = me.data.getRange(start, end); if (options.fireEvent !== false) { me.fireEvent('guaranteedrange', range, start, end, options); } if (options.callback) { options.callback.call(options.scope || me, range, start, end, options); } }, guaranteeRange: function(start, end, callback, scope, options) { options = Ext.apply({ callback: callback, scope: scope }, options); this.getRange(start, end, options) }, prefetchRange: function(start, end) { var me = this, startPage, endPage, page; if (!me.rangeCached(start, end)) { startPage = me.getPageFromRecordIndex(start); endPage = me.getPageFromRecordIndex(end); me.data.maxSize = me.purgePageCount ? (endPage - startPage + 1) + me.purgePageCount : 0; for (page = startPage; page <= endPage; page++) { if (!me.pageCached(page)) { me.prefetchPage(page); } } } }, primeCache: function(start, end, direction) { var me = this; if (direction === -1) { start = Math.max(start - me.leadingBufferZone, 0); end = Math.min(end + me.trailingBufferZone, me.totalCount - 1); } else if (direction === 1) { start = Math.max(Math.min(start - me.trailingBufferZone, me.totalCount - me.pageSize), 0); end = Math.min(end + me.leadingBufferZone, me.totalCount - 1); } else { start = Math.min(Math.max(Math.floor(start - ((me.leadingBufferZone + me.trailingBufferZone) / 2)), 0), me.totalCount - me.pageSize); end = Math.min(Math.max(Math.ceil (end + ((me.leadingBufferZone + me.trailingBufferZone) / 2)), 0), me.totalCount - 1); } me.prefetchRange(start, end); }, sort: function(sorters) { var me = this; if (sorters && me.buffered && me.remoteSort) { me.data.clear(); } return me.callParent(arguments); }, doSort: function(sorterFn) { var me = this, range, ln, i; if (me.remoteSort) { if (me.buffered) { me.data.clear(); me.loadPage(1); } else { me.load(); } } else { me.data.sortBy(sorterFn); if (!me.buffered) { range = me.getRange(); ln = range.length; for (i = 0; i < ln; i++) { range[i].index = i; } } me.fireEvent('datachanged', me); me.fireEvent('refresh', me); } }, find: function(property, value, start, anyMatch, caseSensitive, exactMatch) { var fn = this.createFilterFn(property, value, anyMatch, caseSensitive, exactMatch); return fn ? this.data.findIndexBy(fn, null, start) : -1; }, findRecord: function() { var me = this, index = me.find.apply(me, arguments); return index !== -1 ? me.getAt(index) : null; }, createFilterFn: function(property, value, anyMatch, caseSensitive, exactMatch) { if (Ext.isEmpty(value)) { return false; } value = Ext.util.AbstractMixedCollection.prototype.createValueMatcher(value, anyMatch, caseSensitive, exactMatch); return function(r) { return value.test(r.data[property]); }; }, findExact: function(property, value, start) { return this.data.findIndexBy(function(rec) { return rec.isEqual(rec.get(property), value); }, this, start); }, findBy: function(fn, scope, start) { return this.data.findIndexBy(fn, scope, start); }, collect: function(dataIndex, allowNull, bypassFilter) { var me = this, data = (bypassFilter === true && me.snapshot) ? me.snapshot : me.data; return data.collect(dataIndex, 'data', allowNull); }, getCount: function() { return this.data.getCount(); }, getTotalCount: function() { return this.totalCount || 0; }, getAt: function(index) { return this.data.getAt(index); }, getRange: function(start, end, options) { var me = this, requiredStart, requiredEnd, maxIndex = me.totalCount - 1, lastRequestStart = me.lastRequestStart, pageAddHandler, result; options = Ext.apply({ prefetchStart: start, prefetchEnd: end }, options); if (me.buffered) { end = (end >= me.totalCount) ? maxIndex : end; requiredStart = start === 0 ? 0 : start - 1; requiredEnd = end === maxIndex ? end : end + 1; me.lastRequestStart = start; me.lastRequestEnd = end; if (me.rangeCached(requiredStart, requiredEnd)) { me.onGuaranteedRange(options); result = me.data.getRange(start, end); } else { me.fireEvent('cachemiss', me, start, end); pageAddHandler = function(page, records) { if (me.rangeCached(requiredStart, requiredEnd)) { me.fireEvent('cachefilled', me, start, end); me.data.un('pageAdded', pageAddHandler); me.onGuaranteedRange(options); } }; me.data.on('pageAdded', pageAddHandler); me.prefetchRange(start, end); } me.primeCache(start, end, start < lastRequestStart ? -1 : 1); } else { result = me.data.getRange(start, end); if (options.callback) { options.callback.call(options.scope || me, result, start, end, options) } } return result; }, getById: function(id) { var result = (this.snapshot || this.data).findBy(function(record) { return record.getId() === id; }); return result; }, getByInternalId: function(internalId) { var result; if (this.buffered) { result = (this.snapshot || this.data).findBy(function(record) { return record.internalId === internalId; }); } else { result = this.data.get(internalId); } return result; }, indexOf: function(record) { return this.data.indexOf(record); }, indexOfTotal: function(record) { var index = record.index; if (index || index === 0) { return index; } return this.indexOf(record); }, indexOfId: function(id) { return this.indexOf(this.getById(id)); }, first: function(grouped) { var me = this; if (grouped && me.isGrouped()) { return me.aggregate(function(records) { return records.length ? records[0] : undefined; }, me, true); } else { return me.data.first(); } }, last: function(grouped) { var me = this; if (grouped && me.isGrouped()) { return me.aggregate(function(records) { var len = records.length; return len ? records[len - 1] : undefined; }, me, true); } else { return me.data.last(); } }, sum: function(field, grouped) { var me = this; if (grouped && me.isGrouped()) { return me.aggregate(me.getSum, me, true, [field]); } else { return me.getSum(me.data.items, field); } }, getSum: function(records, field) { var total = 0, i = 0, len = records.length; for (; i < len; ++i) { total += records[i].get(field); } return total; }, count: function(grouped) { var me = this; if (grouped && me.isGrouped()) { return me.aggregate(function(records) { return records.length; }, me, true); } else { return me.getCount(); } }, min: function(field, grouped) { var me = this; if (grouped && me.isGrouped()) { return me.aggregate(me.getMin, me, true, [field]); } else { return me.getMin(me.data.items, field); } }, getMin: function(records, field) { var i = 1, len = records.length, value, min; if (len > 0) { min = records[0].get(field); } for (; i < len; ++i) { value = records[i].get(field); if (value < min) { min = value; } } return min; }, max: function(field, grouped) { var me = this; if (grouped && me.isGrouped()) { return me.aggregate(me.getMax, me, true, [field]); } else { return me.getMax(me.data.items, field); } }, getMax: function(records, field) { var i = 1, len = records.length, value, max; if (len > 0) { max = records[0].get(field); } for (; i < len; ++i) { value = records[i].get(field); if (value > max) { max = value; } } return max; }, average: function(field, grouped) { var me = this; if (grouped && me.isGrouped()) { return me.aggregate(me.getAverage, me, true, [field]); } else { return me.getAverage(me.data.items, field); } }, getAverage: function(records, field) { var i = 0, len = records.length, sum = 0; if (records.length > 0) { for (; i < len; ++i) { sum += records[i].get(field); } return sum / len; } return 0; }, aggregate: function(fn, scope, grouped, args) { args = args || []; if (grouped && this.isGrouped()) { var groups = this.getGroups(), len = groups.length, out = {}, group, i; for (i = 0; i < len; ++i) { group = groups[i]; out[group.name] = this.getAggregate(fn, scope || this, group.children, args); } return out; } else { return this.getAggregate(fn, scope, this.data.items, args); } }, getAggregate: function(fn, scope, records, args){ args = args || []; return fn.apply(scope || this, [records].concat(args)); }, onIdChanged: function(rec, oldId, newId, oldInternalId){ var snapshot = this.snapshot; if (snapshot) { snapshot.updateKey(oldInternalId, newId); } this.data.updateKey(oldInternalId, newId); this.callParent(arguments); }, commitChanges : function(){ var me = this, recs = me.getModifiedRecords(), len = recs.length, i = 0; for (; i < len; i++){ recs[i].commit(); } me.removed.length = 0; }, filterNewOnly: function(item){ return item.phantom === true; }, getRejectRecords: function() { return Ext.Array.push(this.data.filterBy(this.filterNewOnly).items, this.getUpdatedRecords()); }, rejectChanges : function() { var me = this, recs = me.getRejectRecords(), len = recs.length, i = 0, rec; for (; i < len; i++) { rec = recs[i]; rec.reject(); if (rec.phantom) { me.remove(rec); } } recs = me.removed; len = recs.length; for (i = len-1; i >= 0; i--) { rec = recs[i]; me.insert(rec.removedFrom || 0, rec); rec.reject(); } me.removed.length = 0; } }, function() { Ext.regStore('ext-empty-store', {fields: [], proxy: 'memory'}); }); Ext.define('Ext.data.reader.Array', { extend: Ext.data.reader.Json , alternateClassName: 'Ext.data.ArrayReader', alias : 'reader.array', totalProperty: undefined, successProperty: undefined, createFieldAccessExpression: function(field, fieldVarName, dataName) { var index = (field.mapping == null) ? field.originalIndex : field.mapping, result; if (typeof index === 'function') { result = fieldVarName + '.mapping(' + dataName + ', this)'; } else { if (isNaN(index)) { index = '"' + index + '"'; } result = dataName + "[" + index + "]"; } return result; } }); Ext.define('Ext.data.ArrayStore', { extend: Ext.data.Store , alias: 'store.array', constructor: function(config) { config = Ext.apply({ proxy: { type: 'memory', reader: 'array' } }, config); this.callParent([config]); }, loadData: function(data, append) { if (this.expandData === true) { var r = [], i = 0, ln = data.length; for (; i < ln; i++) { r[r.length] = [data[i]]; } data = r; } this.callParent([data, append]); } }, function() { Ext.data.SimpleStore = Ext.data.ArrayStore; }); Ext.define('Ext.data.Batch', { mixins: { observable: Ext.util.Observable }, autoStart: false, pauseOnException: false, current: -1, total: 0, isRunning: false, isComplete: false, hasException: false, constructor: function(config) { var me = this; me.mixins.observable.constructor.call(me, config); me.operations = []; me.exceptions = []; }, add: function(operation) { this.total++; operation.setBatch(this); this.operations.push(operation); return this; }, start: function( index) { var me = this; if (me.isRunning) { return me; } me.exceptions.length = 0; me.hasException = false; me.isRunning = true; return me.runOperation(Ext.isDefined(index) ? index : me.current + 1); }, retry: function() { return this.start(this.current); }, runNextOperation: function() { return this.runOperation(this.current + 1); }, pause: function() { this.isRunning = false; return this; }, runOperation: function(index) { var me = this, operations = me.operations, operation = operations[index], onProxyReturn; if (operation === undefined) { me.isRunning = false; me.isComplete = true; me.fireEvent('complete', me, operations[operations.length - 1]); } else { me.current = index; onProxyReturn = function(operation) { var hasException = operation.hasException(); if (hasException) { me.hasException = true; me.exceptions.push(operation); me.fireEvent('exception', me, operation); } if (hasException && me.pauseOnException) { me.pause(); } else { operation.setCompleted(); me.fireEvent('operationcomplete', me, operation); me.runNextOperation(); } }; operation.setStarted(); me.proxy[operation.action](operation, onProxyReturn, me); } return me; } }); Ext.define('Ext.data.BufferStore', { extend: Ext.data.Store , alias: 'store.buffer', sortOnLoad: false, filterOnLoad: false, constructor: function() { Ext.Error.raise('The BufferStore class has been deprecated. Instead, specify the buffered config option on Ext.data.Store'); } }); Ext.define('Ext.direct.Manager', { singleton: true, mixins: { observable: Ext.util.Observable }, exceptions: { TRANSPORT: 'xhr', PARSE: 'parse', DATA: 'data', LOGIN: 'login', SERVER: 'exception' }, constructor: function() { var me = this; me.addEvents( 'event', 'exception' ); me.transactions = new Ext.util.MixedCollection(); me.providers = new Ext.util.MixedCollection(); me.mixins.observable.constructor.call(me); }, addProvider: function(provider) { var me = this, args = arguments, relayers = me.relayers || (me.relayers = {}), i, len; if (args.length > 1) { for (i = 0, len = args.length; i < len; ++i) { me.addProvider(args[i]); } return; } if (!provider.isProvider) { provider = Ext.create('direct.' + provider.type + 'provider', provider); } me.providers.add(provider); provider.on('data', me.onProviderData, me); if (provider.relayedEvents) { relayers[provider.id] = me.relayEvents(provider, provider.relayedEvents); } if (!provider.isConnected()) { provider.connect(); } return provider; }, getProvider: function(id) { return id.isProvider ? id : this.providers.get(id); }, removeProvider: function(provider) { var me = this, providers = me.providers, relayers = me.relayers, id; provider = provider.isProvider ? provider : providers.get(provider); if (provider) { provider.un('data', me.onProviderData, me); id = provider.id; if (relayers[id]) { relayers[id].destroy(); delete relayers[id]; } providers.remove(provider); return provider; } return null; }, addTransaction: function(transaction) { this.transactions.add(transaction); return transaction; }, removeTransaction: function(transaction) { var me = this; transaction = me.getTransaction(transaction); me.transactions.remove(transaction); return transaction; }, getTransaction: function(transaction) { return typeof transaction === 'object' ? transaction : this.transactions.get(transaction); }, onProviderData: function(provider, event) { var me = this, i, len; if (Ext.isArray(event)) { for (i = 0, len = event.length; i < len; ++i) { me.onProviderData(provider, event[i]); } return; } if (event.name && event.name != 'event' && event.name != 'exception') { me.fireEvent(event.name, event); } else if (event.status === false) { me.fireEvent('exception', event); } me.fireEvent('event', event, provider); }, parseMethod: function(fn) { if (Ext.isString(fn)) { var parts = fn.split('.'), i = 0, len = parts.length, current = Ext.global; while (current && i < len) { current = current[parts[i]]; ++i; } fn = Ext.isFunction(current) ? current : null; } return fn || null; } }, function() { Ext.Direct = Ext.direct.Manager; }); Ext.define('Ext.data.proxy.Direct', { extend: Ext.data.proxy.Server , alternateClassName: 'Ext.data.DirectProxy', alias: 'proxy.direct', paramOrder: undefined, paramsAsHash: true, directFn : undefined, paramOrderRe: /[\s,|]/, constructor: function(config){ var me = this, paramOrder; me.callParent(arguments); paramOrder = me.paramOrder; if (Ext.isString(paramOrder)) { me.paramOrder = paramOrder.split(me.paramOrderRe); } }, resolveMethods: function() { var me = this, fn = me.directFn, api = me.api, Manager = Ext.direct.Manager, method; if (fn) { method = me.directFn = Manager.parseMethod(fn); if (!Ext.isFunction(method)) { Ext.Error.raise('Cannot resolve directFn ' + fn); } } else if (api) { for (fn in api) { if (api.hasOwnProperty(fn)) { method = api[fn]; api[fn] = Manager.parseMethod(method); if (!Ext.isFunction(api[fn])) { Ext.Error.raise('Cannot resolve Direct api ' + fn + ' method ' + method); } } } } me.methodsResolved = true; }, doRequest: function(operation, callback, scope) { var me = this, writer = me.getWriter(), request = me.buildRequest(operation), params = request.params, args = [], fn, method; if (!me.methodsResolved) { me.resolveMethods(); } fn = me.api[request.action] || me.directFn; if (operation.allowWrite()) { request = writer.write(request); } if (operation.action == 'read') { method = fn.directCfg.method; args = method.getArgs(params, me.paramOrder, me.paramsAsHash); } else { args.push(request.jsonData); } Ext.apply(request, { args: args, directFn: fn }); args.push(me.createRequestCallback(request, operation, callback, scope), me); fn.apply(window, args); }, applyEncoding: Ext.identityFn, createRequestCallback: function(request, operation, callback, scope){ var me = this; return function(data, event){ me.processResponse(event.status, operation, request, event, callback, scope); }; }, extractResponseData: function(response){ return Ext.isDefined(response.result) ? response.result : response.data; }, setException: function(operation, response) { operation.setException(response.message); }, buildUrl: function(){ return ''; } }); Ext.define('Ext.data.DirectStore', { extend: Ext.data.Store , alias: 'store.direct', constructor : function(config){ config = Ext.apply({}, config); if (!config.proxy) { var proxy = { type: 'direct', reader: { type: 'json' } }; Ext.copyTo(proxy, config, 'paramOrder,paramsAsHash,directFn,api,simpleSortMode'); Ext.copyTo(proxy.reader, config, 'totalProperty,root,idProperty'); config.proxy = proxy; } this.callParent([config]); } }); Ext.define('Ext.data.JsonP', { singleton: true, requestCount: 0, requests: {}, timeout: 30000, disableCaching: true, disableCachingParam: '_dc', callbackKey: 'callback', request: function(options) { options = Ext.apply({}, options); var me = this, disableCaching = Ext.isDefined(options.disableCaching) ? options.disableCaching : me.disableCaching, cacheParam = options.disableCachingParam || me.disableCachingParam, id = ++me.requestCount, callbackName = options.callbackName || 'callback' + id, callbackKey = options.callbackKey || me.callbackKey, timeout = Ext.isDefined(options.timeout) ? options.timeout : me.timeout, params = Ext.apply({}, options.params), url = options.url, name = Ext.name, request, script; if (disableCaching && !params[cacheParam]) { params[cacheParam] = Ext.Date.now(); } options.params = params; params[callbackKey] = name + '.data.JsonP.' + callbackName; script = me.createScript(url, params, options); me.requests[id] = request = { url: url, params: params, script: script, id: id, scope: options.scope, success: options.success, failure: options.failure, callback: options.callback, callbackKey: callbackKey, callbackName: callbackName }; if (timeout > 0) { request.timeout = setTimeout(Ext.bind(me.handleTimeout, me, [request]), timeout); } me.setupErrorHandling(request); me[callbackName] = Ext.bind(me.handleResponse, me, [request], true); me.loadScript(request); return request; }, abort: function(request){ var me = this, requests = me.requests, key; if (request) { if (!request.id) { request = requests[request]; } me.handleAbort(request); } else { for (key in requests) { if (requests.hasOwnProperty(key)) { me.abort(requests[key]); } } } }, setupErrorHandling: function(request){ request.script.onerror = Ext.bind(this.handleError, this, [request]); }, handleAbort: function(request){ request.errorType = 'abort'; this.handleResponse(null, request); }, handleError: function(request){ request.errorType = 'error'; this.handleResponse(null, request); }, cleanupErrorHandling: function(request){ request.script.onerror = null; }, handleTimeout: function(request){ request.errorType = 'timeout'; this.handleResponse(null, request); }, handleResponse: function(result, request){ var success = true; if (request.timeout) { clearTimeout(request.timeout); } delete this[request.callbackName]; delete this.requests[request.id]; this.cleanupErrorHandling(request); Ext.fly(request.script).remove(); if (request.errorType) { success = false; Ext.callback(request.failure, request.scope, [request.errorType]); } else { Ext.callback(request.success, request.scope, [result]); } Ext.callback(request.callback, request.scope, [success, result, request.errorType]); Ext.EventManager.idleEvent.fire(); }, createScript: function(url, params, options) { var script = document.createElement('script'); script.setAttribute("src", Ext.urlAppend(url, Ext.Object.toQueryString(params))); script.setAttribute("async", true); script.setAttribute("type", "text/javascript"); return script; }, loadScript: function (request) { Ext.getHead().appendChild(request.script); } }); Ext.define('Ext.data.proxy.JsonP', { extend: Ext.data.proxy.Server , alternateClassName: 'Ext.data.ScriptTagProxy', alias: ['proxy.jsonp', 'proxy.scripttag'], defaultWriterType: 'base', callbackKey : 'callback', recordParam: 'records', autoAppendParams: true, constructor: function() { this.addEvents( 'exception' ); this.callParent(arguments); }, doRequest: function(operation, callback, scope) { var me = this, request = me.buildRequest(operation), params = request.params; Ext.apply(request, { callbackKey: me.callbackKey, timeout: me.timeout, scope: me, disableCaching: false, callback: me.createRequestCallback(request, operation, callback, scope) }); if (me.autoAppendParams) { request.params = {}; } request.jsonp = Ext.data.JsonP.request(request); request.params = params; operation.setStarted(); me.lastRequest = request; return request; }, createRequestCallback: function(request, operation, callback, scope) { var me = this; return function(success, response, errorType) { delete me.lastRequest; me.processResponse(success, operation, request, response, callback, scope); }; }, setException: function(operation, response) { operation.setException(operation.request.jsonp.errorType); }, buildUrl: function(request) { var me = this, url = me.callParent(arguments), records = request.records, writer = me.getWriter(), params, filters, filter, i; if (writer && request.operation.allowWrite()) { request = writer.write(request); } params = request.params; filters = params.filters, delete params.filters; if (filters && filters.length) { for (i = 0; i < filters.length; i++) { filter = filters[i]; if (filter.value) { params[filter.property] = filter.value; } } } if ((!writer || !writer.encode) && Ext.isArray(records) && records.length > 0) { params[me.recordParam] = me.encodeRecords(records); } if (me.autoAppendParams) { url = Ext.urlAppend(url, Ext.Object.toQueryString(params)); } return url; }, abort: function() { var lastRequest = this.lastRequest; if (lastRequest) { Ext.data.JsonP.abort(lastRequest.jsonp); } }, encodeRecords: function(records) { var encoded = [], i = 0, len = records.length; for (; i < len; i++) { encoded.push(Ext.encode(records[i].getData())); } return encoded; } }); Ext.define('Ext.data.JsonPStore', { extend: Ext.data.Store , alias : 'store.jsonp', constructor: function(config) { config = Ext.apply({ proxy: { type: 'jsonp', reader: 'json' } }, config); this.callParent([config]); } }); Ext.define('Ext.data.JsonStore', { extend: Ext.data.Store , alias: 'store.json', constructor: function(config) { config = Ext.apply({ proxy: { type : 'ajax', reader: 'json', writer: 'json' } }, config); this.callParent([config]); } }); Ext.define('Ext.data.NodeInterface', { statics: { decorate: function(modelClass) { var idName, idField, idType; if (typeof modelClass == 'string') { modelClass = Ext.ModelManager.getModel(modelClass); } else if (modelClass.isModel) { modelClass = Ext.ModelManager.getModel(modelClass.modelName); } if (modelClass.prototype.isNode) { return; } idName = modelClass.prototype.idProperty; idField = modelClass.prototype.fields.get(idName); idType = modelClass.prototype.fields.get(idName).type.type; modelClass.override(this.getPrototypeBody()); this.applyFields(modelClass, [ { name : 'parentId', type : idType, defaultValue : null, useNull : idField.useNull }, { name : 'index', type : 'int', defaultValue : -1, persist : false , convert: null }, { name : 'depth', type : 'int', defaultValue : 0, persist : false , convert: null }, { name : 'expanded', type : 'bool', defaultValue : false, persist : false , convert: null }, { name : 'expandable', type : 'bool', defaultValue : true, persist : false , convert: null }, { name : 'checked', type : 'auto', defaultValue : null, persist : false , convert: null }, { name : 'leaf', type : 'bool', defaultValue : false }, { name : 'cls', type : 'string', defaultValue : '', persist : false , convert: null }, { name : 'iconCls', type : 'string', defaultValue : '', persist : false , convert: null }, { name : 'icon', type : 'string', defaultValue : '', persist : false , convert: null }, { name : 'root', type : 'boolean', defaultValue : false, persist : false , convert: null }, { name : 'isLast', type : 'boolean', defaultValue : false, persist : false , convert: null }, { name : 'isFirst', type : 'boolean', defaultValue : false, persist : false , convert: null }, { name : 'allowDrop', type : 'boolean', defaultValue : true, persist : false , convert: null }, { name : 'allowDrag', type : 'boolean', defaultValue : true, persist : false , convert: null }, { name : 'loaded', type : 'boolean', defaultValue : false, persist : false , convert: null }, { name : 'loading', type : 'boolean', defaultValue : false, persist : false , convert: null }, { name : 'href', type : 'string', defaultValue : '', persist : false , convert: null }, { name : 'hrefTarget', type : 'string', defaultValue : '', persist : false , convert: null }, { name : 'qtip', type : 'string', defaultValue : '', persist : false , convert: null }, { name : 'qtitle', type : 'string', defaultValue : '', persist : false , convert: null }, { name : 'qshowDelay', type : 'int', defaultValue : 0, persist : false , convert: null }, { name : 'children', type : 'auto', defaultValue : null, persist : false , convert: null } ]); }, applyFields: function(modelClass, addFields) { var modelPrototype = modelClass.prototype, fields = modelPrototype.fields, keys = fields.keys, ln = addFields.length, addField, i; for (i = 0; i < ln; i++) { addField = addFields[i]; if (!Ext.Array.contains(keys, addField.name)) { fields.add(new Ext.data.Field(addField)); } } }, getPrototypeBody: function() { var bubbledEvents = { idchanged : true, append : true, remove : true, bulkremove : true, move : true, insert : true, beforeappend : true, beforeremove : true, beforemove : true, beforeinsert : true, expand : true, collapse : true, beforeexpand : true, beforecollapse: true, sort : true, rootchange : true }; return { isNode: true, constructor: function() { var me = this; me.callParent(arguments); me.firstChild = me.lastChild = me.parentNode = me.previousSibling = me.nextSibling = null; me.childNodes = []; return me; }, createNode: function(node) { if (!node.isModel) { node = Ext.ModelManager.create(node, this.modelName); } if (!node.childNodes) { node.firstChild = node.lastChild = node.parentNode = node.previousSibling = node.nextSibling = null; node.childNodes = []; } return node; }, isLeaf : function() { return this.get('leaf') === true; }, setFirstChild : function(node) { this.firstChild = node; }, setLastChild : function(node) { this.lastChild = node; }, updateInfo: function(commit, info) { var me = this, oldDepth = me.data.depth, childInfo = {}, children = me.childNodes, childCount = children.length, i, phantom = me.phantom, dataObject = me[me.persistenceProperty], fields = me.fields, modified = me.modified, propName, newValue, field, currentValue, key, newParentId = info.parentId, settingIndexInNewParent, persistentField; if (!info) { Ext.Error.raise('NodeInterface expects update info to be passed'); } for (propName in info) { field = fields.get(propName); newValue = info[propName]; persistentField = field && field.persist; currentValue = dataObject[propName]; settingIndexInNewParent = persistentField && (propName === 'index') && (currentValue !== -1) && (newParentId && newParentId !== modified.parentId); if (!settingIndexInNewParent && me.isEqual(currentValue, newValue)) { continue; } dataObject[propName] = newValue; if (persistentField) { if (!settingIndexInNewParent && modified.hasOwnProperty(propName)) { if (me.isEqual(modified[propName], newValue)) { delete modified[propName]; me.dirty = false; for (key in modified) { if (modified.hasOwnProperty(key)){ me.dirty = true; break; } } } } else { me.dirty = true; modified[propName] = currentValue; } } } if (commit) { me.commit(); me.phantom = phantom; } if (me.data.depth !== oldDepth) { childInfo = { depth: me.data.depth + 1 }; for (i = 0; i < childCount; i++) { children[i].updateInfo(commit, childInfo); } } }, isLast : function() { return this.get('isLast'); }, isFirst : function() { return this.get('isFirst'); }, hasChildNodes : function() { return !this.isLeaf() && this.childNodes.length > 0; }, isExpandable : function() { var me = this; if (me.get('expandable')) { return !(me.isLeaf() || (me.isLoaded() && !me.phantom && !me.hasChildNodes())); } return false; }, triggerUIUpdate: function() { this.afterEdit([]); }, appendChild : function(node, suppressEvents, commit) { var me = this, i, ln, index, oldParent, previousSibling, childInfo = { isLast: true, parentId: me.getId(), depth: (me.data.depth||0) + 1 }; if (Ext.isArray(node)) { me.callStore('suspendAutoSync'); for (i = 0, ln = node.length - 1; i < ln; i++) { me.appendChild(node[i], suppressEvents, commit); } me.callStore('resumeAutoSync'); me.appendChild(node[ln], suppressEvents, commit); } else { node = me.createNode(node); if (suppressEvents !== true && me.fireEventArgs("beforeappend", [me, node]) === false) { return false; } index = me.childNodes.length; oldParent = node.parentNode; if (oldParent) { if (suppressEvents !== true && node.fireEventArgs("beforemove", [node, oldParent, me, index]) === false) { return false; } oldParent.removeChild(node, false, false, true); } Ext.suspendLayouts(); index = me.childNodes.length; if (index === 0) { me.setFirstChild(node); } me.childNodes[index] = node; node.parentNode = me; node.nextSibling = null; me.setLastChild(node); previousSibling = me.childNodes[index - 1]; if (previousSibling) { node.previousSibling = previousSibling; previousSibling.nextSibling = node; previousSibling.updateInfo(commit, { isLast: false }); previousSibling.triggerUIUpdate(); } else { node.previousSibling = null; } childInfo.isFirst = index === 0; childInfo.index = index; node.updateInfo(commit, childInfo); if (!me.isLoaded()) { me.set('loaded', true); } else if (me.childNodes.length === 1) { me.triggerUIUpdate(); } if (index && me.childNodes[index - 1].isExpanded()) { me.childNodes[index - 1].cascadeBy(me.triggerUIUpdate); } if(!node.isLeaf() && node.phantom) { node.set('loaded', true); } Ext.resumeLayouts(true); if (suppressEvents !== true) { me.fireEventArgs("append", [me, node, index]); if (oldParent) { node.fireEventArgs("move", [node, oldParent, me, index]); } } return node; } }, getOwnerTree: function() { var node = this, store; while (node.parentNode) { node = node.parentNode; } store = node.store; if (store) { if (store.treeStore) { store = store.treeStore; } if (store.tree) { return store.ownerTree; } } return undefined; }, removeChild : function(node, destroy, suppressEvents, isMove) { var me = this, index = me.indexOf(node), i, childCount, previousSibling; if (index === -1 || (suppressEvents !== true && me.fireEventArgs("beforeremove", [me, node, !!isMove]) === false)) { return false; } Ext.suspendLayouts(); Ext.Array.erase(me.childNodes, index, 1); if (me.firstChild === node) { me.setFirstChild(node.nextSibling); } if (me.lastChild === node) { me.setLastChild(node.previousSibling); } previousSibling = node.previousSibling if (previousSibling) { node.previousSibling.nextSibling = node.nextSibling; } if (node.nextSibling) { node.nextSibling.previousSibling = node.previousSibling; if (index === 0) { node.nextSibling.updateInfo(false, { isFirst: true }); } for (i = index, childCount = me.childNodes.length; i < childCount; i++) { me.childNodes[i].updateInfo(false, { index: i }); } } else if (previousSibling) { previousSibling.updateInfo(false, { isLast: true }); if (previousSibling.isExpanded()) { previousSibling.cascadeBy(me.triggerUIUpdate); } else { previousSibling.triggerUIUpdate(); } } if (!me.childNodes.length) { me.triggerUIUpdate(); } Ext.resumeLayouts(true); if (suppressEvents !== true) { node.removeContext = { parentNode: node.parentNode, previousSibling: node.previousSibling, nextSibling: node.nextSibling }; node.previousSibling = node.nextSibling = node.parentNode = null; me.fireEventArgs('remove', [me, node, !!isMove]); node.removeContext = null; } if (destroy) { node.destroy(true); } else { node.clear(); } return node; }, copy: function(newId, deep) { var me = this, result = me.callParent(arguments), len = me.childNodes ? me.childNodes.length : 0, i; if (deep) { for (i = 0; i < len; i++) { result.appendChild(me.childNodes[i].copy(undefined, true)); } } return result; }, clear : function(destroy) { var me = this; me.parentNode = me.previousSibling = me.nextSibling = null; if (destroy) { me.firstChild = me.lastChild = null; } }, destroy : function(silent) { var me = this, options = me.destroyOptions, nodes = me.childNodes, nLen = nodes.length, n; if (silent === true) { me.clear(true); for (n = 0; n < nLen; n++) { nodes[n].destroy(true); } me.childNodes = null; delete me.destroyOptions; me.callParent([options]); } else { me.destroyOptions = silent; me.remove(true); } }, insertBefore : function(node, refNode, suppressEvents) { var me = this, index = me.indexOf(refNode), oldParent = node.parentNode, refIndex = index, childCount, previousSibling, i; if (!refNode) { return me.appendChild(node); } if (node === refNode) { return false; } node = me.createNode(node); if (suppressEvents !== true && me.fireEventArgs("beforeinsert", [me, node, refNode]) === false) { return false; } if (oldParent === me && me.indexOf(node) < index) { refIndex--; } if (oldParent) { if (suppressEvents !== true && node.fireEventArgs("beforemove", [node, oldParent, me, index, refNode]) === false) { return false; } oldParent.removeChild(node, false, false, true); } if (refIndex === 0) { me.setFirstChild(node); } Ext.Array.splice(me.childNodes, refIndex, 0, node); node.parentNode = me; node.nextSibling = refNode; refNode.previousSibling = node; previousSibling = me.childNodes[refIndex - 1]; if (previousSibling) { node.previousSibling = previousSibling; previousSibling.nextSibling = node; } else { node.previousSibling = null; } node.updateInfo(false, { parentId: me.getId(), index: refIndex, isFirst: refIndex === 0, isLast: false, depth: (me.data.depth||0) + 1 }); for (i = refIndex + 1, childCount = me.childNodes.length; i < childCount; i++) { me.childNodes[i].updateInfo(false, { index: i }); } if (!me.isLoaded()) { me.set('loaded', true); } else if (me.childNodes.length === 1) { me.triggerUIUpdate(); } if(!node.isLeaf() && node.phantom) { node.set('loaded', true); } if (suppressEvents !== true) { me.fireEventArgs("insert", [me, node, refNode]); if (oldParent) { node.fireEventArgs("move", [node, oldParent, me, refIndex, refNode]); } } return node; }, insertChild: function(index, node) { var sibling = this.childNodes[index]; if (sibling) { return this.insertBefore(node, sibling); } else { return this.appendChild(node); } }, remove : function(destroy, suppressEvents) { var me = this, parentNode = me.parentNode; if (parentNode) { parentNode.removeChild(me, destroy, suppressEvents); } else if (destroy) { me.destroy(true); } return me; }, removeAll : function(destroy, suppressEvents, fromParent) { var me = this, childNodes = me.childNodes, i = 0, len = childNodes.length, node; if (!len) { return; } me.fireEventArgs('bulkremove', [me, childNodes, false]); for (; i < len; ++i) { node = childNodes[i]; node.removeContext = { parentNode: node.parentNode, previousSibling: node.previousSibling, nextSibling: node.nextSibling }; node.previousSibling = node.nextSibling = node.parentNode = null; me.fireEventArgs('remove', [me, node, false]); node.removeContext = null; if (destroy) { node.destroy(true); } else { node.removeAll(false, suppressEvents, true); } } me.firstChild = me.lastChild = null; if (fromParent) { me.childNodes = null; } else { me.childNodes.length = 0; me.triggerUIUpdate(); } return me; }, getChildAt : function(index) { return this.childNodes[index]; }, replaceChild : function(newChild, oldChild, suppressEvents) { var s = oldChild ? oldChild.nextSibling : null; this.removeChild(oldChild, false, suppressEvents); this.insertBefore(newChild, s, suppressEvents); return oldChild; }, indexOf : function(child) { return Ext.Array.indexOf(this.childNodes, child); }, indexOfId: function(id) { var childNodes = this.childNodes, len = childNodes.length, i = 0; for (; i < len; ++i) { if (childNodes[i].getId() === id) { return i; } } return -1; }, getPath: function(field, separator) { field = field || this.idProperty; separator = separator || '/'; var path = [this.get(field)], parent = this.parentNode; while (parent) { path.unshift(parent.get(field)); parent = parent.parentNode; } return separator + path.join(separator); }, getDepth : function() { return this.get('depth'); }, bubble : function(fn, scope, args) { var p = this; while (p) { if (fn.apply(scope || p, args || [p]) === false) { break; } p = p.parentNode; } }, cascade: function() { if (Ext.isDefined(Ext.global.console)) { Ext.global.console.warn('Ext.data.Node: cascade has been deprecated. Please use cascadeBy instead.'); } return this.cascadeBy.apply(this, arguments); }, cascadeBy : function(fn, scope, args) { if (fn.apply(scope || this, args || [this]) !== false) { var childNodes = this.childNodes, length = childNodes.length, i; for (i = 0; i < length; i++) { childNodes[i].cascadeBy(fn, scope, args); } } }, eachChild : function(fn, scope, args) { var childNodes = this.childNodes, length = childNodes.length, i; for (i = 0; i < length; i++) { if (fn.apply(scope || this, args || [childNodes[i]]) === false) { break; } } }, findChild : function(attribute, value, deep) { return this.findChildBy(function() { return this.get(attribute) == value; }, null, deep); }, findChildBy : function(fn, scope, deep) { var cs = this.childNodes, len = cs.length, i = 0, n, res; for (; i < len; i++) { n = cs[i]; if (fn.call(scope || n, n) === true) { return n; } else if (deep) { res = n.findChildBy(fn, scope, deep); if (res !== null) { return res; } } } return null; }, contains : function(node) { return node.isAncestor(this); }, isAncestor : function(node) { var p = this.parentNode; while (p) { if (p === node) { return true; } p = p.parentNode; } return false; }, sort : function(sortFn, recursive, suppressEvent) { var cs = this.childNodes, ln = cs.length, i, n, info = { isFirst: true }; if (ln > 0) { Ext.Array.sort(cs, sortFn); this.setFirstChild(cs[0]); this.setLastChild(cs[ln - 1]); for (i = 0; i < ln; i++) { n = cs[i]; n.previousSibling = cs[i-1]; n.nextSibling = cs[i+1]; info.isLast = (i === ln - 1); info.index = i; n.updateInfo(false, info); info.isFirst = false; if (recursive && !n.isLeaf()) { n.sort(sortFn, true, true); } } if (suppressEvent !== true) { this.fireEventArgs('sort', [this, cs]); } } }, isExpanded: function() { return this.get('expanded'); }, isLoaded: function() { return this.get('loaded'); }, isLoading: function() { return this.get('loading'); }, isRoot: function() { return !this.parentNode; }, isVisible: function() { var parent = this.parentNode; while (parent) { if (!parent.isExpanded()) { return false; } parent = parent.parentNode; } return true; }, expand: function(recursive, callback, scope) { var me = this, owner; if (!me.isLeaf()) { if (me.isLoading()) { me.on('expand', function() { me.expand(recursive, callback, scope); }, me, {single: true}); } else { if (!me.isExpanded()) { me.fireEventArgs('beforeexpand', [me, me.onChildNodesAvailable, me, [recursive, callback, scope]]); } else if (recursive) { owner = me.getOwnerTree(); me.expandChildren(true, owner ? owner.singleExpand : false, callback, scope); } else { Ext.callback(callback, scope || me, [me.childNodes]); } } } else { Ext.callback(callback, scope || me); } }, onChildNodesAvailable: function(records, recursive, callback, scope) { var me = this, owner; Ext.suspendLayouts(); me.set('expanded', true); me.fireEventArgs('expand', [me, me.childNodes, false]); if (recursive) { owner = me.getOwnerTree(); me.expandChildren(true, owner ? owner.singleExpand : false, callback, scope); } else { Ext.callback(callback, scope || me, [me.childNodes]); } Ext.resumeLayouts(true); }, expandChildren: function(recursive, singleExpand, callback, scope) { var me = this, i, allNodes = me.childNodes, expandNodes = [], ln = singleExpand ? Math.min(allNodes.length, 1) : allNodes.length, node; for (i = 0; i < ln; ++i) { node = allNodes[i]; if (!node.isLeaf()) { expandNodes[expandNodes.length] = node; } } ln = expandNodes.length; for (i = 0; i < ln; ++i) { expandNodes[i].expand(recursive); } if (callback) { Ext.callback(callback, scope || me, [me.childNodes]); } }, collapse: function(recursive, callback, scope) { var me = this, expanded = me.isExpanded(), len = me.childNodes.length, i, collapseChildren; if (!me.isLeaf() && ((!expanded && recursive) || me.fireEventArgs('beforecollapse', [me]) !== false)) { Ext.suspendLayouts(); if (me.isExpanded()) { if (recursive) { collapseChildren = function() { for (i = 0; i < len; i++) { me.childNodes[i].setCollapsed(true); } }; if (callback) { callback = Ext.Function.createSequence(collapseChildren, callback); } else { callback = collapseChildren; } } me.set('expanded', false); me.fireEventArgs('collapse', [me, me.childNodes, false, callback ? Ext.Function.bind(callback, scope, [me.childNodes]) : null, null]); callback = null; } else if (recursive) { for (i = 0; i < len; i++) { me.childNodes[i].setCollapsed(true); } } Ext.resumeLayouts(true); } Ext.callback(callback, scope || me, [me.childNodes]); }, setCollapsed: function(recursive) { var me = this, len = me.childNodes.length, i; if (!me.isLeaf() && me.fireEventArgs('beforecollapse', [me, Ext.emptyFn]) !== false) { me.data.expanded = false; me.fireEventArgs('collapse', [me, me.childNodes, false, null, null]); if (recursive) { for (i = 0; i < len; i++) { me.childNodes[i].setCollapsed(true); } } } }, collapseChildren: function(recursive, callback, scope) { var me = this, i, allNodes = me.childNodes, ln = allNodes.length, collapseNodes = [], node; for (i = 0; i < ln; ++i) { node = allNodes[i]; if (!node.isLeaf() && node.isLoaded() && node.isExpanded()) { collapseNodes.push(node); } } ln = collapseNodes.length; if (ln) { for (i = 0; i < ln; ++i) { node = collapseNodes[i]; if (i === ln - 1) { node.collapse(recursive, callback, scope); } else { node.collapse(recursive); } } } else { Ext.callback(callback, scope); } }, fireEventArgs: function(eventName, args) { var fireEventArgs = Ext.data.Model.prototype.fireEventArgs, result, eventSource, tree, treeStore, rootNode; if (bubbledEvents[eventName]) { for (eventSource = this; result !== false && eventSource; eventSource = (rootNode = eventSource).parentNode) { if (eventSource.hasListeners[eventName]) { result = fireEventArgs.call(eventSource, eventName, args); } } tree = rootNode.rootOf; if (result !== false && tree) { treeStore = tree.treeStore; if (treeStore && treeStore.hasListeners[eventName]) { result = treeStore.fireEventArgs.call(treeStore, eventName, args); } if (result !== false && tree.hasListeners[eventName]) { result = tree.fireEventArgs.call(tree, eventName, args); } } return result; } else { return fireEventArgs.apply(this, arguments) } }, serialize: function() { var result = Ext.data.writer.Json.prototype.getRecordData(this), childNodes = this.childNodes, len = childNodes.length, children, i; if (len > 0) { children = []; for (i = 0; i < len; i++) { children.push(childNodes[i].serialize()); } result.children = children; } return result; } }; } } }); Ext.define('Ext.data.NodeStore', { extend: Ext.data.Store , alias: 'store.node', isNodeStore: true, node: null, recursive: false, rootVisible: false, isExpandingOrCollapsing: 0, constructor: function(config) { var me = this, node; config = config || {}; Ext.apply(me, config); config.proxy = {type: 'proxy'}; me.callParent([config]); node = me.node; if (node) { me.node = null; me.setNode(node); } }, getTotalCount: function() { return this.getCount(); }, setNode: function(node) { var me = this; if (me.node && me.node != node) { me.mun(me.node, { expand: me.onNodeExpand, collapse: me.onNodeCollapse, append: me.onNodeAppend, insert: me.onNodeInsert, bulkremove: me.onBulkRemove, remove: me.onNodeRemove, sort: me.onNodeSort, scope: me }); me.node = null; } if (node) { Ext.data.NodeInterface.decorate(node.self); me.removeAll(); if (me.rootVisible) { me.add(node); } else if (!node.isExpanded() && me.treeStore.autoLoad !== false) { node.expand(); } me.mon(node, { expand: me.onNodeExpand, collapse: me.onNodeCollapse, append: me.onNodeAppend, insert: me.onNodeInsert, bulkremove: me.onBulkRemove, remove: me.onNodeRemove, sort: me.onNodeSort, scope: me }); me.node = node; if (node.isExpanded() && node.isLoaded()) { me.onNodeExpand(node, node.childNodes, true); } } }, onNodeSort: function(node, childNodes) { var me = this; if ((me.indexOf(node) !== -1 || (node === me.node && !me.rootVisible) && node.isExpanded())) { Ext.suspendLayouts(); me.onNodeCollapse(node, childNodes, true); me.onNodeExpand(node, childNodes, true); Ext.resumeLayouts(true); } }, onNodeExpand: function(parent, records, suppressEvent) { var me = this, insertIndex = me.indexOf(parent) + 1, toAdd = []; if (!suppressEvent) { me.fireEvent('beforeexpand', parent, records, insertIndex); } me.handleNodeExpand(parent, records, toAdd); me.insert(insertIndex, toAdd); if (!suppressEvent) { me.fireEvent('expand', parent, records); } }, handleNodeExpand: function(parent, records, toAdd) { var me = this, ln = records ? records.length : 0, i, record; if (!me.recursive && parent !== me.node) { return; } if (parent !== this.node && !me.isVisible(parent)) { return; } if (ln) { for (i = 0; i < ln; i++) { record = records[i]; toAdd.push(record); if (record.isExpanded()) { if (record.isLoaded()) { me.handleNodeExpand(record, record.childNodes, toAdd); } else { record.set('expanded', false); record.expand(); } } } } }, onBulkRemove: function(parent, childNodes, isMove) { this.onNodeCollapse(parent, childNodes, true); }, onNodeCollapse: function(parent, records, suppressEvent, callback, scope) { var me = this, collapseIndex = me.indexOf(parent) + 1, node, lastNodeIndexPlus, sibling, found; if (!me.recursive && parent !== me.node) { return; } if (!suppressEvent) { me.fireEvent('beforecollapse', parent, records, collapseIndex, callback, scope); } if (records.length && me.data.contains(records[0])) { node = parent; while (node.parentNode) { sibling = node.nextSibling; if (sibling) { found = true; lastNodeIndexPlus = me.indexOf(sibling); break; } else { node = node.parentNode; } } if (!found) { lastNodeIndexPlus = me.getCount(); } me.removeAt(collapseIndex, lastNodeIndexPlus - collapseIndex); } if (!suppressEvent) { me.fireEvent('collapse', parent, records, collapseIndex); } }, onNodeAppend: function(parent, node, index) { var me = this, refNode, sibling; if (me.isVisible(node)) { if (index === 0) { refNode = parent; } else { sibling = node.previousSibling; while (sibling.isExpanded() && sibling.lastChild) { sibling = sibling.lastChild; } refNode = sibling; } me.insert(me.indexOf(refNode) + 1, node); if (!node.isLeaf() && node.isExpanded()) { if (node.isLoaded()) { me.onNodeExpand(node, node.childNodes, true); } else if (!me.treeStore.fillCount ) { node.set('expanded', false); node.expand(); } } } }, onNodeInsert: function(parent, node, refNode) { var me = this, index = this.indexOf(refNode); if (index != -1 && me.isVisible(node)) { me.insert(index, node); if (!node.isLeaf() && node.isExpanded()) { if (node.isLoaded()) { me.onNodeExpand(node, node.childNodes, true); } else { node.set('expanded', false); node.expand(); } } } }, onNodeRemove: function(parent, node, isMove) { var me = this; if (me.indexOf(node) != -1) { if (!node.isLeaf() && node.isExpanded()) { node.parentNode = node.removeContext.parentNode; node.nextSibling = node.removeContext.nextSibling; me.onNodeCollapse(node, node.childNodes, true); node.parentNode = node.nextSibling = null; } me.remove(node); } }, isVisible: function(node) { var parent = node.parentNode; while (parent) { if (parent === this.node && parent.data.expanded) { return true; } if (!parent.data.expanded) { return false; } parent = parent.parentNode; } return false; } }); Ext.define('Ext.data.Request', { action: undefined, params: undefined, method: 'GET', url: undefined, constructor: function(config) { Ext.apply(this, config); } }); Ext.define('Ext.data.SequentialIdGenerator', { extend: Ext.data.IdGenerator , alias: 'idgen.sequential', constructor: function() { var me = this; me.callParent(arguments); me.parts = [ me.prefix, '']; }, prefix: '', seed: 1, generate: function () { var me = this, parts = me.parts; parts[1] = me.seed++; return parts.join(''); } }); Ext.define('Ext.data.Tree', { alias: 'data.tree', mixins: { observable: Ext.util.Observable }, root: null, constructor: function(root) { var me = this; me.mixins.observable.constructor.call(me); if (root) { me.setRootNode(root); } me.on({ scope: me, idchanged: me.onNodeIdChanged, insert: me.onNodeInsert, append: me.onNodeAppend, remove: me.onNodeRemove }); }, getRootNode : function() { return this.root; }, setRootNode : function(node) { var me = this; me.root = node; if (node.rootOf) { node.rootOf.removeRootNode(); } else if (node.parentNode) { node.parentNode.removeChild(node); } node.rootOf = me; if (node.fireEventArgs('beforeappend', [null, node]) !== false) { node.set('root', true); node.updateInfo(true, { isFirst: true, isLast: true, depth: 0, index: 0, parentId: null }); me.nodeHash = {}; node.fireEvent('append', null, node); node.fireEvent('rootchange', node); } return node; }, removeRootNode: function() { var me = this, root = me.root; root.set('root', false); root.fireEvent('remove', null, root, false); root.fireEvent('rootchange', null); root.rootOf = me.root = null; return root; }, flatten: function(){ return Ext.Object.getValues(this.nodeHash); }, onNodeInsert: function(parent, node) { this.registerNode(node, true); }, onNodeAppend: function(parent, node) { this.registerNode(node, true); }, onNodeRemove: function(parent, node) { this.unregisterNode(node, true); }, onNodeIdChanged: function(node, oldId, newId, oldInternalId) { var nodeHash = this.nodeHash; nodeHash[node.internalId] = node; delete nodeHash[oldInternalId]; }, getNodeById : function(id) { return this.nodeHash[id]; }, registerNode : function(node, includeChildren) { var me = this, children, length, i; me.nodeHash[node.internalId] = node; if (includeChildren === true) { children = node.childNodes; length = children.length; for (i = 0; i < length; i++) { me.registerNode(children[i], true); } } }, unregisterNode : function(node, includeChildren) { var me = this, children, length, i; delete me.nodeHash[node.internalId]; if (includeChildren === true) { children = node.childNodes; length = children.length; for (i = 0; i < length; i++) { me.unregisterNode(children[i], true); } } }, sort: function(sorterFn, recursive) { this.getRootNode().sort(sorterFn, recursive); }, filter: function(filters, recursive) { this.getRootNode().filter(filters, recursive); } }); Ext.define('Ext.data.TreeModel', { extend: Ext.data.Model }, function () { Ext.data.NodeInterface.decorate(this); }); Ext.define('Ext.data.TreeStore', { extend: Ext.data.AbstractStore , alias: 'store.tree', clearOnLoad : true, clearRemovedOnLoad: true, nodeParam: 'node', defaultRootId: 'root', defaultRootText: 'Root', defaultRootProperty: 'children', rootProperty: 'children', fillCount: 0, folderSort: false, constructor: function(config) { var me = this, root, fields, defaultRoot; config = Ext.apply({}, config); fields = config.fields || me.fields; if (!fields) { config.fields = [ {name: 'text', type: 'string'} ]; defaultRoot = config.defaultRootProperty || me.defaultRootProperty; if (defaultRoot !== me.defaultRootProperty) { config.fields.push({ name: defaultRoot, type: 'auto', defaultValue: null, persist: false }); } } me.callParent([config]); me.tree = new Ext.data.Tree(); me.tree.treeStore = me; me.tree.on({ scope: me, remove: me.onNodeRemove, beforeexpand: me.onBeforeNodeExpand, append: me.onNodeAdded, insert: me.onNodeAdded, sort: me.onNodeSort }); me.onBeforeSort(); root = me.root; if (root) { delete me.root; me.setRootNode(root); } if (Ext.isDefined(me.nodeParameter)) { if (Ext.isDefined(Ext.global.console)) { Ext.global.console.warn('Ext.data.TreeStore: nodeParameter has been deprecated. Please use nodeParam instead.'); } me.nodeParam = me.nodeParameter; delete me.nodeParameter; } }, setProxy: function(proxy) { var reader, needsRoot; if (proxy instanceof Ext.data.proxy.Proxy) { needsRoot = Ext.isEmpty(proxy.getReader().root); } else if (Ext.isString(proxy)) { needsRoot = true; } else { reader = proxy.reader; needsRoot = !(reader && !Ext.isEmpty(reader.root)); } proxy = this.callParent(arguments); proxy.idParam = this.nodeParam; if (needsRoot) { reader = proxy.getReader(); reader.root = this.defaultRootProperty; reader.buildExtractors(true); } return proxy; }, onBeforeSort: function() { if (this.folderSort) { this.sort({ property: 'leaf', direction: 'ASC' }, 'prepend', false); } }, onBeforeNodeExpand: function(node, callback, scope, args) { var me = this, reader, dataRoot, data, callbackArgs; if (node.isLoaded()) { callbackArgs = [node.childNodes]; if (args) { callbackArgs.push.apply(callbackArgs, args); } Ext.callback(callback, scope || node, callbackArgs); } else if (dataRoot = (data = (node.raw || node[node.persistenceProperty])[(reader = me.getProxy().getReader()).root])) { me.fillNode(node, reader.extractData(dataRoot)); delete data[reader.root]; callbackArgs = [node.childNodes]; if (args) { callbackArgs.push.apply(callbackArgs, args); } Ext.callback(callback, scope || node, callbackArgs); } else if (node.isLoading()) { me.on('load', function() { callbackArgs = [node.childNodes]; if (args) { callbackArgs.push.apply(callbackArgs, args); } Ext.callback(callback, scope || node, callbackArgs); }, me, { single: true, priority: 1001 }); } else { me.read({ node: node, internalCallback: function() { delete me.lastOptions.internalCallback; callbackArgs = [node.childNodes]; if (args) { callbackArgs.push.apply(callbackArgs, args); } Ext.callback(callback, scope || node, callbackArgs); } }); } }, getNewRecords: function() { return Ext.Array.filter(this.tree.flatten(), this.filterNew); }, getUpdatedRecords: function() { return Ext.Array.filter(this.tree.flatten(), this.filterUpdated); }, onNodeRemove: function(parent, node, isMove) { var me = this; node.unjoin(me); if (!node.phantom && !isMove) { Ext.Array.include(me.removed, node); } if (me.autoSync && !me.autoSyncSuspended && !isMove) { me.sync(); } }, onNodeAdded: function(parent, node) { var me = this, proxy = me.getProxy(), reader = proxy.getReader(), data = node.raw || node[node.persistenceProperty], dataRoot; Ext.Array.remove(me.removed, node); node.join(me); if (!node.isLeaf() && !me.lazyFill) { dataRoot = reader.getRoot(data); if (dataRoot) { me.fillNode(node, reader.extractData(dataRoot)); delete data[reader.root]; } } if (me.autoSync && !me.autoSyncSuspended && (node.phantom || node.dirty)) { me.sync(); } }, onNodeSort: function() { if (this.autoSync && !this.autoSyncSuspended) { this.sync(); } }, setRootNode: function(root, preventLoad) { var me = this, model = me.model, idProperty = model.prototype.idProperty root = root || {}; if (!root.isModel) { root = Ext.apply({}, root); Ext.applyIf(root, { id: me.defaultRootId, text: me.defaultRootText, allowDrag: false }); if (root[idProperty] === undefined) { root[idProperty] = me.defaultRootId; } Ext.data.NodeInterface.decorate(model); root = Ext.ModelManager.create(root, model); } else if (root.isModel && !root.isNode) { Ext.data.NodeInterface.decorate(model); } me.getProxy().getReader().buildExtractors(true); me.tree.setRootNode(root); if (preventLoad !== true && !root.isLoaded() && (me.autoLoad === true || root.isExpanded())) { root.data.expanded = false; root.expand(); } return root; }, getRootNode: function() { return this.tree.getRootNode(); }, getNodeById: function(id) { return this.tree.getNodeById(id); }, getById: function(id) { return this.getNodeById(id); }, load: function(options) { options = options || {}; options.params = options.params || {}; var me = this, node = options.node || me.tree.getRootNode(), callback = options.callback, scope = options.scope, operation; if (!node) { node = me.setRootNode({ expanded: true }, true); } if (node.data.expanded) { node.data.loaded = false; if (me.clearOnLoad) { node.data.expanded = false; } options.callback = function() { if (!me.clearOnLoad) { node.collapse(); } node.expand(); Ext.callback(callback, scope, arguments); } } options.id = node.getId(); options = Ext.apply({ action: 'read', filters: me.filters.items, sorters: me.getSorters(), node: options.node || node }, options); me.lastOptions = options; operation = new Ext.data.Operation(options); if (me.fireEvent('beforeload', me, operation) !== false) { if (me.clearOnLoad) { if(me.clearRemovedOnLoad) { me.clearRemoved(node); } me.tree.un('remove', me.onNodeRemove, me); node.removeAll(false); me.tree.on('remove', me.onNodeRemove, me); } me.loading = true; me.proxy.read(operation, me.onProxyLoad, me); } if (me.loading && node) { node.set('loading', true); } return me; }, clearRemoved: function(node) { var me = this, removed = me.removed, id = node.getId(), removedLength = removed.length, i = removedLength, recordsToClear = {}, newRemoved = [], removedHash = {}, removedNode, targetNode, targetId; if(node === me.getRootNode()) { me.removed = []; return; } for(; i--;) { removedNode = removed[i]; removedHash[removedNode.getId()] = removedNode; } for(i = removedLength; i--;) { removedNode = removed[i]; targetNode = removedNode; while(targetNode && targetNode.getId() !== id) { targetId = targetNode.get('parentId'); targetNode = targetNode.parentNode || me.getNodeById(targetId) || removedHash[targetId]; } if(targetNode) { recordsToClear[removedNode.getId()] = removedNode; } } for(i = 0; i < removedLength; i++) { removedNode = removed[i]; if(!recordsToClear[removedNode.getId()]) { newRemoved.push(removedNode); } } me.removed = newRemoved; }, fillNode: function(node, newNodes) { var me = this, ln = newNodes ? newNodes.length : 0, sorters = me.sorters, i, sortCollection, needsIndexSort = false, performLocalSort = ln && me.sortOnLoad && !me.remoteSort && sorters && sorters.items && sorters.items.length, node1, node2, rootFill; for (i = 1; i < ln; i++) { node1 = newNodes[i]; node2 = newNodes[i - 1]; needsIndexSort = node1[node1.persistenceProperty].index != node2[node2.persistenceProperty].index; if (needsIndexSort) { break; } } if (performLocalSort) { if (needsIndexSort) { me.sorters.insert(0, me.indexSorter); } sortCollection = new Ext.util.MixedCollection(); sortCollection.addAll(newNodes); sortCollection.sort(me.sorters.items); newNodes = sortCollection.items; me.sorters.remove(me.indexSorter); } else if (needsIndexSort) { Ext.Array.sort(newNodes, me.sortByIndex); } node.set('loaded', true); rootFill = me.fillCount === 0; if (rootFill) { me.fireEvent('beforefill', me, node, newNodes); } ++me.fillCount; if (newNodes.length) { node.appendChild(newNodes, undefined, true); } if (rootFill) { me.fireEvent('fillcomplete', me, node, newNodes); } --me.fillCount; return newNodes; }, sortByIndex: function(node1, node2) { return node1[node1.persistenceProperty].index - node2[node2.persistenceProperty].index; }, onIdChanged: function(model, oldId, newId, oldInternalId){ this.tree.onNodeIdChanged(model, oldId, newId, oldInternalId); this.callParent(arguments); }, onProxyLoad: function(operation) { var me = this, successful = operation.wasSuccessful(), records = operation.getRecords(), node = operation.node, scope = operation.scope || me, args = [records, operation, successful]; me.loading = false; node.set('loading', false); if (successful) { if (!me.clearOnLoad) { records = me.cleanRecords(node, records); } records = me.fillNode(node, records); } Ext.callback(operation.internalCallback, scope, args); me.fireEvent('read', me, operation.node, records, successful); me.fireEvent('load', me, operation.node, records, successful); Ext.callback(operation.callback, scope, args); }, cleanRecords: function(node, records){ var nodeHash = {}, childNodes = node.childNodes, i = 0, len = childNodes.length, out = [], rec; for (; i < len; ++i) { nodeHash[childNodes[i].getId()] = true; } for (i = 0, len = records.length; i < len; ++i) { rec = records[i]; if (!nodeHash[rec.getId()]) { out.push(rec); } } return out; }, removeAll: function() { var root = this.getRootNode(); if (root) { root.destroy(true); } this.fireEvent('clear', this); }, doSort: function(sorterFn) { var me = this; if (me.remoteSort) { me.load(); } else { me.tree.sort(sorterFn, true); me.fireEvent('datachanged', me); me.fireEvent('refresh', me); } me.fireEvent('sort', me, me.sorters.getRange()); } }, function() { var proto = this.prototype; proto.indexSorter = new Ext.util.Sorter({ sorterFn: proto.sortByIndex }); }); Ext.define('Ext.data.UuidGenerator', (function () { var twoPow14 = Math.pow(2, 14), twoPow16 = Math.pow(2, 16), twoPow28 = Math.pow(2, 28), twoPow32 = Math.pow(2, 32); function toHex (value, length) { var ret = value.toString(16); if (ret.length > length) { ret = ret.substring(ret.length - length); } else if (ret.length < length) { ret = Ext.String.leftPad(ret, length, '0'); } return ret; } function rand (lo, hi) { var v = Math.random() * (hi - lo + 1); return Math.floor(v) + lo; } function split (bignum) { if (typeof(bignum) == 'number') { var hi = Math.floor(bignum / twoPow32); return { lo: Math.floor(bignum - hi * twoPow32), hi: hi }; } return bignum; } return { extend: Ext.data.IdGenerator , alias: 'idgen.uuid', id: 'uuid', version: 4, constructor: function() { var me = this; me.callParent(arguments); me.parts = []; me.init(); }, generate: function () { var me = this, parts = me.parts, ts = me.timestamp; parts[0] = toHex(ts.lo, 8); parts[1] = toHex(ts.hi & 0xFFFF, 4); parts[2] = toHex(((ts.hi >>> 16) & 0xFFF) | (me.version << 12), 4); parts[3] = toHex(0x80 | ((me.clockSeq >>> 8) & 0x3F), 2) + toHex(me.clockSeq & 0xFF, 2); parts[4] = toHex(me.salt.hi, 4) + toHex(me.salt.lo, 8); if (me.version == 4) { me.init(); } else { ++ts.lo; if (ts.lo >= twoPow32) { ts.lo = 0; ++ts.hi; } } return parts.join('-').toLowerCase(); }, getRecId: function (rec) { return rec.getId(); }, init: function () { var me = this, salt, time; if (me.version == 4) { me.clockSeq = rand(0, twoPow14-1); salt = me.salt || (me.salt = {}); time = me.timestamp || (me.timestamp = {}); salt.lo = rand(0, twoPow32-1); salt.hi = rand(0, twoPow16-1); time.lo = rand(0, twoPow32-1); time.hi = rand(0, twoPow28-1); } else { me.salt = split(me.salt); me.timestamp = split(me.timestamp); me.salt.hi |= 0x100; } }, reconfigure: function (config) { Ext.apply(this, config); this.init(); } }; }())); Ext.define('Ext.data.reader.Xml', { extend: Ext.data.reader.Reader , alternateClassName: 'Ext.data.XmlReader', alias : 'reader.xml', createAccessor: function(expr) { var me = this; if (Ext.isEmpty(expr)) { return Ext.emptyFn; } if (Ext.isFunction(expr)) { return expr; } return function(root) { return me.getNodeValue(Ext.DomQuery.selectNode(expr, root)); }; }, getNodeValue: function(node) { if (node) { if (typeof node.normalize === 'function') { node.normalize(); } node = node.firstChild; if (node) { return node.nodeValue; } } return undefined; }, getResponseData: function(response) { var xml = response.responseXML, error, msg; if (!xml) { msg = 'XML data not found in the response'; error = new Ext.data.ResultSet({ total : 0, count : 0, records: [], success: false, message: msg }); this.fireEvent('exception', this, response, error); Ext.Logger.warn(msg); return error; } return this.readRecords(xml); }, getData: function(data) { return data.documentElement || data; }, getRoot: function(data) { var nodeName = data.nodeName, root = this.root; if (!root || (nodeName && nodeName == root)) { return data; } else if (Ext.DomQuery.isXml(data)) { return Ext.DomQuery.selectNode(root, data); } }, extractData: function(root) { var recordName = this.record; if (recordName != root.nodeName) { root = Ext.DomQuery.select(recordName, root); } else { root = [root]; } return this.callParent([root]); }, getAssociatedDataRoot: function(data, associationName) { return Ext.DomQuery.select(associationName, data)[0]; }, readRecords: function(doc) { if (Ext.isArray(doc)) { doc = doc[0]; } this.xmlData = doc; return this.callParent([doc]); }, createFieldAccessExpression: function(field, fieldVarName, dataName) { var namespace = this.namespace, selector, result; selector = field.mapping || ((namespace ? namespace + '|' : '') + field.name); if (typeof selector === 'function') { result = fieldVarName + '.mapping(' + dataName + ', this)'; } else { result = 'me.getNodeValue(Ext.DomQuery.selectNode("' + selector + '", ' + dataName + '))'; } return result; } }); Ext.define('Ext.data.writer.Xml', { extend: Ext.data.writer.Writer , alternateClassName: 'Ext.data.XmlWriter', alias: 'writer.xml', documentRoot: 'xmlData', defaultDocumentRoot: 'xmlData', header: '', record: 'record', writeRecords: function(request, data) { var me = this, xml = [], i = 0, len = data.length, root = me.documentRoot, record = me.record, needsRoot = data.length !== 1, item, key; xml.push(me.header || ''); if (!root && needsRoot) { root = me.defaultDocumentRoot; } if (root) { xml.push('<', root, '>'); } for (; i < len; ++i) { item = data[i]; xml.push('<', record, '>'); for (key in item) { if (item.hasOwnProperty(key)) { xml.push('<', key, '>', item[key], ''); } } xml.push(''); } if (root) { xml.push(''); } request.xmlData = xml.join(''); return request; } }); Ext.define('Ext.data.XmlStore', { extend: Ext.data.Store , alias: 'store.xml', constructor: function(config){ config = Ext.apply({ proxy: { type: 'ajax', reader: 'xml', writer: 'xml' } }, config); this.callParent([config]); } }); Ext.define('Ext.data.association.BelongsTo', { extend: Ext.data.association.Association , alternateClassName: 'Ext.data.BelongsToAssociation', alias: 'association.belongsto', constructor: function(config) { this.callParent(arguments); var me = this, ownerProto = me.ownerModel.prototype, associatedName = me.associatedName, getterName = me.getterName || 'get' + associatedName, setterName = me.setterName || 'set' + associatedName; Ext.applyIf(me, { name : associatedName, foreignKey : associatedName.toLowerCase() + "_id", instanceName: associatedName + 'BelongsToInstance', associationKey: associatedName.toLowerCase() }); ownerProto[getterName] = me.createGetter(); ownerProto[setterName] = me.createSetter(); }, createSetter: function() { var me = this, foreignKey = me.foreignKey, instanceName = me.instanceName; return function(value, options, scope) { var setByRecord = value && value.isModel, valueToSet = setByRecord ? value.getId() : value; if (setByRecord) { this[instanceName] = value; } else if (this[instanceName] instanceof Ext.data.Model && !this.isEqual(this.get(foreignKey), valueToSet)) { delete this[instanceName]; } this.set(foreignKey, valueToSet); if (Ext.isFunction(options)) { options = { callback: options, scope: scope || this }; } if (Ext.isObject(options)) { return this.save(options); } }; }, createGetter: function() { var me = this, associatedName = me.associatedName, associatedModel = me.associatedModel, foreignKey = me.foreignKey, primaryKey = me.primaryKey, instanceName = me.instanceName; return function(options, scope) { options = options || {}; var model = this, foreignKeyId = model.get(foreignKey), success, instance, args; if (options.reload === true || model[instanceName] === undefined) { instance = Ext.ModelManager.create({}, associatedName); instance.set(primaryKey, foreignKeyId); if (typeof options == 'function') { options = { callback: options, scope: scope || model }; } success = options.success; options.success = function(rec){ model[instanceName] = rec; if (success) { success.apply(this, arguments); } }; associatedModel.load(foreignKeyId, options); model[instanceName] = instance; return instance; } else { instance = model[instanceName]; args = [instance]; scope = scope || options.scope || model; Ext.callback(options, scope, args); Ext.callback(options.success, scope, args); Ext.callback(options.failure, scope, args); Ext.callback(options.callback, scope, args); return instance; } }; }, read: function(record, reader, associationData){ record[this.instanceName] = reader.read([associationData]).records[0]; } }); Ext.define('Ext.util.Inflector', { singleton: true, plurals: [ [(/(quiz)$/i), "$1zes" ], [(/^(ox)$/i), "$1en" ], [(/([m|l])ouse$/i), "$1ice" ], [(/(matr|vert|ind)ix|ex$/i), "$1ices" ], [(/(x|ch|ss|sh)$/i), "$1es" ], [(/([^aeiouy]|qu)y$/i), "$1ies" ], [(/(hive)$/i), "$1s" ], [(/(?:([^f])fe|([lr])f)$/i), "$1$2ves"], [(/sis$/i), "ses" ], [(/([ti])um$/i), "$1a" ], [(/(buffal|tomat|potat)o$/i), "$1oes" ], [(/(bu)s$/i), "$1ses" ], [(/(alias|status|sex)$/i), "$1es" ], [(/(octop|vir)us$/i), "$1i" ], [(/(ax|test)is$/i), "$1es" ], [(/^person$/), "people" ], [(/^man$/), "men" ], [(/^(child)$/), "$1ren" ], [(/s$/i), "s" ], [(/$/), "s" ] ], singulars: [ [(/(quiz)zes$/i), "$1" ], [(/(matr)ices$/i), "$1ix" ], [(/(vert|ind)ices$/i), "$1ex" ], [(/^(ox)en/i), "$1" ], [(/(alias|status)es$/i), "$1" ], [(/(octop|vir)i$/i), "$1us" ], [(/(cris|ax|test)es$/i), "$1is" ], [(/(shoe)s$/i), "$1" ], [(/(o)es$/i), "$1" ], [(/(bus)es$/i), "$1" ], [(/([m|l])ice$/i), "$1ouse" ], [(/(x|ch|ss|sh)es$/i), "$1" ], [(/(m)ovies$/i), "$1ovie" ], [(/(s)eries$/i), "$1eries"], [(/([^aeiouy]|qu)ies$/i), "$1y" ], [(/([lr])ves$/i), "$1f" ], [(/(tive)s$/i), "$1" ], [(/(hive)s$/i), "$1" ], [(/([^f])ves$/i), "$1fe" ], [(/(^analy)ses$/i), "$1sis" ], [(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i), "$1$2sis"], [(/([ti])a$/i), "$1um" ], [(/(n)ews$/i), "$1ews" ], [(/people$/i), "person" ], [(/s$/i), "" ] ], uncountable: [ "sheep", "fish", "series", "species", "money", "rice", "information", "equipment", "grass", "mud", "offspring", "deer", "means" ], singular: function(matcher, replacer) { this.singulars.unshift([matcher, replacer]); }, plural: function(matcher, replacer) { this.plurals.unshift([matcher, replacer]); }, clearSingulars: function() { this.singulars = []; }, clearPlurals: function() { this.plurals = []; }, isTransnumeral: function(word) { return Ext.Array.indexOf(this.uncountable, word) != -1; }, pluralize: function(word) { if (this.isTransnumeral(word)) { return word; } var plurals = this.plurals, length = plurals.length, tuple, regex, i; for (i = 0; i < length; i++) { tuple = plurals[i]; regex = tuple[0]; if (regex == word || (regex.test && regex.test(word))) { return word.replace(regex, tuple[1]); } } return word; }, singularize: function(word) { if (this.isTransnumeral(word)) { return word; } var singulars = this.singulars, length = singulars.length, tuple, regex, i; for (i = 0; i < length; i++) { tuple = singulars[i]; regex = tuple[0]; if (regex == word || (regex.test && regex.test(word))) { return word.replace(regex, tuple[1]); } } return word; }, classify: function(word) { return Ext.String.capitalize(this.singularize(word)); }, ordinalize: function(number) { var parsed = parseInt(number, 10), mod10 = parsed % 10, mod100 = parsed % 100; if (11 <= mod100 && mod100 <= 13) { return number + "th"; } else { switch(mod10) { case 1 : return number + "st"; case 2 : return number + "nd"; case 3 : return number + "rd"; default: return number + "th"; } } } }, function() { var irregulars = { alumnus: 'alumni', cactus : 'cacti', focus : 'foci', nucleus: 'nuclei', radius: 'radii', stimulus: 'stimuli', ellipsis: 'ellipses', paralysis: 'paralyses', oasis: 'oases', appendix: 'appendices', index: 'indexes', beau: 'beaux', bureau: 'bureaux', tableau: 'tableaux', woman: 'women', child: 'children', man: 'men', corpus: 'corpora', criterion: 'criteria', curriculum: 'curricula', genus: 'genera', memorandum: 'memoranda', phenomenon: 'phenomena', foot: 'feet', goose: 'geese', tooth: 'teeth', antenna: 'antennae', formula: 'formulae', nebula: 'nebulae', vertebra: 'vertebrae', vita: 'vitae' }, singular; for (singular in irregulars) { this.plural(singular, irregulars[singular]); this.singular(irregulars[singular], singular); } }); Ext.define('Ext.data.association.HasMany', { extend: Ext.data.association.Association , alternateClassName: 'Ext.data.HasManyAssociation', alias: 'association.hasmany', constructor: function(config) { var me = this, ownerProto, name; me.callParent(arguments); me.name = me.name || Ext.util.Inflector.pluralize(me.associatedName.toLowerCase()); ownerProto = me.ownerModel.prototype; name = me.name; Ext.applyIf(me, { storeName : name + "Store", foreignKey: me.ownerName.toLowerCase() + "_id" }); ownerProto[name] = me.createStore(); }, createStore: function() { var that = this, associatedModel = that.associatedModel, storeName = that.storeName, foreignKey = that.foreignKey, primaryKey = that.primaryKey, filterProperty = that.filterProperty, autoLoad = that.autoLoad, storeConfig = that.storeConfig || {}; return function() { var me = this, config, filter, modelDefaults = {}, id; if (me[storeName] === undefined) { id = me.get(primaryKey); if (filterProperty) { filter = { property : filterProperty, value : me.get(filterProperty), exactMatch: true }; } else if (me.hasId(id)) { filter = { property : foreignKey, value : id, exactMatch: true }; } modelDefaults[foreignKey] = me.get(primaryKey); config = Ext.apply({}, storeConfig, { model : associatedModel, filters : filter ? [filter] : undefined, remoteFilter : false, modelDefaults: modelDefaults, disableMetaChangeEvent: true }); me[storeName] = Ext.data.AbstractStore.create(config); if (autoLoad) { me[storeName].load(); } } return me[storeName]; }; }, read: function(record, reader, associationData){ var store = record[this.name](), inverse, items, iLen, i; store.add(reader.read(associationData).records); inverse = this.associatedModel.prototype.associations.findBy(function(assoc){ return assoc.type === 'belongsTo' && assoc.associatedName === record.$className; }); if (inverse) { items = store.data.items; iLen = items.length; for (i = 0; i < iLen; i++) { items[i][inverse.instanceName] = record; } } } }); Ext.define('Ext.data.association.HasOne', { extend: Ext.data.association.Association , alternateClassName: 'Ext.data.HasOneAssociation', alias: 'association.hasone', constructor: function(config) { this.callParent(arguments); var me = this, ownerProto = me.ownerModel.prototype, associatedName = me.associatedName, getterName = me.getterName || 'get' + associatedName, setterName = me.setterName || 'set' + associatedName; Ext.applyIf(me, { name : associatedName, foreignKey : associatedName.toLowerCase() + "_id", instanceName: associatedName + 'HasOneInstance', associationKey: associatedName.toLowerCase() }); ownerProto[getterName] = me.createGetter(); ownerProto[setterName] = me.createSetter(); }, createSetter: function() { var me = this, foreignKey = me.foreignKey, instanceName = me.instanceName; return function(value, options, scope) { var setByRecord = value && value.isModel, valueToSet = setByRecord ? value.getId() : value; if (setByRecord) { this[instanceName] = value; } else if (this[instanceName] instanceof Ext.data.Model && !this.isEqual(this.get(foreignKey), valueToSet)) { delete this[instanceName]; } this.set(foreignKey, valueToSet); if (Ext.isFunction(options)) { options = { callback: options, scope: scope || this }; } if (Ext.isObject(options)) { return this.save(options); } }; }, createGetter: function() { var me = this, ownerModel = me.ownerModel, associatedName = me.associatedName, associatedModel = me.associatedModel, foreignKey = me.foreignKey, primaryKey = me.primaryKey, instanceName = me.instanceName; return function(options, scope) { options = options || {}; var model = this, foreignKeyId = model.get(foreignKey), success, instance, args; if (options.reload === true || model[instanceName] === undefined) { instance = Ext.ModelManager.create({}, associatedName); instance.set(primaryKey, foreignKeyId); if (typeof options == 'function') { options = { callback: options, scope: scope || model }; } success = options.success; options.success = function(rec){ model[instanceName] = rec; if (success) { success.apply(this, arguments); } }; associatedModel.load(foreignKeyId, options); model[instanceName] = instance; return instance; } else { instance = model[instanceName]; args = [instance]; scope = scope || options.scope || model; Ext.callback(options, scope, args); Ext.callback(options.success, scope, args); Ext.callback(options.failure, scope, args); Ext.callback(options.callback, scope, args); return instance; } }; }, read: function(record, reader, associationData){ var inverse = this.associatedModel.prototype.associations.findBy(function(assoc){ return assoc.type === 'belongsTo' && assoc.associatedName === record.$className; }), newRecord = reader.read([associationData]).records[0]; record[this.instanceName] = newRecord; if (inverse) { newRecord[inverse.instanceName] = record; } } }); Ext.define('Ext.data.proxy.WebStorage', { extend: Ext.data.proxy.Client , alternateClassName: 'Ext.data.WebStorageProxy', id: undefined, constructor: function(config) { this.callParent(arguments); this.cache = {}; this.id = this.id || (this.store ? this.store.storeId : undefined); this.initialize(); }, create: function(operation, callback, scope) { var me = this, records = operation.records, length = records.length, ids = me.getIds(), id, record, i; operation.setStarted(); if(me.isHierarchical === undefined) { me.isHierarchical = !!records[0].isNode; if(me.isHierarchical) { me.getStorageObject().setItem(me.getTreeKey(), true); } } for (i = 0; i < length; i++) { record = records[i]; if (record.phantom) { record.phantom = false; id = me.getNextId(); } else { id = record.getId(); } me.setRecord(record, id); record.commit(); ids.push(id); } me.setIds(ids); operation.setCompleted(); operation.setSuccessful(); if (typeof callback == 'function') { callback.call(scope || me, operation); } }, read: function(operation, callback, scope) { var me = this, records = [], i = 0, success = true, Model = me.model, ids, length, record, data, id; operation.setStarted(); if(me.isHierarchical) { records = me.getTreeData(); } else { ids = me.getIds(); length = ids.length; id = operation.id; if (id) { data = me.getRecord(id); if (data !== null) { record = new Model(data, id, data); } if (record) { records.push(record); } else { success = false; } } else { for (; i < length; i++) { id = ids[i]; data = me.getRecord(id); records.push(new Model(data, id, data)); } } } if(success) { operation.setSuccessful(); } operation.setCompleted(); operation.resultSet = Ext.create('Ext.data.ResultSet', { records: records, total : records.length, loaded : true }); if (typeof callback == 'function') { callback.call(scope || me, operation); } }, update: function(operation, callback, scope) { var records = operation.records, length = records.length, ids = this.getIds(), record, id, i; operation.setStarted(); for (i = 0; i < length; i++) { record = records[i]; this.setRecord(record); record.commit(); id = record.getId(); if (id !== undefined && Ext.Array.indexOf(ids, id) == -1) { ids.push(id); } } this.setIds(ids); operation.setCompleted(); operation.setSuccessful(); if (typeof callback == 'function') { callback.call(scope || this, operation); } }, destroy: function(operation, callback, scope) { var me = this, records = operation.records, ids = me.getIds(), idLength = ids.length, newIds = [], removedHash = {}, i = records.length, id; operation.setStarted(); for (; i--;) { Ext.apply(removedHash, me.removeRecord(records[i])); } for(i = 0; i < idLength; i++) { id = ids[i]; if(!removedHash[id]) { newIds.push(id); } } me.setIds(newIds); operation.setCompleted(); operation.setSuccessful(); if (typeof callback == 'function') { callback.call(scope || me, operation); } }, getRecord: function(id) { var me = this, cache = me.cache, data = !cache[id] ? Ext.decode(me.getStorageObject().getItem(me.getRecordKey(id))) : cache[id]; if(!data) { return null; } cache[id] = data; data[me.model.prototype.idProperty] = id; return data; }, setRecord: function(record, id) { if (id) { record.setId(id); } else { id = record.getId(); } var me = this, rawData = record.data, data = {}, model = me.model, fields = model.prototype.fields.items, length = fields.length, i = 0, field, name, obj, key; for (; i < length; i++) { field = fields[i]; name = field.name; if(field.persist) { data[name] = rawData[name]; } } delete data[me.model.prototype.idProperty]; if(record.isNode && record.get('depth') === 1) { delete data.parentId; } obj = me.getStorageObject(); key = me.getRecordKey(id); me.cache[id] = data; obj.removeItem(key); obj.setItem(key, Ext.encode(data)); }, removeRecord: function(record) { var me = this, id = record.getId(), records = {}, i, childNodes; records[id] = record; me.getStorageObject().removeItem(me.getRecordKey(id)); delete me.cache[id]; if(record.childNodes) { childNodes = record.childNodes; for(i = childNodes.length; i--;) { Ext.apply(records, me.removeRecord(childNodes[i])); } } return records; }, getRecordKey: function(id) { if (id.isModel) { id = id.getId(); } return Ext.String.format("{0}-{1}", this.id, id); }, getRecordCounterKey: function() { return Ext.String.format("{0}-counter", this.id); }, getTreeKey: function() { return Ext.String.format("{0}-tree", this.id); }, getIds: function() { var me = this, ids = (me.getStorageObject().getItem(me.id) || "").split(","), model = me.model, length = ids.length, isString = model.prototype.fields.get(model.prototype.idProperty).type.type === 'string', i; if (length == 1 && ids[0] === "") { ids = []; } else { for (i = 0; i < length; i++) { ids[i] = isString ? ids[i] : +ids[i]; } } return ids; }, setIds: function(ids) { var obj = this.getStorageObject(), str = ids.join(","); obj.removeItem(this.id); if (!Ext.isEmpty(str)) { obj.setItem(this.id, str); } }, getNextId: function() { var me = this, obj = me.getStorageObject(), key = me.getRecordCounterKey(), model = me.model, isString = model.prototype.fields.get(model.prototype.idProperty).type.type === 'string', id; id = me.idGenerator.generate(); obj.setItem(key, id); if(!isString) { id = +id; } return id; }, getTreeData: function() { var me = this, ids = me.getIds(), length = ids.length, records = [], recordHash = {}, root = [], i = 0, Model = me.model, idProperty = Model.prototype.idProperty, rootLength, record, parent, parentId, children, id; for(; i < length; i++) { id = ids[i]; record = me.getRecord(id); records.push(record); recordHash[id] = record; if(!record.parentId) { root.push(record); } } rootLength = root.length; Ext.Array.sort(records, me.sortByParentId); for(i = rootLength; i < length; i++) { record = records[i]; parentId = record.parentId; if(!parent || parent[idProperty] !== parentId) { parent = recordHash[parentId]; parent.children = children = []; } children.push(record); } for(i = length; i--;) { record = records[i]; if(!record.children && !record.leaf) { record.loaded = true; } } for(i = rootLength; i--;) { record = root[i]; root[i] = new Model(record, record[idProperty], record); } return root; }, sortByParentId: function(node1, node2) { return (node1.parentId || 0) - (node2.parentId || 0); }, initialize: function() { var me = this, storageObject = me.getStorageObject(), lastId = +storageObject.getItem(me.getRecordCounterKey()); storageObject.setItem(me.id, storageObject.getItem(me.id) || ""); if(storageObject.getItem(me.getTreeKey())) { me.isHierarchical = true; } me.idGenerator = new Ext.data.SequentialIdGenerator({ seed: lastId ? lastId + 1 : 1 }); }, clear: function() { var me = this, obj = me.getStorageObject(), ids = me.getIds(), len = ids.length, i; for (i = 0; i < len; i++) { obj.removeItem(me.getRecordKey(ids[i])); } obj.removeItem(me.getRecordCounterKey()); obj.removeItem(me.getTreeKey()); obj.removeItem(me.id); me.cache = {}; }, getStorageObject: function() { } }); Ext.define('Ext.data.proxy.LocalStorage', { extend: Ext.data.proxy.WebStorage , alias: 'proxy.localstorage', alternateClassName: 'Ext.data.LocalStorageProxy', getStorageObject: function() { return window.localStorage; } }); Ext.define('Ext.data.proxy.Rest', { extend: Ext.data.proxy.Ajax , alternateClassName: 'Ext.data.RestProxy', alias : 'proxy.rest', actionMethods: { create : 'POST', read : 'GET', update : 'PUT', destroy: 'DELETE' }, defaultActionMethods: { create : 'POST', read : 'GET', update : 'PUT', destroy: 'DELETE' }, appendId: true, batchActions: false, buildUrl: function(request) { var me = this, operation = request.operation, records = operation.records || [], record = records[0], format = me.format, url = me.getUrl(request), id = record ? record.getId() : operation.id; if (me.appendId && me.isValidId(id)) { if (!url.match(/\/$/)) { url += '/'; } url += id; } if (format) { if (!url.match(/\.$/)) { url += '.'; } url += format; } request.url = url; return me.callParent(arguments); }, isValidId: function(id) { return id || id === 0; } }); Ext.define('Ext.data.proxy.SessionStorage', { extend: Ext.data.proxy.WebStorage , alias: 'proxy.sessionstorage', alternateClassName: 'Ext.data.SessionStorageProxy', getStorageObject: function() { return window.sessionStorage; } }); Ext.define('Ext.dd.DDTarget', { extend: Ext.dd.DragDrop , constructor: function(id, sGroup, config) { if (id) { this.initTarget(id, sGroup, config); } }, getDragEl: Ext.emptyFn, isValidHandleChild: Ext.emptyFn, startDrag: Ext.emptyFn, endDrag: Ext.emptyFn, onDrag: Ext.emptyFn, onDragDrop: Ext.emptyFn, onDragEnter: Ext.emptyFn, onDragOut: Ext.emptyFn, onDragOver: Ext.emptyFn, onInvalidDrop: Ext.emptyFn, onMouseDown: Ext.emptyFn, onMouseUp: Ext.emptyFn, setXConstraint: Ext.emptyFn, setYConstraint: Ext.emptyFn, resetConstraints: Ext.emptyFn, clearConstraints: Ext.emptyFn, clearTicks: Ext.emptyFn, setInitPosition: Ext.emptyFn, setDragElId: Ext.emptyFn, setHandleElId: Ext.emptyFn, setOuterHandleElId: Ext.emptyFn, addInvalidHandleClass: Ext.emptyFn, addInvalidHandleId: Ext.emptyFn, addInvalidHandleType: Ext.emptyFn, removeInvalidHandleClass: Ext.emptyFn, removeInvalidHandleId: Ext.emptyFn, removeInvalidHandleType: Ext.emptyFn, toString: function() { return ("DDTarget " + this.id); } }); Ext.define('Ext.dd.DragTracker', { mixins: { observable: Ext.util.Observable }, active: false, trackOver: false, tolerance: 5, autoStart: false, constructor : function(config){ var me = this; Ext.apply(me, config); me.addEvents( 'mouseover', 'mouseout', 'mousedown', 'mouseup', 'mousemove', 'beforedragstart', 'dragstart', 'dragend', 'drag' ); me.dragRegion = new Ext.util.Region(0,0,0,0); if (me.el) { me.initEl(me.el); } me.mixins.observable.constructor.call(me); if (me.disabled) { me.disable(); } }, initEl: function(el) { var me = this; me.el = Ext.get(el); me.handle = Ext.get(me.delegate); me.delegate = me.handle ? undefined : me.delegate; if (!me.handle) { me.handle = me.el; } me.handleListeners = { scope: me, delegate: me.delegate, mousedown: me.onMouseDown }; if (me.trackOver || me.overCls) { Ext.apply(me.handleListeners, { mouseover: me.onMouseOver, mouseout: me.onMouseOut }); } me.mon(me.handle, me.handleListeners); }, disable: function() { this.disabled = true; }, enable: function() { this.disabled = false; }, destroy : function() { var me = this; if (me.active) { me.endDrag({}); } me.clearListeners(); me.mun(me.handle, me.handleListeners); me.el = me.handle = null; }, onMouseOver: function(e, target) { var me = this; if (!me.disabled) { if (Ext.EventManager.contains(e) || me.delegate) { me.mouseIsOut = false; if (me.overCls) { me.el.addCls(me.overCls); } me.fireEvent('mouseover', me, e, me.delegate ? e.getTarget(me.delegate, target) : me.handle); } } }, onMouseOut: function(e) { var me = this; if (me.mouseIsDown) { me.mouseIsOut = true; } else { if (me.overCls) { me.el.removeCls(me.overCls); } me.fireEvent('mouseout', me, e); } }, onMouseDown: function(e, target){ var me = this, el; if (me.disabled ||e.dragTracked) { return; } me.dragTarget = me.delegate ? target : me.handle.dom; me.startXY = me.lastXY = e.getXY(); me.startRegion = Ext.fly(me.dragTarget).getRegion(); if (me.fireEvent('mousedown', me, e) === false || me.fireEvent('beforedragstart', me, e) === false || me.onBeforeStart(e) === false) { return; } me.mouseIsDown = true; e.dragTracked = true; el = me.el.dom; if (Ext.isIE && el.setCapture) { el.setCapture(); } if (me.preventDefault !== false) { e.preventDefault(); } Ext.getDoc().on({ scope: me, mouseup: me.onMouseUp, mousemove: me.onMouseMove, selectstart: me.stopSelect }); if (me.autoStart) { me.timer = Ext.defer(me.triggerStart, me.autoStart === true ? 1000 : me.autoStart, me, [e]); } }, onMouseMove: function(e, target){ var me = this, xy = e.getXY(), s = me.startXY; e.preventDefault(); me.lastXY = xy; if (!me.active) { if (Math.max(Math.abs(s[0]-xy[0]), Math.abs(s[1]-xy[1])) > me.tolerance) { me.triggerStart(e); } else { return; } } if (me.fireEvent('mousemove', me, e) === false) { me.onMouseUp(e); } else { me.onDrag(e); me.fireEvent('drag', me, e); } }, onMouseUp: function(e) { var me = this; me.mouseIsDown = false; if (me.mouseIsOut) { me.mouseIsOut = false; me.onMouseOut(e); } e.preventDefault(); if (Ext.isIE && document.releaseCapture) { document.releaseCapture(); } me.fireEvent('mouseup', me, e); me.endDrag(e); }, endDrag: function(e) { var me = this, wasActive = me.active; Ext.getDoc().un({ mousemove: me.onMouseMove, mouseup: me.onMouseUp, selectstart: me.stopSelect, scope: me }); me.clearStart(); me.active = false; if (wasActive) { me.onEnd(e); me.fireEvent('dragend', me, e); } me._constrainRegion = Ext.EventObject.dragTracked = null }, triggerStart: function(e) { var me = this; me.clearStart(); me.active = true; me.onStart(e); me.fireEvent('dragstart', me, e); }, clearStart : function() { var timer = this.timer; if (timer) { clearTimeout(timer); this.timer = null; } }, stopSelect : function(e) { e.stopEvent(); return false; }, onBeforeStart : function(e) { }, onStart : function(xy) { }, onDrag : function(e) { }, onEnd : function(e) { }, getDragTarget : function(){ return this.dragTarget; }, getDragCt : function(){ return this.el; }, getConstrainRegion: function() { var me = this; if (me.constrainTo) { if (me.constrainTo instanceof Ext.util.Region) { return me.constrainTo; } if (!me._constrainRegion) { me._constrainRegion = Ext.fly(me.constrainTo).getViewRegion(); } } else { if (!me._constrainRegion) { me._constrainRegion = me.getDragCt().getViewRegion(); } } return me._constrainRegion; }, getXY : function(constrain){ return constrain ? this.constrainModes[constrain](this, this.lastXY) : this.lastXY; }, getOffset : function(constrain){ var xy = this.getXY(constrain), s = this.startXY; return [xy[0]-s[0], xy[1]-s[1]]; }, constrainModes: { point: function(me, xy) { var dr = me.dragRegion, constrainTo = me.getConstrainRegion(); if (!constrainTo) { return xy; } dr.x = dr.left = dr[0] = dr.right = xy[0]; dr.y = dr.top = dr[1] = dr.bottom = xy[1]; dr.constrainTo(constrainTo); return [dr.left, dr.top]; }, dragTarget: function(me, xy) { var s = me.startXY, dr = me.startRegion.copy(), constrainTo = me.getConstrainRegion(), adjust; if (!constrainTo) { return xy; } dr.translateBy(xy[0]-s[0], xy[1]-s[1]); if (dr.right > constrainTo.right) { xy[0] += adjust = (constrainTo.right - dr.right); dr.left += adjust; } if (dr.left < constrainTo.left) { xy[0] += (constrainTo.left - dr.left); } if (dr.bottom > constrainTo.bottom) { xy[1] += adjust = (constrainTo.bottom - dr.bottom); dr.top += adjust; } if (dr.top < constrainTo.top) { xy[1] += (constrainTo.top - dr.top); } return xy; } } }); Ext.define('Ext.dd.DragZone', { extend: Ext.dd.DragSource , constructor : function(el, config){ var me = this, scroll = me.containerScroll; me.callParent([el, config]); if (scroll) { el = me.scrollEl || el; el = Ext.get(el); if (Ext.isObject(scroll)) { el.ddScrollConfig = scroll; } Ext.dd.ScrollManager.register(el); } }, getDragData : function(e){ return Ext.dd.Registry.getHandleFromEvent(e); }, onInitDrag : function(x, y){ this.proxy.update(this.dragData.ddel.cloneNode(true)); this.onStartDrag(x, y); return true; }, getRepairXY : function(e){ return Ext.fly(this.dragData.ddel).getXY(); }, destroy : function(){ this.callParent(); if (this.containerScroll) { Ext.dd.ScrollManager.unregister(this.scrollEl || this.el); } } }); Ext.define('Ext.dd.ScrollManager', { singleton: true, constructor: function() { var ddm = Ext.dd.DragDropManager; ddm.fireEvents = Ext.Function.createSequence(ddm.fireEvents, this.onFire, this); ddm.stopDrag = Ext.Function.createSequence(ddm.stopDrag, this.onStop, this); this.doScroll = Ext.Function.bind(this.doScroll, this); this.ddmInstance = ddm; this.els = {}; this.dragEl = null; this.proc = {}; }, onStop: function(e){ var sm = Ext.dd.ScrollManager; sm.dragEl = null; sm.clearProc(); }, triggerRefresh: function() { if (this.ddmInstance.dragCurrent) { this.ddmInstance.refreshCache(this.ddmInstance.dragCurrent.groups); } }, doScroll: function() { if (this.ddmInstance.dragCurrent) { var proc = this.proc, procEl = proc.el, ddScrollConfig = proc.el.ddScrollConfig, inc = ddScrollConfig && ddScrollConfig.increment ? ddScrollConfig.increment : this.increment, animate = ddScrollConfig && 'animate' in ddScrollConfig ? ddScrollConfig.animate : this.animate; if (!animate) { if (procEl.scroll(proc.dir, inc)) { this.triggerRefresh(); } } else { procEl.scroll(proc.dir, inc, true, this.animDuration, this.triggerRefresh); } } }, clearProc: function() { var proc = this.proc; if (proc.id) { clearInterval(proc.id); } proc.id = 0; proc.el = null; proc.dir = ""; }, startProc: function(el, dir) { this.clearProc(); this.proc.el = el; this.proc.dir = dir; var group = el.ddScrollConfig ? el.ddScrollConfig.ddGroup : undefined, freq = (el.ddScrollConfig && el.ddScrollConfig.frequency) ? el.ddScrollConfig.frequency : this.frequency; if (group === undefined || this.ddmInstance.dragCurrent.ddGroup == group) { this.proc.id = setInterval(this.doScroll, freq); } }, onFire: function(e, isDrop) { if (isDrop || !this.ddmInstance.dragCurrent) { return; } if (!this.dragEl || this.dragEl != this.ddmInstance.dragCurrent) { this.dragEl = this.ddmInstance.dragCurrent; this.refreshCache(); } var pt = e.getPoint(), proc = this.proc, els = this.els, id, el, r, c; for (id in els) { el = els[id]; r = el._region; c = el.ddScrollConfig ? el.ddScrollConfig : this; if (r && r.contains(pt) && el.isScrollable()) { if (r.bottom - pt.y <= c.vthresh) { if(proc.el != el){ this.startProc(el, "down"); } return; }else if (r.right - pt.x <= c.hthresh) { if (proc.el != el) { this.startProc(el, "right"); } return; } else if(pt.y - r.top <= c.vthresh) { if (proc.el != el) { this.startProc(el, "up"); } return; } else if(pt.x - r.left <= c.hthresh) { if (proc.el != el) { this.startProc(el, "left"); } return; } } } this.clearProc(); }, register : function(el){ if (Ext.isArray(el)) { for(var i = 0, len = el.length; i < len; i++) { this.register(el[i]); } } else { el = Ext.get(el); this.els[el.id] = el; } }, unregister : function(el){ if(Ext.isArray(el)){ for (var i = 0, len = el.length; i < len; i++) { this.unregister(el[i]); } }else{ el = Ext.get(el); delete this.els[el.id]; } }, vthresh : 25, hthresh : 25, increment : 100, frequency : 500, animate: true, animDuration: 0.4, ddGroup: undefined, refreshCache : function(){ var els = this.els, id; for (id in els) { if(typeof els[id] == 'object'){ els[id]._region = els[id].getRegion(); } } } }); Ext.define('Ext.dd.DropTarget', { extend: Ext.dd.DDTarget , constructor : function(el, config){ this.el = Ext.get(el); Ext.apply(this, config); if(this.containerScroll){ Ext.dd.ScrollManager.register(this.el); } this.callParent([this.el.dom, this.ddGroup || this.group, {isTarget: true}]); }, dropAllowed : Ext.baseCSSPrefix + 'dd-drop-ok', dropNotAllowed : Ext.baseCSSPrefix + 'dd-drop-nodrop', isTarget : true, isNotifyTarget : true, notifyEnter : function(dd, e, data){ if(this.overClass){ this.el.addCls(this.overClass); } return this.dropAllowed; }, notifyOver : function(dd, e, data){ return this.dropAllowed; }, notifyOut : function(dd, e, data){ if(this.overClass){ this.el.removeCls(this.overClass); } }, notifyDrop : function(dd, e, data){ return false; }, destroy : function(){ this.callParent(); if(this.containerScroll){ Ext.dd.ScrollManager.unregister(this.el); } } }); Ext.define('Ext.dd.Registry', { singleton: true, constructor: function() { this.elements = {}; this.handles = {}; this.autoIdSeed = 0; }, getId: function(el, autogen){ if(typeof el == "string"){ return el; } var id = el.id; if(!id && autogen !== false){ id = "extdd-" + (++this.autoIdSeed); el.id = id; } return id; }, register : function(el, data){ data = data || {}; if (typeof el == "string") { el = document.getElementById(el); } data.ddel = el; this.elements[this.getId(el)] = data; if (data.isHandle !== false) { this.handles[data.ddel.id] = data; } if (data.handles) { var hs = data.handles, i, len; for (i = 0, len = hs.length; i < len; i++) { this.handles[this.getId(hs[i])] = data; } } }, unregister : function(el){ var id = this.getId(el, false), data = this.elements[id], hs, i, len; if(data){ delete this.elements[id]; if(data.handles){ hs = data.handles; for (i = 0, len = hs.length; i < len; i++) { delete this.handles[this.getId(hs[i], false)]; } } } }, getHandle : function(id){ if(typeof id != "string"){ id = id.id; } return this.handles[id]; }, getHandleFromEvent : function(e){ var t = e.getTarget(); return t ? this.handles[t.id] : null; }, getTarget : function(id){ if(typeof id != "string"){ id = id.id; } return this.elements[id]; }, getTargetFromEvent : function(e){ var t = e.getTarget(); return t ? this.elements[t.id] || this.handles[t.id] : null; } }); Ext.define('Ext.dd.DropZone', { extend: Ext.dd.DropTarget , getTargetFromEvent : function(e){ return Ext.dd.Registry.getTargetFromEvent(e); }, onNodeEnter : function(n, dd, e, data){ }, onNodeOver : function(n, dd, e, data){ return this.dropAllowed; }, onNodeOut : function(n, dd, e, data){ }, onNodeDrop : function(n, dd, e, data){ return false; }, onContainerOver : function(dd, e, data){ return this.dropNotAllowed; }, onContainerDrop : function(dd, e, data){ return false; }, notifyEnter : function(dd, e, data){ return this.dropNotAllowed; }, notifyOver : function(dd, e, data){ var n = this.getTargetFromEvent(e); if(!n) { if(this.lastOverNode){ this.onNodeOut(this.lastOverNode, dd, e, data); this.lastOverNode = null; } return this.onContainerOver(dd, e, data); } if(this.lastOverNode != n){ if(this.lastOverNode){ this.onNodeOut(this.lastOverNode, dd, e, data); } this.onNodeEnter(n, dd, e, data); this.lastOverNode = n; } return this.onNodeOver(n, dd, e, data); }, notifyOut : function(dd, e, data){ if(this.lastOverNode){ this.onNodeOut(this.lastOverNode, dd, e, data); this.lastOverNode = null; } }, notifyDrop : function(dd, e, data){ var me = this, n = me.getTargetFromEvent(e), result = n ? me.onNodeDrop(n, dd, e, data) : me.onContainerDrop(dd, e, data); if (me.lastOverNode) { me.onNodeOut(me.lastOverNode, dd, e, data); me.lastOverNode = null; } return result; }, triggerCacheRefresh : function() { Ext.dd.DDM.refreshCache(this.groups); } }); Ext.define('Ext.direct.Event', { alias: 'direct.event', status: true, constructor: function(config) { Ext.apply(this, config); }, getName: function() { return this.name; }, getData: function() { return this.data; } }); Ext.define('Ext.direct.RemotingEvent', { extend: Ext.direct.Event , alias: 'direct.rpc', getTransaction: function() { var me = this; return me.transaction || Ext.direct.Manager.getTransaction(me.tid); } }); Ext.define('Ext.direct.ExceptionEvent', { extend: Ext.direct.RemotingEvent , alias: 'direct.exception', status: false }); Ext.define('Ext.direct.JsonProvider', { extend: Ext.direct.Provider , alias: 'direct.jsonprovider', parseResponse: function(response) { if (!Ext.isEmpty(response.responseText)) { if (Ext.isObject(response.responseText)) { return response.responseText; } return Ext.decode(response.responseText); } return null; }, createEvents: function(response) { var me = this, data = null, events = [], event, i, len; try { data = me.parseResponse(response); } catch (e) { event = new Ext.direct.ExceptionEvent({ data: e, xhr: response, code: Ext.direct.Manager.exceptions.PARSE, message: 'Error parsing json response: \n\n ' + e }); return [event]; } if (Ext.isArray(data)) { for (i = 0, len = data.length; i < len; ++i) { events.push(me.createEvent(data[i])); } } else if (Ext.isObject(data)) { events.push(me.createEvent(data)); } return events; }, createEvent: function(response) { if (typeof response !== 'object'|| !('type' in response)) { return new Ext.direct.ExceptionEvent({ data: response, code: Ext.direct.Manager.exceptions.DATA, message: 'Invalid data: event type is not specified' }); } return Ext.create('direct.' + response.type, response); } }); Ext.define('Ext.direct.PollingProvider', { extend: Ext.direct.JsonProvider , alias: 'direct.pollingprovider', interval: 3000, constructor: function(config) { var me = this; me.callParent(arguments); me.addEvents( 'beforepoll', 'poll' ); }, isConnected: function() { return !!this.pollTask; }, connect: function() { var me = this, url = me.url; if (url && !me.pollTask) { me.pollTask = Ext.TaskManager.start({ run: me.runPoll, interval: me.interval, scope: me }); me.fireEvent('connect', me); } }, disconnect: function() { var me = this; if (me.pollTask) { Ext.TaskManager.stop(me.pollTask); delete me.pollTask; me.fireEvent('disconnect', me); } }, runPoll: function() { var me = this, url = me.url; if (me.fireEvent('beforepoll', me) !== false) { if (Ext.isFunction(url)) { url(me.baseParams); } else { Ext.Ajax.request({ url: url, callback: me.onData, scope: me, params: me.baseParams }); } me.fireEvent('poll', me); } }, onData: function(opt, success, response) { var me = this, i, len, events; if (success) { events = me.createEvents(response); for (i = 0, len = events.length; i < len; ++i) { me.fireEvent('data', me, events[i]); } } else { events = new Ext.direct.ExceptionEvent({ data: null, code: Ext.direct.Manager.exceptions.TRANSPORT, message: 'Unable to connect to the server.', xhr: response }); me.fireEvent('data', me, events); } } }); Ext.define('Ext.direct.RemotingMethod', { constructor: function(config) { var me = this, params = Ext.isDefined(config.params) ? config.params : config.len, name, pLen, p, param; me.name = config.name; me.formHandler = config.formHandler; if (Ext.isNumeric(params)) { me.len = params; me.ordered = true; } else { me.params = {}; pLen = params.length; for (p = 0; p < pLen; p++) { param = params[p]; name = Ext.isObject(param) ? param.name : param; me.params[name] = true; } } }, getArgs: function(params, paramOrder, paramsAsHash) { var me = this, args = [], i, len; if (me.ordered) { if (me.len > 0) { if (paramOrder) { for (i = 0, len = paramOrder.length; i < len; i++) { args.push(params[paramOrder[i]]); } } else if (paramsAsHash) { args.push(params); } } } else { args.push(params); } return args; }, getCallData: function(args) { var me = this, data = null, len = me.len, params = me.params, callback, scope, name, options; if (me.ordered) { callback = args[len]; scope = args[len + 1]; options = args[len + 2]; if (len !== 0) { data = args.slice(0, len); } } else { data = Ext.apply({}, args[0]); callback = args[1]; scope = args[2]; options = args[3]; for (name in data) { if (data.hasOwnProperty(name) && !params[name]) { delete data[name]; } } } return { data: data, callback: callback, scope: scope, options: options }; } }); Ext.define('Ext.direct.Transaction', { alias: 'direct.transaction', alternateClassName: 'Ext.Direct.Transaction', statics: { TRANSACTION_ID: 0 }, constructor: function(config) { var me = this; Ext.apply(me, config); me.id = me.tid = ++me.self.TRANSACTION_ID; me.retryCount = 0; }, send: function() { var me = this; me.provider.queueTransaction(me); }, retry: function() { var me = this; me.retryCount++; me.send(); }, getProvider: function() { return this.provider; } }); Ext.define('Ext.direct.RemotingProvider', { extend: Ext.direct.JsonProvider , alias: 'direct.remotingprovider', enableBuffer: 10, maxRetries: 1, constructor: function(config) { var me = this; me.callParent(arguments); me.addEvents( 'beforecall', 'call', 'beforecallback' ); me.namespace = (Ext.isString(me.namespace)) ? Ext.ns(me.namespace) : me.namespace || Ext.global; me.transactions = new Ext.util.MixedCollection(); me.callBuffer = []; }, getNamespace: function(root, action) { var parts, ns, i, l; root = root || Ext.global; parts = action.toString().split('.'); for (i = 0, l = parts.length; i < l; i++) { ns = parts[i]; root = root[ns]; if (typeof root === 'undefined') { return root; } } return root; }, createNamespaces: function(root, action) { var parts, ns; root = root || Ext.global; parts = action.toString().split('.'); for ( var i = 0, l = parts.length; i < l; i++ ) { ns = parts[i]; root[ns] = root[ns] || {}; root = root[ns]; }; return root; }, initAPI: function() { var me = this, actions = me.actions, namespace = me.namespace, action, cls, methods, i, len, method; for (action in actions) { if (actions.hasOwnProperty(action)) { if (me.disableNestedActions) { cls = namespace[action]; if (!cls) { cls = namespace[action] = {}; } } else { cls = me.getNamespace(namespace, action); if (!cls) { cls = me.createNamespaces(namespace, action); } } methods = actions[action]; for (i = 0, len = methods.length; i < len; ++i) { method = new Ext.direct.RemotingMethod(methods[i]); cls[method.name] = me.createHandler(action, method); } } } }, createHandler: function(action, method) { var me = this, slice = Array.prototype.slice, handler; if (!method.formHandler) { handler = function() { me.configureRequest(action, method, slice.call(arguments, 0)); }; } else { handler = function(form, callback, scope) { me.configureFormRequest(action, method, form, callback, scope); }; } handler.directCfg = { action: action, method: method }; return handler; }, isConnected: function() { return !!this.connected; }, connect: function() { var me = this; if (me.url) { me.initAPI(); me.connected = true; me.fireEvent('connect', me); } }, disconnect: function() { var me = this; if (me.connected) { me.connected = false; me.fireEvent('disconnect', me); } }, runCallback: function(transaction, event) { var success = !!event.status, funcName = success ? 'success' : 'failure', callback, options, result; if (transaction && transaction.callback) { callback = transaction.callback; options = transaction.callbackOptions; result = typeof event.result !== 'undefined' ? event.result : event.data; if (Ext.isFunction(callback)) { callback(result, event, success, options); } else { Ext.callback(callback[funcName], callback.scope, [result, event, success, options]); Ext.callback(callback.callback, callback.scope, [result, event, success, options]); } } }, onData: function(options, success, response) { var me = this, i, len, events, event, transaction, transactions; if (success) { events = me.createEvents(response); for (i = 0, len = events.length; i < len; ++i) { event = events[i]; transaction = me.getTransaction(event); me.fireEvent('data', me, event); if (transaction && me.fireEvent('beforecallback', me, event, transaction) !== false) { me.runCallback(transaction, event, true); Ext.direct.Manager.removeTransaction(transaction); } } } else { transactions = [].concat(options.transaction); for (i = 0, len = transactions.length; i < len; ++i) { transaction = me.getTransaction(transactions[i]); if (transaction && transaction.retryCount < me.maxRetries) { transaction.retry(); } else { event = new Ext.direct.ExceptionEvent({ data: null, transaction: transaction, code: Ext.direct.Manager.exceptions.TRANSPORT, message: 'Unable to connect to the server.', xhr: response }); me.fireEvent('data', me, event); if (transaction && me.fireEvent('beforecallback', me, transaction) !== false) { me.runCallback(transaction, event, false); Ext.direct.Manager.removeTransaction(transaction); } } } } }, getTransaction: function(options) { return options && options.tid ? Ext.direct.Manager.getTransaction(options.tid) : null; }, configureRequest: function(action, method, args) { var me = this, callData, data, callback, scope, opts, transaction, params; callData = method.getCallData(args); data = callData.data; callback = callData.callback; scope = callData.scope; opts = callData.options || {}; params = Ext.apply({}, { provider: me, args: args, action: action, method: method.name, data: data, callbackOptions: opts, callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback }); if (opts.timeout) { Ext.applyIf(params, { timeout: opts.timeout }); }; transaction = new Ext.direct.Transaction(params); if (me.fireEvent('beforecall', me, transaction, method) !== false) { Ext.direct.Manager.addTransaction(transaction); me.queueTransaction(transaction); me.fireEvent('call', me, transaction, method); } }, getCallData: function(transaction) { return { action: transaction.action, method: transaction.method, data: transaction.data, type: 'rpc', tid: transaction.id }; }, sendRequest: function(data) { var me = this, request, callData, params, enableUrlEncode = me.enableUrlEncode, i, len; request = { url: me.url, callback: me.onData, scope: me, transaction: data, timeout: me.timeout }; if (data.timeout) { request.timeout = data.timeout; } if (Ext.isArray(data)) { callData = []; for (i = 0, len = data.length; i < len; ++i) { callData.push(me.getCallData(data[i])); } } else { callData = me.getCallData(data); } if (enableUrlEncode) { params = {}; params[Ext.isString(enableUrlEncode) ? enableUrlEncode : 'data'] = Ext.encode(callData); request.params = params; } else { request.jsonData = callData; } Ext.Ajax.request(request); }, queueTransaction: function(transaction) { var me = this, enableBuffer = me.enableBuffer; if (transaction.form) { me.sendFormRequest(transaction); return; } if (enableBuffer === false || typeof transaction.timeout !== 'undefined') { me.sendRequest(transaction); return; } me.callBuffer.push(transaction); if (enableBuffer) { if (!me.callTask) { me.callTask = new Ext.util.DelayedTask(me.combineAndSend, me); } me.callTask.delay(Ext.isNumber(enableBuffer) ? enableBuffer : 10); } else { me.combineAndSend(); } }, combineAndSend : function() { var me = this, buffer = me.callBuffer, len = buffer.length; if (len > 0) { me.sendRequest(len == 1 ? buffer[0] : buffer); me.callBuffer = []; } }, configureFormRequest: function(action, method, form, callback, scope) { var me = this, transaction, isUpload, params; transaction = new Ext.direct.Transaction({ provider: me, action: action, method: method.name, args: [form, callback, scope], callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback, isForm: true }); if (me.fireEvent('beforecall', me, transaction, method) !== false) { Ext.direct.Manager.addTransaction(transaction); isUpload = String(form.getAttribute("enctype")).toLowerCase() == 'multipart/form-data'; params = { extTID: transaction.id, extAction: action, extMethod: method.name, extType: 'rpc', extUpload: String(isUpload) }; Ext.apply(transaction, { form: Ext.getDom(form), isUpload: isUpload, params: callback && Ext.isObject(callback.params) ? Ext.apply(params, callback.params) : params }); me.fireEvent('call', me, transaction, method); me.sendFormRequest(transaction); } }, sendFormRequest: function(transaction) { var me = this; Ext.Ajax.request({ url: me.url, params: transaction.params, callback: me.onData, scope: me, form: transaction.form, isUpload: transaction.isUpload, transaction: transaction }); } }); Ext.define('Ext.dom.Layer', { extend: Ext.Element , alternateClassName: 'Ext.Layer', statics: { shims: [] }, isLayer: true, localXYNames: { get: 'getLocalXY', set: 'setLocalXY' }, constructor: function(config, existingEl) { config = config || {}; var me = this, dh = Ext.DomHelper, cp = config.parentEl, pel = cp ? Ext.getDom(cp) : document.body, hm = config.hideMode, cls = Ext.baseCSSPrefix + (config.fixed && !(Ext.isIE6 || Ext.isIEQuirks) ? 'fixed-layer' : 'layer'); me.el = me; if (existingEl) { me.dom = Ext.getDom(existingEl); } if (!me.dom) { me.dom = dh.append(pel, config.dh || { tag: 'div', cls: cls }); } else { me.addCls(cls); if (!me.dom.parentNode) { pel.appendChild(me.dom); } } if (config.preventSync) { me.preventSync = true; } if (config.id) { me.id = me.dom.id = config.id; } else { me.id = Ext.id(me.dom); } Ext.Element.addToCache(me); if (config.cls) { me.addCls(config.cls); } me.constrain = config.constrain !== false; if (hm) { me.setVisibilityMode(Ext.Element[hm.toUpperCase()]); if (me.visibilityMode == Ext.Element.ASCLASS) { me.visibilityCls = config.visibilityCls; } } else if (config.useDisplay) { me.setVisibilityMode(Ext.Element.DISPLAY); } else { me.setVisibilityMode(Ext.Element.VISIBILITY); } if (config.shadow) { me.shadowOffset = config.shadowOffset || 4; me.shadow = new Ext.Shadow({ offset: me.shadowOffset, mode: config.shadow, fixed: config.fixed }); me.disableShadow(); } else { me.shadowOffset = 0; } me.useShim = config.shim !== false && Ext.useShims; if (config.hidden === true) { me.hide(); } else if (config.hidden === false) { me.show(); } }, getZIndex: function() { return parseInt((this.getShim() || this).getStyle('z-index'), 10); }, getShim: function() { var me = this, shim, pn; if (!me.useShim) { return null; } if (!me.shim) { shim = me.self.shims.shift(); if (!shim) { shim = me.createShim(); shim.enableDisplayMode('block'); shim.hide(); } pn = me.dom.parentNode; if (shim.dom.parentNode != pn) { pn.insertBefore(shim.dom, me.dom); } me.shim = shim; } return me.shim; }, hideShim: function() { var me = this; if (me.shim) { me.shim.setDisplayed(false); me.self.shims.push(me.shim); delete me.shim; } }, disableShadow: function() { var me = this; if (me.shadow && !me.shadowDisabled) { me.shadowDisabled = true; me.shadow.hide(); me.lastShadowOffset = me.shadowOffset; me.shadowOffset = 0; } }, enableShadow: function(show) { var me = this; if (me.shadow && me.shadowDisabled) { me.shadowDisabled = false; me.shadowOffset = me.lastShadowOffset; delete me.lastShadowOffset; if (show) { me.sync(true); } } }, sync: function(doShow) { var me = this, shadow = me.shadow, shadowPos, shimStyle, shadowSize, shim, xy, x, y, w, h, shimIndex; if (me.preventSync) { return; } if (!me.updating && me.isVisible() && (shadow || me.useShim)) { shim = me.getShim(); xy = me[me.localXYNames.get](); x = xy[0]; y = xy[1]; w = me.dom.offsetWidth; h = me.dom.offsetHeight; if (shadow && !me.shadowDisabled) { if (doShow && !shadow.isVisible()) { shadow.show(me); } else { shadow.realign(x, y, w, h); } if (shim) { shimIndex = shim.getStyle('z-index'); if (shimIndex > me.zindex) { me.shim.setStyle('z-index', me.zindex - 2); } shim.show(); if (shadow.isVisible()) { shadowPos = shadow.el.getXY(); shimStyle = shim.dom.style; shadowSize = shadow.el.getSize(); if (Ext.supports.CSS3BoxShadow) { shadowSize.height += 6; shadowSize.width += 4; shadowPos[0] -= 2; shadowPos[1] -= 4; } shimStyle.left = (shadowPos[0]) + 'px'; shimStyle.top = (shadowPos[1]) + 'px'; shimStyle.width = (shadowSize.width) + 'px'; shimStyle.height = (shadowSize.height) + 'px'; } else { shim.setSize(w, h); shim[me.localXYNames.set](x, y); } } } else if (shim) { shimIndex = shim.getStyle('z-index'); if (shimIndex > me.zindex) { me.shim.setStyle('z-index', me.zindex - 2); } shim.show(); shim.setSize(w, h); shim[me.localXYNames.set](x, y); } } return me; }, remove: function() { this.hideUnders(); this.callParent(); }, beginUpdate: function() { this.updating = true; }, endUpdate: function() { this.updating = false; this.sync(true); }, hideUnders: function() { if (this.shadow) { this.shadow.hide(); } this.hideShim(); }, constrainXY: function() { if (this.constrain) { var vw = Ext.Element.getViewWidth(), vh = Ext.Element.getViewHeight(), s = Ext.getDoc().getScroll(), xy = this.getXY(), x = xy[0], y = xy[1], so = this.shadowOffset, w = this.dom.offsetWidth + so, h = this.dom.offsetHeight + so, moved = false; if ((x + w) > vw + s.left) { x = vw - w - so; moved = true; } if ((y + h) > vh + s.top) { y = vh - h - so; moved = true; } if (x < s.left) { x = s.left; moved = true; } if (y < s.top) { y = s.top; moved = true; } if (moved) { Ext.Layer.superclass.setXY.call(this, [x, y]); this.sync(); } } return this; }, getConstrainOffset: function() { return this.shadowOffset; }, setVisible: function(visible, animate, duration, callback, easing) { var me = this, cb; cb = function() { if (visible) { me.sync(true); } if (callback) { callback(); } }; if (!visible) { me.hideUnders(true); } me.callParent([visible, animate, duration, callback, easing]); if (!animate) { cb(); } return me; }, beforeFx: function() { this.beforeAction(); return this.callParent(arguments); }, afterFx: function() { this.callParent(arguments); this.sync(this.isVisible()); }, beforeAction: function() { if (!this.updating && this.shadow) { this.shadow.hide(); } }, setLeft: function(left) { this.callParent(arguments); return this.sync(); }, setTop: function(top) { this.callParent(arguments); return this.sync(); }, setLeftTop: function(left, top) { this.callParent(arguments); return this.sync(); }, setLocalX: function() { this.callParent(arguments); return this.sync(); }, setLocalXY: function() { this.callParent(arguments); return this.sync(); }, setLocalY: function() { this.callParent(arguments); return this.sync(); }, setXY: function(xy, animate, duration, callback, easing) { var me = this; callback = me.createCB(callback); me.fixDisplay(); me.beforeAction(); me.callParent([xy, animate, duration, callback, easing]); if (!animate) { callback(); } return me; }, createCB: function(callback) { var me = this, showShadow = me.shadow && me.shadow.isVisible(); return function() { me.constrainXY(); me.sync(showShadow); if (callback) { callback(); } }; }, setX: function(x, animate, duration, callback, easing) { this.setXY([x, this.getY()], animate, duration, callback, easing); return this; }, setY: function(y, animate, duration, callback, easing) { this.setXY([this.getX(), y], animate, duration, callback, easing); return this; }, setSize: function(w, h, animate, duration, callback, easing) { var me = this; callback = me.createCB(callback); me.beforeAction(); me.callParent([w, h, animate, duration, callback, easing]); if (!animate) { callback(); } return me; }, setWidth: function(w, animate, duration, callback, easing) { var me = this; callback = me.createCB(callback); me.beforeAction(); me.callParent([w, animate, duration, callback, easing]); if (!animate) { callback(); } return me; }, setHeight: function(h, animate, duration, callback, easing) { var me = this; callback = me.createCB(callback); me.beforeAction(); me.callParent([h, animate, duration, callback, easing]); if (!animate) { callback(); } return me; }, setBounds: function(x, y, width, height, animate, duration, callback, easing) { var me = this; callback = me.createCB(callback); me.beforeAction(); if (!animate) { Ext.Layer.superclass.setXY.call(me, [x, y]); Ext.Layer.superclass.setSize.call(me, width, height); callback(); } else { me.callParent([x, y, width, height, animate, duration, callback, easing]); } return me; }, setZIndex: function(zindex) { var me = this; me.zindex = zindex; if (me.getShim()) { me.shim.setStyle('z-index', zindex++); } if (me.shadow) { me.shadow.setZIndex(zindex++); } return me.setStyle('z-index', zindex); }, onOpacitySet: function(opacity){ var shadow = this.shadow; if (shadow) { shadow.setOpacity(opacity); } } }); Ext.define('Ext.draw.Matrix', { constructor: function(a, b, c, d, e, f) { if (a != null) { this.matrix = [[a, c, e], [b, d, f], [0, 0, 1]]; } else { this.matrix = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]; } }, add: function(a, b, c, d, e, f) { var me = this, out = [[], [], []], matrix = [[a, c, e], [b, d, f], [0, 0, 1]], x, y, z, res; for (x = 0; x < 3; x++) { for (y = 0; y < 3; y++) { res = 0; for (z = 0; z < 3; z++) { res += me.matrix[x][z] * matrix[z][y]; } out[x][y] = res; } } me.matrix = out; }, prepend: function(a, b, c, d, e, f) { var me = this, out = [[], [], []], matrix = [[a, c, e], [b, d, f], [0, 0, 1]], x, y, z, res; for (x = 0; x < 3; x++) { for (y = 0; y < 3; y++) { res = 0; for (z = 0; z < 3; z++) { res += matrix[x][z] * me.matrix[z][y]; } out[x][y] = res; } } me.matrix = out; }, invert: function() { var matrix = this.matrix, a = matrix[0][0], b = matrix[1][0], c = matrix[0][1], d = matrix[1][1], e = matrix[0][2], f = matrix[1][2], x = a * d - b * c; return new Ext.draw.Matrix(d / x, -b / x, -c / x, a / x, (c * f - d * e) / x, (b * e - a * f) / x); }, clone: function() { var matrix = this.matrix, a = matrix[0][0], b = matrix[1][0], c = matrix[0][1], d = matrix[1][1], e = matrix[0][2], f = matrix[1][2]; return new Ext.draw.Matrix(a, b, c, d, e, f); }, translate: function(x, y) { this.prepend(1, 0, 0, 1, x, y); }, scale: function(x, y, cx, cy) { var me = this; if (y == null) { y = x; } me.add(x, 0, 0, y, cx * (1 - x), cy * (1 - y)); }, rotate: function(a, x, y) { a = Ext.draw.Draw.rad(a); var me = this, cos = +Math.cos(a).toFixed(9), sin = +Math.sin(a).toFixed(9); me.add(cos, sin, -sin, cos, x - cos * x + sin * y, -(sin * x) + y - cos * y); }, x: function(x, y) { var matrix = this.matrix; return x * matrix[0][0] + y * matrix[0][1] + matrix[0][2]; }, y: function(x, y) { var matrix = this.matrix; return x * matrix[1][0] + y * matrix[1][1] + matrix[1][2]; }, get: function(i, j) { return + this.matrix[i][j].toFixed(4); }, toString: function() { var me = this; return [me.get(0, 0), me.get(0, 1), me.get(1, 0), me.get(1, 1), 0, 0].join(); }, toSvg: function() { var me = this; return "matrix(" + [me.get(0, 0), me.get(1, 0), me.get(0, 1), me.get(1, 1), me.get(0, 2), me.get(1, 2)].join() + ")"; }, toFilter: function(dx, dy) { var me = this; dx = dx || 0; dy = dy || 0; return "progid:DXImageTransform.Microsoft.Matrix(sizingMethod='auto expand', filterType='bilinear', M11=" + me.get(0, 0) + ", M12=" + me.get(0, 1) + ", M21=" + me.get(1, 0) + ", M22=" + me.get(1, 1) + ", Dx=" + (me.get(0, 2) + dx) + ", Dy=" + (me.get(1, 2) + dy) + ")"; }, offset: function() { var matrix = this.matrix; return [(matrix[0][2] || 0).toFixed(4), (matrix[1][2] || 0).toFixed(4)]; }, split: function () { function norm(a) { return a[0] * a[0] + a[1] * a[1]; } function normalize(a) { var mag = Math.sqrt(norm(a)); a[0] /= mag; a[1] /= mag; } var matrix = this.matrix, out = { translateX: matrix[0][2], translateY: matrix[1][2] }, row; row = [[matrix[0][0], matrix[0][1]], [matrix[1][1], matrix[1][1]]]; out.scaleX = Math.sqrt(norm(row[0])); normalize(row[0]); out.shear = row[0][0] * row[1][0] + row[0][1] * row[1][1]; row[1] = [row[1][0] - row[0][0] * out.shear, row[1][1] - row[0][1] * out.shear]; out.scaleY = Math.sqrt(norm(row[1])); normalize(row[1]); out.shear /= out.scaleY; out.rotate = Math.asin(-row[0][1]); out.isSimple = !+out.shear.toFixed(9) && (out.scaleX.toFixed(9) == out.scaleY.toFixed(9) || !out.rotate); return out; } }); Ext.define('Ext.draw.SpriteDD', { extend: Ext.dd.DragSource , constructor : function(sprite, cfg){ var me = this, el = sprite.el; me.sprite = sprite; me.el = el; me.dragData = {el: el, sprite: sprite}; me.callParent([el, cfg]); me.sprite.setStyle('cursor', 'move'); }, showFrame: Ext.emptyFn, createFrame : Ext.emptyFn, getDragEl : function(e){ return this.el; }, getRegion: function() { var me = this, el = me.el, pos, x1, x2, y1, y2, t, r, b, l, bbox, sprite; sprite = me.sprite; bbox = sprite.getBBox(); try { pos = Ext.Element.getXY(el); } catch (e) { } if (!pos) { return null; } x1 = pos[0]; x2 = x1 + bbox.width; y1 = pos[1]; y2 = y1 + bbox.height; return new Ext.util.Region(y1, x2, y2, x1); }, startDrag: function(x, y) { var me = this, attr = me.sprite.attr; me.prev = me.sprite.surface.transformToViewBox(x, y); }, onDrag: function(e) { var xy = e.getXY(), me = this, sprite = me.sprite, attr = sprite.attr, dx, dy; xy = me.sprite.surface.transformToViewBox(xy[0], xy[1]); dx = xy[0] - me.prev[0]; dy = xy[1] - me.prev[1]; sprite.setAttributes({ translate: { x: attr.translation.x + dx, y: attr.translation.y + dy } }, true); me.prev = xy; }, setDragElPos: function () { return false; } }); Ext.define('Ext.draw.Sprite', { mixins: { observable: Ext.util.Observable , animate: Ext.util.Animate }, dirty: false, dirtyHidden: false, dirtyTransform: false, dirtyPath: true, dirtyFont: true, zIndexDirty: true, isSprite: true, zIndex: 0, fontProperties: [ 'font', 'font-size', 'font-weight', 'font-style', 'font-family', 'text-anchor', 'text' ], pathProperties: [ 'x', 'y', 'd', 'path', 'height', 'width', 'radius', 'r', 'rx', 'ry', 'cx', 'cy' ], constructor: function(config) { var me = this; config = Ext.merge({}, config || {}); me.id = Ext.id(null, 'ext-sprite-'); me.transformations = []; Ext.copyTo(this, config, 'surface,group,type,draggable'); me.bbox = {}; me.attr = { zIndex: 0, translation: { x: null, y: null }, rotation: { degrees: null, x: null, y: null }, scaling: { x: null, y: null, cx: null, cy: null } }; delete config.surface; delete config.group; delete config.type; delete config.draggable; me.setAttributes(config); me.addEvents( 'beforedestroy', 'destroy', 'render', 'mousedown', 'mouseup', 'mouseover', 'mouseout', 'mousemove', 'click' ); me.mixins.observable.constructor.apply(this, arguments); }, initDraggable: function() { var me = this; if (!me.el) { me.surface.createSpriteElement(me); } me.dd = new Ext.draw.SpriteDD(me, Ext.isBoolean(me.draggable) ? null : me.draggable); me.on('beforedestroy', me.dd.destroy, me.dd); }, setAttributes: function(attrs, redraw) { var me = this, fontProps = me.fontProperties, fontPropsLength = fontProps.length, pathProps = me.pathProperties, pathPropsLength = pathProps.length, hasSurface = !!me.surface, custom = hasSurface && me.surface.customAttributes || {}, spriteAttrs = me.attr, dirtyBBox = false, attr, i, newTranslation, translation, newRotate, rotation, newScaling, scaling; attrs = Ext.apply({}, attrs); for (attr in custom) { if (attrs.hasOwnProperty(attr) && typeof custom[attr] == "function") { Ext.apply(attrs, custom[attr].apply(me, [].concat(attrs[attr]))); } } if (!!attrs.hidden !== !!spriteAttrs.hidden) { me.dirtyHidden = true; } for (i = 0; i < pathPropsLength; i++) { attr = pathProps[i]; if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) { me.dirtyPath = true; dirtyBBox = true; break; } } if ('zIndex' in attrs) { me.zIndexDirty = true; } if ('text' in attrs) { me.dirtyFont = true; dirtyBBox = true; attrs.text = me.transformText(attrs.text); } for (i = 0; i < fontPropsLength; i++) { attr = fontProps[i]; if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) { me.dirtyFont = true; dirtyBBox = true; break; } } newTranslation = attrs.translation || attrs.translate; delete attrs.translate; delete attrs.translation; translation = spriteAttrs.translation; if (newTranslation) { if (('x' in newTranslation && newTranslation.x !== translation.x) || ('y' in newTranslation && newTranslation.y !== translation.y)) { me.dirtyTransform = true; translation.x = newTranslation.x; translation.y = newTranslation.y; } } newRotate = attrs.rotation || attrs.rotate; rotation = spriteAttrs.rotation; delete attrs.rotate; delete attrs.rotation; if (newRotate) { if (('x' in newRotate && newRotate.x !== rotation.x) || ('y' in newRotate && newRotate.y !== rotation.y) || ('degrees' in newRotate && newRotate.degrees !== rotation.degrees)) { me.dirtyTransform = true; rotation.x = newRotate.x; rotation.y = newRotate.y; rotation.degrees = newRotate.degrees; } } newScaling = attrs.scaling || attrs.scale; scaling = spriteAttrs.scaling; delete attrs.scale; delete attrs.scaling; if (newScaling) { if (('x' in newScaling && newScaling.x !== scaling.x) || ('y' in newScaling && newScaling.y !== scaling.y) || ('cx' in newScaling && newScaling.cx !== scaling.cx) || ('cy' in newScaling && newScaling.cy !== scaling.cy)) { me.dirtyTransform = true; scaling.x = newScaling.x; scaling.y = newScaling.y; scaling.cx = newScaling.cx; scaling.cy = newScaling.cy; } } if (!me.dirtyTransform && dirtyBBox) { if (spriteAttrs.scaling.x === null || spriteAttrs.scaling.y === null || spriteAttrs.rotation.y === null || spriteAttrs.rotation.y === null) { me.dirtyTransform = true; } } Ext.apply(spriteAttrs, attrs); me.dirty = true; if (redraw === true && hasSurface) { me.redraw(); } return this; }, transformText: Ext.identityFn, getBBox: function() { return this.surface.getBBox(this); }, setText: function(text) { return this.surface.setText(this, text); }, hide: function(redraw) { this.setAttributes({ hidden: true }, redraw); return this; }, show: function(redraw) { this.setAttributes({ hidden: false }, redraw); return this; }, remove: function() { if (this.surface) { this.surface.remove(this); return true; } return false; }, onRemove: function() { this.surface.onRemove(this); }, destroy: function() { var me = this; if (me.fireEvent('beforedestroy', me) !== false) { me.remove(); me.surface.onDestroy(me); me.clearListeners(); me.fireEvent('destroy'); } }, redraw: function() { var me = this, changed = !me.el || me.dirty, surface = me.surface, owner; surface.renderItem(me); if (changed) { owner = surface.owner; if (!me.isBackground && owner && (owner.viewBox || owner.autoSize)) { owner.configureSurfaceSize(); } } return this; }, setStyle: function() { this.el.setStyle.apply(this.el, arguments); return this; }, addCls: function(obj) { this.surface.addCls(this, obj); return this; }, removeCls: function(obj) { this.surface.removeCls(this, obj); return this; } }); Ext.define('Ext.draw.Text', { extend: Ext.draw.Component , alias: 'widget.text', text: '', focusable: false, viewBox: false, autoSize: true, baseCls: Ext.baseCSSPrefix + 'surface ' + Ext.baseCSSPrefix + 'draw-text', initComponent: function() { var me = this; me.textConfig = Ext.apply({ type: 'text', text: me.text, rotate: { degrees: me.degrees || 0 } }, me.textStyle); Ext.apply(me.textConfig, me.getStyles(me.styleSelectors || me.styleSelector)); me.initialConfig.items = [me.textConfig]; me.callParent(arguments); }, getStyles: function(selectors) { selectors = Ext.Array.from(selectors); var i = 0, len = selectors.length, rule, style, prop, result = {}; for (; i < len; i++) { rule = Ext.util.CSS.getRule(selectors[i]); if (rule) { style = rule.style; if (style) { Ext.apply(result, { 'font-family': style.fontFamily, 'font-weight': style.fontWeight, 'line-height': style.lineHeight, 'font-size': style.fontSize, fill: style.color }); } } } return result; }, setAngle: function(degrees) { var me = this, surface, sprite; if (me.rendered) { surface = me.surface; sprite = surface.items.items[0]; me.degrees = degrees; sprite.setAttributes({ rotate: { degrees: degrees } }, true); if (me.autoSize || me.viewBox) { me.updateLayout(); } } else { me.degrees = degrees; } }, setText: function(text) { var me = this, surface, sprite; if (me.rendered) { surface = me.surface; sprite = surface.items.items[0]; me.text = text || ''; surface.remove(sprite); me.textConfig.type = 'text'; me.textConfig.text = me.text; sprite = surface.add(me.textConfig); sprite.setAttributes({ rotate: { degrees: me.degrees } }, true); if (me.autoSize || me.viewBox) { me.updateLayout(); } } else { me.on({ render: function() { me.setText(text); }, single: true }); } } }); Ext.define('Ext.draw.engine.ImageExporter', { singleton: true, defaultUrl: 'http://svg.sencha.io', supportedTypes: ['image/png', 'image/jpeg'], widthParam: 'width', heightParam: 'height', typeParam: 'type', svgParam: 'svg', formCls: Ext.baseCSSPrefix + 'hide-display', generate: function(surface, config) { config = config || {}; var me = this, type = config.type, form; if (Ext.Array.indexOf(me.supportedTypes, type) === -1) { return false; } form = Ext.getBody().createChild({ tag: 'form', method: 'POST', action: config.url || me.defaultUrl, cls: me.formCls, children: [{ tag: 'input', type: 'hidden', name: config.widthParam || me.widthParam, value: config.width || surface.width }, { tag: 'input', type: 'hidden', name: config.heightParam || me.heightParam, value: config.height || surface.height }, { tag: 'input', type: 'hidden', name: config.typeParam || me.typeParam, value: type }, { tag: 'input', type: 'hidden', name: config.svgParam || me.svgParam }] }); form.last(null, true).value = Ext.draw.engine.SvgExporter.generate(surface); form.dom.submit(); form.remove(); return true; } }); Ext.define('Ext.draw.engine.Svg', { extend: Ext.draw.Surface , engine: 'Svg', trimRe: /^\s+|\s+$/g, spacesRe: /\s+/, xlink: "http:/" + "/www.w3.org/1999/xlink", translateAttrs: { radius: "r", radiusX: "rx", radiusY: "ry", path: "d", lineWidth: "stroke-width", fillOpacity: "fill-opacity", strokeOpacity: "stroke-opacity", strokeLinejoin: "stroke-linejoin" }, parsers: {}, minDefaults: { circle: { cx: 0, cy: 0, r: 0, fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, ellipse: { cx: 0, cy: 0, rx: 0, ry: 0, fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, rect: { x: 0, y: 0, width: 0, height: 0, rx: 0, ry: 0, fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, text: { x: 0, y: 0, "text-anchor": "start", "font-family": null, "font-size": null, "font-weight": null, "font-style": null, fill: "#000", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, path: { d: "M0,0", fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, image: { x: 0, y: 0, width: 0, height: 0, preserveAspectRatio: "none", opacity: null } }, createSvgElement: function(type, attrs) { var el = this.domRef.createElementNS("http:/" + "/www.w3.org/2000/svg", type), key; if (attrs) { for (key in attrs) { el.setAttribute(key, String(attrs[key])); } } return el; }, createSpriteElement: function(sprite) { var el = this.createSvgElement(sprite.type); el.id = sprite.id; if (el.style) { el.style.webkitTapHighlightColor = "rgba(0,0,0,0)"; } sprite.el = Ext.get(el); this.applyZIndex(sprite); sprite.matrix = new Ext.draw.Matrix(); sprite.bbox = { plain: 0, transform: 0 }; this.applyAttrs(sprite); this.applyTransformations(sprite); sprite.fireEvent("render", sprite); return el; }, getBBoxText: function (sprite) { var bbox = {}, bb, height, width, i, ln, el; if (sprite && sprite.el) { el = sprite.el.dom; try { bbox = el.getBBox(); return bbox; } catch(e) { } bbox = {x: bbox.x, y: Infinity, width: 0, height: 0}; ln = el.getNumberOfChars(); for (i = 0; i < ln; i++) { bb = el.getExtentOfChar(i); bbox.y = Math.min(bb.y, bbox.y); height = bb.y + bb.height - bbox.y; bbox.height = Math.max(bbox.height, height); width = bb.x + bb.width - bbox.x; bbox.width = Math.max(bbox.width, width); } return bbox; } }, hide: function() { Ext.get(this.el).hide(); }, show: function() { Ext.get(this.el).show(); }, hidePrim: function(sprite) { this.addCls(sprite, Ext.baseCSSPrefix + 'hide-visibility'); }, showPrim: function(sprite) { this.removeCls(sprite, Ext.baseCSSPrefix + 'hide-visibility'); }, getDefs: function() { return this._defs || (this._defs = this.createSvgElement("defs")); }, transform: function(sprite, matrixOnly) { var me = this, matrix = new Ext.draw.Matrix(), transforms = sprite.transformations, transformsLength = transforms.length, i = 0, transform, type; for (; i < transformsLength; i++) { transform = transforms[i]; type = transform.type; if (type == "translate") { matrix.translate(transform.x, transform.y); } else if (type == "rotate") { matrix.rotate(transform.degrees, transform.x, transform.y); } else if (type == "scale") { matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY); } } sprite.matrix = matrix; if (!matrixOnly) { sprite.el.set({transform: matrix.toSvg()}); } }, setSize: function(width, height) { var me = this, el = me.el; width = +width || me.width; height = +height || me.height; me.width = width; me.height = height; el.setSize(width, height); el.set({ width: width, height: height }); me.callParent([width, height]); }, getRegion: function() { var svgXY = this.el.getXY(), rectXY = this.bgRect.getXY(), max = Math.max, x = max(svgXY[0], rectXY[0]), y = max(svgXY[1], rectXY[1]); return { left: x, top: y, right: x + this.width, bottom: y + this.height }; }, onRemove: function(sprite) { if (sprite.el) { sprite.el.destroy(); delete sprite.el; } this.callParent(arguments); }, setViewBox: function(x, y, width, height) { if (isFinite(x) && isFinite(y) && isFinite(width) && isFinite(height)) { this.callParent(arguments); this.el.dom.setAttribute("viewBox", [x, y, width, height].join(" ")); } }, render: function (container) { var me = this, el, defs, bgRect, webkitRect; if (!me.el) { cfg = { xmlns: "http:/" + "/www.w3.org/2000/svg", version: 1.1, width: me.width || 0, height: me.height || 0 }; if (me.forceLtr) { cfg.direction = 'ltr'; } el = me.createSvgElement('svg', cfg); defs = me.getDefs(); bgRect = me.createSvgElement("rect", { width: "100%", height: "100%", fill: "#000", stroke: "none", opacity: 0 }); if (Ext.isSafari3) { webkitRect = me.createSvgElement("rect", { x: -10, y: -10, width: "110%", height: "110%", fill: "none", stroke: "#000" }); } el.appendChild(defs); if (Ext.isSafari3) { el.appendChild(webkitRect); } el.appendChild(bgRect); container.appendChild(el); me.el = Ext.get(el); me.bgRect = Ext.get(bgRect); if (Ext.isSafari3) { me.webkitRect = Ext.get(webkitRect); me.webkitRect.hide(); } me.el.on({ scope: me, mouseup: me.onMouseUp, mousedown: me.onMouseDown, mouseover: me.onMouseOver, mouseout: me.onMouseOut, mousemove: me.onMouseMove, mouseenter: me.onMouseEnter, mouseleave: me.onMouseLeave, click: me.onClick, dblclick: me.onDblClick }); } me.renderAll(); }, onMouseEnter: function(e) { if (this.el.parent().getRegion().contains(e.getPoint())) { this.fireEvent('mouseenter', e); } }, onMouseLeave: function(e) { if (!this.el.parent().getRegion().contains(e.getPoint())) { this.fireEvent('mouseleave', e); } }, processEvent: function(name, e) { var target = e.getTarget(), surface = this.surface, sprite; this.fireEvent(name, e); if (target.nodeName == "tspan" && target.parentNode) { target = target.parentNode; } sprite = this.items.get(target.id); if (sprite) { sprite.fireEvent(name, sprite, e); } }, tuneText: function (sprite, attrs) { var el = sprite.el.dom, tspans = [], height, tspan, text, i, ln, texts, factor, x; if (attrs.hasOwnProperty("text")) { text = sprite.tspans && Ext.Array.map(sprite.tspans, function(t) { return t.textContent; }).join(''); if (!sprite.tspans || attrs.text != text) { tspans = this.setText(sprite, attrs.text); sprite.tspans = tspans; } else { tspans = sprite.tspans || []; } } if (tspans.length) { height = this.getBBoxText(sprite).height; x = sprite.el.dom.getAttribute("x"); for (i = 0, ln = tspans.length; i < ln; i++) { factor = (Ext.isFF3_0 || Ext.isFF3_5) ? 2 : 4; tspans[i].setAttribute("x", x); tspans[i].setAttribute("dy", i ? height * 1.2 : height / factor); } sprite.dirty = true; } }, setText: function(sprite, textString) { var me = this, el = sprite.el.dom, tspans = [], height, tspan, text, i, ln, texts; while (el.firstChild) { el.removeChild(el.firstChild); } texts = String(textString).split("\n"); for (i = 0, ln = texts.length; i < ln; i++) { text = texts[i]; if (text) { tspan = me.createSvgElement("tspan"); tspan.appendChild(document.createTextNode(Ext.htmlDecode(text))); el.appendChild(tspan); tspans[i] = tspan; } } return tspans; }, renderAll: function() { this.items.each(this.renderItem, this); }, renderItem: function (sprite) { if (!this.el) { return; } if (!sprite.el) { this.createSpriteElement(sprite); } if (sprite.zIndexDirty) { this.applyZIndex(sprite); } if (sprite.dirty) { this.applyAttrs(sprite); if (sprite.dirtyTransform) { this.applyTransformations(sprite); } } }, redraw: function(sprite) { sprite.dirty = sprite.zIndexDirty = true; this.renderItem(sprite); }, applyAttrs: function (sprite) { var me = this, el = sprite.el, group = sprite.group, sattr = sprite.attr, parsers = me.parsers, gradientsMap = me.gradientsMap || {}, safariFix = Ext.isSafari && !Ext.isStrict, groups, i, ln, attrs, font, key, style, name, rect; if (group) { groups = [].concat(group); ln = groups.length; for (i = 0; i < ln; i++) { group = groups[i]; me.getGroup(group).add(sprite); } delete sprite.group; } attrs = me.scrubAttrs(sprite) || {}; sprite.bbox.plain = 0; sprite.bbox.transform = 0; if (sprite.type == "circle" || sprite.type == "ellipse") { attrs.cx = attrs.cx || attrs.x; attrs.cy = attrs.cy || attrs.y; } else if (sprite.type == "rect") { attrs.rx = attrs.ry = attrs.r; } else if (sprite.type == "path" && attrs.d) { attrs.d = Ext.draw.Draw.pathToString(Ext.draw.Draw.pathToAbsolute(attrs.d)); } sprite.dirtyPath = false; if (attrs['clip-rect']) { me.setClip(sprite, attrs); delete attrs['clip-rect']; } if (sprite.type == 'text' && attrs.font && sprite.dirtyFont) { el.set({ style: "font: " + attrs.font}); } if (sprite.type == "image") { el.dom.setAttributeNS(me.xlink, "href", attrs.src); } Ext.applyIf(attrs, me.minDefaults[sprite.type]); if (sprite.dirtyHidden) { (sattr.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite); sprite.dirtyHidden = false; } for (key in attrs) { if (attrs.hasOwnProperty(key) && attrs[key] != null) { if (safariFix && ('color|stroke|fill'.indexOf(key) > -1) && (attrs[key] in gradientsMap)) { attrs[key] = gradientsMap[attrs[key]]; } if (key == 'hidden' && sprite.type == 'text') { continue; } if (key in parsers) { el.dom.setAttribute(key, parsers[key](attrs[key], sprite, me)); } else { el.dom.setAttribute(key, attrs[key]); } } } if (sprite.type == 'text') { me.tuneText(sprite, attrs); } sprite.dirtyFont = false; style = sattr.style; if (style) { el.setStyle(style); } sprite.dirty = false; if (Ext.isSafari3) { me.webkitRect.show(); setTimeout(function () { me.webkitRect.hide(); }); } }, setClip: function(sprite, params) { var me = this, rect = params["clip-rect"], clipEl, clipPath; if (rect) { if (sprite.clip) { sprite.clip.parentNode.parentNode.removeChild(sprite.clip.parentNode); } clipEl = me.createSvgElement('clipPath'); clipPath = me.createSvgElement('rect'); clipEl.id = Ext.id(null, 'ext-clip-'); clipPath.setAttribute("x", rect.x); clipPath.setAttribute("y", rect.y); clipPath.setAttribute("width", rect.width); clipPath.setAttribute("height", rect.height); clipEl.appendChild(clipPath); me.getDefs().appendChild(clipEl); sprite.el.dom.setAttribute("clip-path", "url(#" + clipEl.id + ")"); sprite.clip = clipPath; } }, applyZIndex: function(sprite) { var me = this, items = me.items, idx = items.indexOf(sprite), el = sprite.el, prevEl; if (me.el.dom.childNodes[idx + 2] !== el.dom) { if (idx > 0) { do { prevEl = items.getAt(--idx).el; } while (!prevEl && idx > 0); } el.insertAfter(prevEl || me.bgRect); } sprite.zIndexDirty = false; }, createItem: function (config) { var sprite = new Ext.draw.Sprite(config); sprite.surface = this; return sprite; }, addGradient: function(gradient) { gradient = Ext.draw.Draw.parseGradient(gradient); var me = this, ln = gradient.stops.length, vector = gradient.vector, usePlain = Ext.isSafari && !Ext.isStrict, gradientEl, stop, stopEl, i, gradientsMap; gradientsMap = me.gradientsMap || {}; if (!usePlain) { if (gradient.type == "linear") { gradientEl = me.createSvgElement("linearGradient"); gradientEl.setAttribute("x1", vector[0]); gradientEl.setAttribute("y1", vector[1]); gradientEl.setAttribute("x2", vector[2]); gradientEl.setAttribute("y2", vector[3]); } else { gradientEl = me.createSvgElement("radialGradient"); gradientEl.setAttribute("cx", gradient.centerX); gradientEl.setAttribute("cy", gradient.centerY); gradientEl.setAttribute("r", gradient.radius); if (Ext.isNumber(gradient.focalX) && Ext.isNumber(gradient.focalY)) { gradientEl.setAttribute("fx", gradient.focalX); gradientEl.setAttribute("fy", gradient.focalY); } } gradientEl.id = gradient.id; me.getDefs().appendChild(gradientEl); for (i = 0; i < ln; i++) { stop = gradient.stops[i]; stopEl = me.createSvgElement("stop"); stopEl.setAttribute("offset", stop.offset + "%"); stopEl.setAttribute("stop-color", stop.color); stopEl.setAttribute("stop-opacity",stop.opacity); gradientEl.appendChild(stopEl); } } else { gradientsMap['url(#' + gradient.id + ')'] = gradient.stops[0].color; } me.gradientsMap = gradientsMap; }, hasCls: function(sprite, className) { return className && (' ' + (sprite.el.dom.getAttribute('class') || '') + ' ').indexOf(' ' + className + ' ') != -1; }, addCls: function(sprite, className) { var el = sprite.el, i, len, v, cls = [], curCls = el.getAttribute('class') || ''; if (!Ext.isArray(className)) { if (typeof className == 'string' && !this.hasCls(sprite, className)) { el.set({ 'class': curCls + ' ' + className }); } } else { for (i = 0, len = className.length; i < len; i++) { v = className[i]; if (typeof v == 'string' && (' ' + curCls + ' ').indexOf(' ' + v + ' ') == -1) { cls.push(v); } } if (cls.length) { el.set({ 'class': ' ' + cls.join(' ') }); } } }, removeCls: function(sprite, className) { var me = this, el = sprite.el, curCls = el.getAttribute('class') || '', i, idx, len, cls, elClasses; if (!Ext.isArray(className)){ className = [className]; } if (curCls) { elClasses = curCls.replace(me.trimRe, ' ').split(me.spacesRe); for (i = 0, len = className.length; i < len; i++) { cls = className[i]; if (typeof cls == 'string') { cls = cls.replace(me.trimRe, ''); idx = Ext.Array.indexOf(elClasses, cls); if (idx != -1) { Ext.Array.erase(elClasses, idx, 1); } } } el.set({ 'class': elClasses.join(' ') }); } }, destroy: function() { var me = this; me.callParent(); if (me.el) { me.el.remove(); } if (me._defs) { Ext.get(me._defs).destroy(); } if (me.bgRect) { Ext.get(me.bgRect).destroy(); } if (me.webkitRect) { Ext.get(me.webkitRect).destroy(); } delete me.el; } }); Ext.define('Ext.draw.engine.SvgExporter', function(){ var commaRe = /,/g, fontRegex = /(-?\d*\.?\d*){1}(em|ex|px|in|cm|mm|pt|pc|%)\s('*.*'*)/, rgbColorRe = /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/g, rgbaColorRe = /rgba\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,([\d\.]+)\)/g, surface, len, width, height, init = function(s){ surface = s; len = surface.length; width = surface.width; height = surface.height; }, spriteProcessor = { path: function(sprite){ var attr = sprite.attr, path = attr.path, pathString = '', props, p, pLen; if (Ext.isArray(path[0])) { pLen = path.length; for (p = 0; p < pLen; p++) { pathString += path[p].join(' '); } } else if (Ext.isArray(path)) { pathString = path.join(' '); } else { pathString = path.replace(commaRe,' '); } props = toPropertyString({ d: pathString, fill: attr.fill || 'none', stroke: attr.stroke, 'fill-opacity': attr.opacity, 'stroke-width': attr['stroke-width'], 'stroke-opacity': attr['stroke-opacity'], "z-index": attr.zIndex, transform: sprite.matrix.toSvg() }); return ''; }, text: function(sprite){ var attr = sprite.attr, match = fontRegex.exec(attr.font), size = (match && match[1]) || "12", family = (match && match[3]) || 'Arial', text = attr.text, factor = (Ext.isFF3_0 || Ext.isFF3_5) ? 2 : 4, tspanString = '', props; sprite.getBBox(); tspanString += ''; tspanString += Ext.htmlEncode(text) + ''; props = toPropertyString({ x: attr.x, y: attr.y, 'font-size': size, 'font-family': family, 'font-weight': attr['font-weight'], 'text-anchor': attr['text-anchor'], fill: attr.fill || '#000', 'fill-opacity': attr.opacity, transform: sprite.matrix.toSvg() }); return '' + tspanString + ''; }, rect: function(sprite){ var attr = sprite.attr, props = toPropertyString({ x: attr.x, y: attr.y, rx: attr.rx, ry: attr.ry, width: attr.width, height: attr.height, fill: attr.fill || 'none', 'fill-opacity': attr.opacity, stroke: attr.stroke, 'stroke-opacity': attr['stroke-opacity'], 'stroke-width':attr['stroke-width'], transform: sprite.matrix && sprite.matrix.toSvg() }); return ''; }, circle: function(sprite){ var attr = sprite.attr, props = toPropertyString({ cx: attr.x, cy: attr.y, r: attr.radius, fill: attr.translation.fill || attr.fill || 'none', 'fill-opacity': attr.opacity, stroke: attr.stroke, 'stroke-opacity': attr['stroke-opacity'], 'stroke-width':attr['stroke-width'], transform: sprite.matrix.toSvg() }); return ''; }, image: function(sprite){ var attr = sprite.attr, props = toPropertyString({ x: attr.x - (attr.width/2 >> 0), y: attr.y - (attr.height/2 >> 0), width: attr.width, height: attr.height, 'xlink:href': attr.src, transform: sprite.matrix.toSvg() }); return ''; } }, svgHeader = function(){ var svg = ''; svg += ''; return svg; }, svgContent = function(){ var svg = '', defs = '', item, itemsLen, items, gradient, getSvgString, colorstops, stop, coll, keys, colls, k, kLen, key, collI, i, j, stopsLen, sortedItems, za, zb; items = surface.items.items; itemsLen = items.length; getSvgString = function(node){ var childs = node.childNodes, childLength = childs.length, i = 0, attrLength, j, svgString = '', child, attr, tagName, attrItem; for(; i < childLength; i++){ child = childs[i]; attr = child.attributes; tagName = child.tagName; svgString += '<' +tagName; for(j = 0, attrLength = attr.length; j < attrLength; j++){ attrItem = attr.item(j); svgString += ' '+attrItem.name+'="'+attrItem.value+'"'; } svgString += '>'; if(child.childNodes.length > 0){ svgString += getSvgString(child); } svgString += ''; } return svgString; }; if(surface.getDefs){ defs = getSvgString(surface.getDefs()); }else{ coll = surface.gradientsColl; if (coll) { keys = coll.keys; colls = coll.items; k = 0; kLen = keys.length; } for (; k < kLen; k++) { key = keys[k]; collI = colls[k]; gradient = surface.gradientsColl.getByKey(key); defs += ''; var color = gradient.colors.replace(rgbColorRe, 'rgb($1|$2|$3)'); color = color.replace(rgbaColorRe, 'rgba($1|$2|$3|$4)') colorstops = color.split(','); for(i=0, stopsLen = colorstops.length; i < stopsLen; i++){ stop = colorstops[i].split(' '); color = Ext.draw.Color.fromString(stop[1].replace(/\|/g,',')); defs += ''; } defs += ''; } } svg += '' + defs + ''; svg += spriteProcessor.rect({ attr: { width: '100%', height: '100%', fill: '#fff', stroke: 'none', opacity: '0' } }); sortedItems = new Array(itemsLen); for(i = 0; i < itemsLen; i++){ sortedItems[i] = i; } sortedItems.sort(function (a, b) { za = items[a].attr.zIndex || 0; zb = items[b].attr.zIndex || 0; if (za == zb) { return a - b; } return za - zb; }); for(i = 0; i < itemsLen; i++){ item = items[sortedItems[i]]; if(!item.attr.hidden){ svg += spriteProcessor[item.type](item); } } svg += ''; return svg; }, toPropertyString = function(obj){ var propString = '', key; for(key in obj){ if(obj.hasOwnProperty(key) && obj[key] != null){ propString += key +'="'+ obj[key]+'" '; } } return propString; }; return { singleton: true, generate: function(surface, config){ config = config || {}; init(surface); return svgHeader() + svgContent(); } }; }); Ext.define('Ext.draw.engine.Vml', { extend: Ext.draw.Surface , engine: 'Vml', map: {M: "m", L: "l", C: "c", Z: "x", m: "t", l: "r", c: "v", z: "x"}, bitesRe: /([clmz]),?([^clmz]*)/gi, valRe: /-?[^,\s\-]+/g, fillUrlRe: /^url\(\s*['"]?([^\)]+?)['"]?\s*\)$/i, pathlike: /^(path|rect)$/, NonVmlPathRe: /[ahqstv]/ig, // Non-VML Pathing ops partialPathRe: /[clmz]/g, fontFamilyRe: /^['"]+|['"]+$/g, baseVmlCls: Ext.baseCSSPrefix + 'vml-base', vmlGroupCls: Ext.baseCSSPrefix + 'vml-group', spriteCls: Ext.baseCSSPrefix + 'vml-sprite', measureSpanCls: Ext.baseCSSPrefix + 'vml-measure-span', zoom: 21600, coordsize: 1000, coordorigin: '0 0', zIndexShift: 0, // VML uses CSS z-index and therefore doesn't need sprites to be kept in zIndex order orderSpritesByZIndex: false, path2vml: function (path) { var me = this, nonVML = me.NonVmlPathRe, map = me.map, val = me.valRe, zoom = me.zoom, bites = me.bitesRe, command = Ext.Function.bind(Ext.draw.Draw.pathToAbsolute, Ext.draw.Draw), res, pa, p, r, i, ii, j, jj; if (String(path).match(nonVML)) { command = Ext.Function.bind(Ext.draw.Draw.path2curve, Ext.draw.Draw); } else if (!String(path).match(me.partialPathRe)) { res = String(path).replace(bites, function (all, command, args) { var vals = [], isMove = command.toLowerCase() == "m", res = map[command]; args.replace(val, function (value) { if (isMove && vals.length === 2) { res += vals + map[command == "m" ? "l" : "L"]; vals = []; } vals.push(Math.round(value * zoom)); }); return res + vals; }); return res; } pa = command(path); res = []; for (i = 0, ii = pa.length; i < ii; i++) { p = pa[i]; r = pa[i][0].toLowerCase(); if (r == "z") { r = "x"; } for (j = 1, jj = p.length; j < jj; j++) { r += Math.round(p[j] * me.zoom) + (j != jj - 1 ? "," : ""); } res.push(r); } return res.join(" "); }, translateAttrs: { radius: "r", radiusX: "rx", radiusY: "ry", lineWidth: "stroke-width", fillOpacity: "fill-opacity", strokeOpacity: "stroke-opacity", strokeLinejoin: "stroke-linejoin" }, minDefaults: { circle: { fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, ellipse: { cx: 0, cy: 0, rx: 0, ry: 0, fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, rect: { x: 0, y: 0, width: 0, height: 0, rx: 0, ry: 0, fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, text: { x: 0, y: 0, "text-anchor": "start", font: '10px "Arial"', fill: "#000", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, path: { d: "M0,0", fill: "none", stroke: null, "stroke-width": null, opacity: null, "fill-opacity": null, "stroke-opacity": null }, image: { x: 0, y: 0, width: 0, height: 0, preserveAspectRatio: "none", opacity: null } }, onMouseEnter: function (e) { this.fireEvent("mouseenter", e); }, onMouseLeave: function (e) { this.fireEvent("mouseleave", e); }, processEvent: function (name, e) { var target = e.getTarget(), surface = this.surface, sprite; this.fireEvent(name, e); sprite = this.items.get(target.id); if (sprite) { sprite.fireEvent(name, sprite, e); } }, createSpriteElement: function (sprite) { var me = this, attr = sprite.attr, type = sprite.type, zoom = me.zoom, vml = sprite.vml || (sprite.vml = {}), round = Math.round, el = (type === 'image') ? me.createNode('image') : me.createNode('shape'), path, skew, textPath; el.coordsize = zoom + ' ' + zoom; el.coordorigin = attr.coordorigin || "0 0"; Ext.get(el).addCls(me.spriteCls); if (type == "text") { vml.path = path = me.createNode("path"); path.textpathok = true; vml.textpath = textPath = me.createNode("textpath"); textPath.on = true; el.appendChild(textPath); el.appendChild(path); } el.id = sprite.id; sprite.el = Ext.get(el); sprite.el.setStyle('zIndex', -me.zIndexShift); me.el.appendChild(el); if (type !== 'image') { skew = me.createNode("skew"); skew.on = true; el.appendChild(skew); sprite.skew = skew; } sprite.matrix = new Ext.draw.Matrix(); sprite.bbox = { plain: null, transform: null }; this.applyAttrs(sprite); this.applyTransformations(sprite); sprite.fireEvent("render", sprite); return sprite.el; }, getBBoxText: function (sprite) { var vml = sprite.vml; return { x: vml.X + (vml.bbx || 0) - vml.W / 2, y: vml.Y - vml.H / 2, width: vml.W, height: vml.H }; }, applyAttrs: function (sprite) { var me = this, vml = sprite.vml, group = sprite.group, spriteAttr = sprite.attr, el = sprite.el, dom = el.dom, style, name, groups, i, ln, scrubbedAttrs, font, key, cx, cy, rx, ry; if (group) { groups = [].concat(group); ln = groups.length; for (i = 0; i < ln; i++) { group = groups[i]; me.getGroup(group).add(sprite); } delete sprite.group; } scrubbedAttrs = me.scrubAttrs(sprite) || {}; if (sprite.zIndexDirty) { me.setZIndex(sprite); } Ext.applyIf(scrubbedAttrs, me.minDefaults[sprite.type]); if (sprite.type == 'image') { Ext.apply(sprite.attr, { x: scrubbedAttrs.x, y: scrubbedAttrs.y, width: scrubbedAttrs.width, height: scrubbedAttrs.height }); el.setStyle({ width: scrubbedAttrs.width + 'px', height: scrubbedAttrs.height + 'px' }); dom.src = scrubbedAttrs.src; } if (dom.href) { dom.href = scrubbedAttrs.href; } if (dom.title) { dom.title = scrubbedAttrs.title; } if (dom.target) { dom.target = scrubbedAttrs.target; } if (dom.cursor) { dom.cursor = scrubbedAttrs.cursor; } if (sprite.dirtyHidden) { (scrubbedAttrs.hidden) ? me.hidePrim(sprite) : me.showPrim(sprite); sprite.dirtyHidden = false; } if (sprite.dirtyPath) { if (sprite.type == "circle" || sprite.type == "ellipse") { cx = scrubbedAttrs.x; cy = scrubbedAttrs.y; rx = scrubbedAttrs.rx || scrubbedAttrs.r || 0; ry = scrubbedAttrs.ry || scrubbedAttrs.r || 0; dom.path = Ext.String.format("ar{0},{1},{2},{3},{4},{1},{4},{1}", Math.round((cx - rx) * me.zoom), Math.round((cy - ry) * me.zoom), Math.round((cx + rx) * me.zoom), Math.round((cy + ry) * me.zoom), Math.round(cx * me.zoom)); sprite.dirtyPath = false; } else if (sprite.type !== "text" && sprite.type !== 'image') { sprite.attr.path = scrubbedAttrs.path = me.setPaths(sprite, scrubbedAttrs) || scrubbedAttrs.path; dom.path = me.path2vml(scrubbedAttrs.path); sprite.dirtyPath = false; } } if ("clip-rect" in scrubbedAttrs) { me.setClip(sprite, scrubbedAttrs); } if (sprite.type == "text") { me.setTextAttributes(sprite, scrubbedAttrs); } if (scrubbedAttrs.opacity || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) { me.setFill(sprite, scrubbedAttrs); } if (scrubbedAttrs.stroke || scrubbedAttrs['stroke-opacity'] || scrubbedAttrs.fill) { me.setStroke(sprite, scrubbedAttrs); } style = spriteAttr.style; if (style) { el.setStyle(style); } sprite.dirty = false; }, setZIndex: function (sprite) { var me = this, zIndex = sprite.attr.zIndex, shift = me.zIndexShift, items, iLen, item, i; if (zIndex < shift) { items = me.items.items; iLen = items.length; for (i = 0; i < iLen; i++) { if ((zIndex = items[i].attr.zIndex) && zIndex < shift) { shift = zIndex; } } me.zIndexShift = shift; for (i = 0; i < iLen; i++) { item = items[i]; if (item.el) { item.el.setStyle('zIndex', item.attr.zIndex - shift); } item.zIndexDirty = false; } } else if (sprite.el) { sprite.el.setStyle('zIndex', zIndex - shift); sprite.zIndexDirty = false; } }, setPaths: function (sprite, params) { var spriteAttr = sprite.attr, thickness = sprite.attr['stroke-width'] || 1; sprite.bbox.plain = null; sprite.bbox.transform = null; if (sprite.type == 'circle') { spriteAttr.rx = spriteAttr.ry = params.r; return Ext.draw.Draw.ellipsePath(sprite); } else if (sprite.type == 'ellipse') { spriteAttr.rx = params.rx; spriteAttr.ry = params.ry; return Ext.draw.Draw.ellipsePath(sprite); } else if (sprite.type == 'rect') { spriteAttr.rx = spriteAttr.ry = params.r; return Ext.draw.Draw.rectPath(sprite); } else if (sprite.type == 'path' && spriteAttr.path) { return Ext.draw.Draw.pathToAbsolute(spriteAttr.path); } return false; }, setFill: function (sprite, params) { var me = this, el = sprite.el.dom, fillEl = el.fill, newfill = false, opacity, gradient, fillUrl, rotation, angle; if (!fillEl) { fillEl = el.fill = me.createNode("fill"); newfill = true; } if (Ext.isArray(params.fill)) { params.fill = params.fill[0]; } if (params.fill == "none") { fillEl.on = false; } else { if (typeof params.opacity == "number") { fillEl.opacity = params.opacity; } if (typeof params["fill-opacity"] == "number") { fillEl.opacity = params["fill-opacity"]; } fillEl.on = true; if (typeof params.fill == "string") { fillUrl = params.fill.match(me.fillUrlRe); if (fillUrl) { fillUrl = fillUrl[1]; if (fillUrl.charAt(0) == "#") { gradient = me.gradientsColl.getByKey(fillUrl.substring(1)); } if (gradient) { rotation = params.rotation; angle = -(gradient.angle + 270 + (rotation ? rotation.degrees : 0)) % 360; if (angle === 0) { angle = 180; } fillEl.angle = angle; fillEl.type = "gradient"; fillEl.method = "sigma"; if (fillEl.colors) { fillEl.colors.value = gradient.colors; } else { fillEl.colors = gradient.colors; } } else { fillEl.src = fillUrl; fillEl.type = "tile"; } } else { fillEl.color = Ext.draw.Color.toHex(params.fill); fillEl.src = ""; fillEl.type = "solid"; } } } if (newfill) { el.appendChild(fillEl); } }, setStroke: function (sprite, params) { var me = this, el = sprite.el.dom, strokeEl = sprite.strokeEl, newStroke = false, width, opacity; if (!strokeEl) { strokeEl = sprite.strokeEl = me.createNode("stroke"); newStroke = true; } if (Ext.isArray(params.stroke)) { params.stroke = params.stroke[0]; } if (!params.stroke || params.stroke == "none" || params.stroke == 0 || params["stroke-width"] == 0) { strokeEl.on = false; } else { strokeEl.on = true; if (params.stroke && !params.stroke.match(me.fillUrlRe)) { strokeEl.color = Ext.draw.Color.toHex(params.stroke); } strokeEl.dashstyle = params["stroke-dasharray"] ? "dash" : "solid"; strokeEl.joinstyle = params["stroke-linejoin"]; strokeEl.endcap = params["stroke-linecap"] || "round"; strokeEl.miterlimit = params["stroke-miterlimit"] || 8; width = parseFloat(params["stroke-width"] || 1) * 0.75; opacity = params["stroke-opacity"] || 1; if (Ext.isNumber(width) && width < 1) { strokeEl.weight = 1; strokeEl.opacity = opacity * width; } else { strokeEl.weight = width; strokeEl.opacity = opacity; } } if (newStroke) { el.appendChild(strokeEl); } }, setClip: function (sprite, params) { var me = this, el = sprite.el, clipEl = sprite.clipEl, rect = String(params["clip-rect"]).split(me.separatorRe); if (!clipEl) { clipEl = sprite.clipEl = me.el.insertFirst(Ext.getDoc().dom.createElement("div")); clipEl.addCls(Ext.baseCSSPrefix + 'vml-sprite'); } if (rect.length == 4) { rect[2] = +rect[2] + (+rect[0]); rect[3] = +rect[3] + (+rect[1]); clipEl.setStyle("clip", Ext.String.format("rect({1}px {2}px {3}px {0}px)", rect[0], rect[1], rect[2], rect[3])); clipEl.setSize(me.el.width, me.el.height); } else { clipEl.setStyle("clip", ""); } }, setTextAttributes: function (sprite, params) { var me = this, vml = sprite.vml, textStyle = vml.textpath.style, spanCacheStyle = me.span.style, zoom = me.zoom, round = Math.round, fontObj = { fontSize: "font-size", fontWeight: "font-weight", fontStyle: "font-style" }, fontProp, paramProp; if (sprite.dirtyFont) { if (params.font) { textStyle.font = spanCacheStyle.font = params.font; } if (params["font-family"]) { textStyle.fontFamily = '"' + params["font-family"].split(",")[0].replace(me.fontFamilyRe, "") + '"'; spanCacheStyle.fontFamily = params["font-family"]; } for (fontProp in fontObj) { paramProp = params[fontObj[fontProp]]; if (paramProp) { textStyle[fontProp] = spanCacheStyle[fontProp] = paramProp; } } me.setText(sprite, params.text); if (vml.textpath.string) { me.span.innerHTML = String(vml.textpath.string).replace(/"); } vml.W = me.span.offsetWidth; vml.H = me.span.offsetHeight + 2; if (params["text-anchor"] == "middle") { textStyle["v-text-align"] = "center"; } else if (params["text-anchor"] == "end") { textStyle["v-text-align"] = "right"; vml.bbx = -Math.round(vml.W / 2); } else { textStyle["v-text-align"] = "left"; vml.bbx = Math.round(vml.W / 2); } } vml.X = params.x; vml.Y = params.y; vml.path.v = Ext.String.format("m{0},{1}l{2},{1}", Math.round(vml.X * zoom), Math.round(vml.Y * zoom), Math.round(vml.X * zoom) + 1); sprite.bbox.plain = null; sprite.bbox.transform = null; sprite.dirtyFont = false; }, setText: function (sprite, text) { sprite.vml.textpath.string = Ext.htmlDecode(text); }, hide: function () { this.el.hide(); }, show: function () { this.el.show(); }, hidePrim: function (sprite) { sprite.el.addCls(Ext.baseCSSPrefix + 'hide-visibility'); }, showPrim: function (sprite) { sprite.el.removeCls(Ext.baseCSSPrefix + 'hide-visibility'); }, setSize: function (width, height) { var me = this; width = width || me.width; height = height || me.height; me.width = width; me.height = height; if (me.el) { if (width != undefined) { me.el.setWidth(width); } if (height != undefined) { me.el.setHeight(height); } } me.callParent(arguments); }, applyViewBox: function () { var me = this, viewBox = me.viewBox, width = me.width, height = me.height, items, iLen, i; me.callParent(); if (viewBox && (width || height)) { items = me.items.items; iLen = items.length; for (i = 0; i < iLen; i++) { me.applyTransformations(items[i]); } } }, onAdd: function (item) { this.callParent(arguments); if (this.el) { this.renderItem(item); } }, onRemove: function (sprite) { if (sprite.el) { sprite.el.remove(); delete sprite.el; } this.callParent(arguments); }, render: function (container) { var me = this, doc = Ext.getDoc().dom, el; if (!me.createNode) { try { if (!doc.namespaces.rvml) { doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml"); } me.createNode = function (tagName) { return doc.createElement("'); }; } catch (e) { me.createNode = function (tagName) { return doc.createElement("<" + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">'); }; } } if (!me.el) { el = doc.createElement("div"); me.el = Ext.get(el); me.el.addCls(me.baseVmlCls); me.span = doc.createElement("span"); Ext.get(me.span).addCls(me.measureSpanCls); el.appendChild(me.span); me.el.setSize(me.width || 0, me.height || 0); container.appendChild(el); me.el.on({ scope: me, mouseup: me.onMouseUp, mousedown: me.onMouseDown, mouseover: me.onMouseOver, mouseout: me.onMouseOut, mousemove: me.onMouseMove, mouseenter: me.onMouseEnter, mouseleave: me.onMouseLeave, click: me.onClick, dblclick: me.onDblClick }); } me.renderAll(); }, renderAll: function () { this.items.each(this.renderItem, this); }, redraw: function (sprite) { sprite.dirty = true; this.renderItem(sprite); }, renderItem: function (sprite) { if (!this.el) { return; } if (!sprite.el) { this.createSpriteElement(sprite); } if (sprite.dirty) { this.applyAttrs(sprite); if (sprite.dirtyTransform) { this.applyTransformations(sprite); } } }, rotationCompensation: function (deg, dx, dy) { var matrix = new Ext.draw.Matrix(); matrix.rotate(-deg, 0.5, 0.5); return { x: matrix.x(dx, dy), y: matrix.y(dx, dy) }; }, transform: function (sprite, matrixOnly) { var me = this, bbox = me.getBBox(sprite, true), cx = bbox.x + bbox.width * 0.5, cy = bbox.y + bbox.height * 0.5, matrix = new Ext.draw.Matrix(), transforms = sprite.transformations, transformsLength = transforms.length, i = 0, deltaDegrees = 0, deltaScaleX = 1, deltaScaleY = 1, flip = "", el = sprite.el, dom = el.dom, domStyle = dom.style, zoom = me.zoom, skew = sprite.skew, shift = me.viewBoxShift, deltaX, deltaY, transform, type, compensate, y, fill, newAngle, zoomScaleX, zoomScaleY, newOrigin, offset; for (; i < transformsLength; i++) { transform = transforms[i]; type = transform.type; if (type == "translate") { matrix.translate(transform.x, transform.y); } else if (type == "rotate") { matrix.rotate(transform.degrees, transform.x, transform.y); deltaDegrees += transform.degrees; } else if (type == "scale") { matrix.scale(transform.x, transform.y, transform.centerX, transform.centerY); deltaScaleX *= transform.x; deltaScaleY *= transform.y; } } sprite.matrix = matrix.clone(); if (matrixOnly) { return; } if (shift) { matrix.prepend(shift.scale, 0, 0, shift.scale, shift.dx * shift.scale, shift.dy * shift.scale); } if (sprite.type != "image" && skew) { skew.origin = "0,0"; skew.matrix = matrix.toString(); offset = matrix.offset(); if (offset[0] > 32767) { offset[0] = 32767; } else if (offset[0] < -32768) { offset[0] = -32768; } if (offset[1] > 32767) { offset[1] = 32767; } else if (offset[1] < -32768) { offset[1] = -32768; } skew.offset = offset; } else { domStyle.filter = matrix.toFilter(); domStyle.left = Math.min( matrix.x(bbox.x, bbox.y), matrix.x(bbox.x + bbox.width, bbox.y), matrix.x(bbox.x, bbox.y + bbox.height), matrix.x(bbox.x + bbox.width, bbox.y + bbox.height)) + 'px'; domStyle.top = Math.min( matrix.y(bbox.x, bbox.y), matrix.y(bbox.x + bbox.width, bbox.y), matrix.y(bbox.x, bbox.y + bbox.height), matrix.y(bbox.x + bbox.width, bbox.y + bbox.height)) + 'px'; } }, createItem: function (config) { return Ext.create('Ext.draw.Sprite', config); }, getRegion: function () { return this.el.getRegion(); }, addCls: function (sprite, className) { if (sprite && sprite.el) { sprite.el.addCls(className); } }, removeCls: function (sprite, className) { if (sprite && sprite.el) { sprite.el.removeCls(className); } }, addGradient: function (gradient) { var gradients = this.gradientsColl || (this.gradientsColl = Ext.create('Ext.util.MixedCollection')), colors = [], stops = Ext.create('Ext.util.MixedCollection'), keys, items, iLen, key, item, i; stops.addAll(gradient.stops); stops.sortByKey("ASC", function (a, b) { a = parseInt(a, 10); b = parseInt(b, 10); return a > b ? 1 : (a < b ? -1 : 0); }); keys = stops.keys; items = stops.items; iLen = keys.length; for (i = 0; i < iLen; i++) { key = keys[i]; item = items[i]; colors.push(key + '% ' + item.color); } gradients.add(gradient.id, { colors: colors.join(","), angle: gradient.angle }); }, destroy: function () { var me = this; me.callParent(arguments); if (me.el) { me.el.remove(); } delete me.el; } }); Ext.define('Ext.flash.Component', { extend: Ext.Component , alternateClassName: 'Ext.FlashComponent', alias: 'widget.flash', flashVersion : '9.0.115', backgroundColor: '#ffffff', wmode: 'opaque', swfWidth: '100%', swfHeight: '100%', expressInstall: false, renderTpl: [''], initComponent: function() { this.callParent(); this.addEvents( 'success', 'failure' ); }, beforeRender: function(){ this.callParent(); Ext.applyIf(this.renderData, { swfId: this.getSwfId() }); }, afterRender: function() { var me = this, flashParams = Ext.apply({}, me.flashParams), flashVars = Ext.apply({}, me.flashVars); me.callParent(); flashParams = Ext.apply({ allowScriptAccess: 'always', bgcolor: me.backgroundColor, wmode: me.wmode }, flashParams); flashVars = Ext.apply({ allowedDomain: document.location.hostname }, flashVars); new swfobject.embedSWF( me.url, me.getSwfId(), me.swfWidth, me.swfHeight, me.flashVersion, me.expressInstall ? me.statics.EXPRESS_INSTALL_URL : undefined, flashVars, flashParams, me.flashAttributes, Ext.bind(me.swfCallback, me) ); }, swfCallback: function(e) { var me = this; if (e.success) { me.swf = Ext.get(e.ref); me.onSuccess(); me.fireEvent('success', me); } else { me.onFailure(); me.fireEvent('failure', me); } }, getSwfId: function() { return this.swfId || (this.swfId = "extswf" + this.getAutoId()); }, onSuccess: function() { this.swf.setStyle('visibility', 'inherit'); }, onFailure: Ext.emptyFn, beforeDestroy: function() { var me = this, swf = me.swf; if (swf) { swfobject.removeSWF(me.getSwfId()); Ext.destroy(swf); delete me.swf; } me.callParent(); }, statics: { EXPRESS_INSTALL_URL: 'http:/' + '/swfobject.googlecode.com/svn/trunk/swfobject/expressInstall.swf' } }); Ext.define('Ext.form.action.Action', { alternateClassName: 'Ext.form.Action', submitEmptyText : true, constructor: function(config) { if (config) { Ext.apply(this, config); } var params = config.params; if (Ext.isString(params)) { this.params = Ext.Object.fromQueryString(params); } }, run: Ext.emptyFn, onFailure : function(response){ this.response = response; this.failureType = Ext.form.action.Action.CONNECT_FAILURE; this.form.afterAction(this, false); }, processResponse : function(response){ this.response = response; if (!response.responseText && !response.responseXML) { return true; } return (this.result = this.handleResponse(response)); }, getUrl: function() { return this.url || this.form.url; }, getMethod: function() { return (this.method || this.form.method || 'POST').toUpperCase(); }, getParams: function() { return Ext.apply({}, this.params, this.form.baseParams); }, createCallback: function() { var me = this, undef, form = me.form; return { success: me.onSuccess, failure: me.onFailure, scope: me, timeout: (this.timeout * 1000) || (form.timeout * 1000), upload: form.fileUpload ? me.onSuccess : undef }; }, statics: { CLIENT_INVALID: 'client', SERVER_INVALID: 'server', CONNECT_FAILURE: 'connect', LOAD_FAILURE: 'load' } }); Ext.define('Ext.form.action.Load', { extend: Ext.form.action.Action , alternateClassName: 'Ext.form.Action.Load', alias: 'formaction.load', type: 'load', run: function() { Ext.Ajax.request(Ext.apply( this.createCallback(), { method: this.getMethod(), url: this.getUrl(), headers: this.headers, params: this.getParams() } )); }, onSuccess: function(response){ var result = this.processResponse(response), form = this.form; if (result === true || !result.success || !result.data) { this.failureType = Ext.form.action.Action.LOAD_FAILURE; form.afterAction(this, false); return; } form.clearInvalid(); form.setValues(result.data); form.afterAction(this, true); }, handleResponse: function(response) { var reader = this.form.reader, rs, data; if (reader) { rs = reader.read(response); data = rs.records && rs.records[0] ? rs.records[0].data : null; return { success : rs.success, data : data }; } return Ext.decode(response.responseText); } }); Ext.define('Ext.form.action.Submit', { extend: Ext.form.action.Action , alternateClassName: 'Ext.form.Action.Submit', alias: 'formaction.submit', type: 'submit', run : function(){ var me = this, form = me.form; if (me.clientValidation === false || form.isValid()) { me.doSubmit(); } else { me.failureType = Ext.form.action.Action.CLIENT_INVALID; form.afterAction(me, false); } }, doSubmit: function() { var me = this, ajaxOptions = Ext.apply(me.createCallback(), { url: me.getUrl(), method: me.getMethod(), headers: me.headers }), form = me.form, jsonSubmit = me.jsonSubmit || form.jsonSubmit, paramsProp = jsonSubmit ? 'jsonData' : 'params', formInfo; if (form.hasUpload()) { formInfo = me.buildForm(); ajaxOptions.form = formInfo.formEl; ajaxOptions.isUpload = true; } else { ajaxOptions[paramsProp] = me.getParams(jsonSubmit); } Ext.Ajax.request(ajaxOptions); if (formInfo) { me.cleanup(formInfo); } }, cleanup: function(formInfo) { var formEl = formInfo.formEl, uploadEls = formInfo.uploadEls, uploadFields = formInfo.uploadFields, len = uploadFields.length, i, field; for (i = 0; i < len; ++i) { field = uploadFields[i]; if (!field.clearOnSubmit) { field.restoreInput(uploadEls[i]); } } if (formEl) { Ext.removeNode(formEl); } }, getParams: function(useModelValues) { var falseVal = false, configParams = this.callParent(), fieldParams = this.form.getValues(falseVal, falseVal, this.submitEmptyText !== falseVal, useModelValues, true); return Ext.apply({}, fieldParams, configParams); }, buildForm: function() { var me = this, fieldsSpec = [], formSpec, formEl, basicForm = me.form, params = me.getParams(), uploadFields = [], uploadEls = [], fields = basicForm.getFields().items, i, len = fields.length, field, key, value, v, vLen, el; for (i = 0; i < len; ++i) { field = fields[i]; if (field.isFileUpload()) { uploadFields.push(field); } } for (key in params) { if (params.hasOwnProperty(key)) { value = params[key]; if (Ext.isArray(value)) { vLen = value.length; for (v = 0; v < vLen; v++) { fieldsSpec.push(me.getFieldConfig(key, value[v])); } } else { fieldsSpec.push(me.getFieldConfig(key, value)); } } } formSpec = { tag: 'form', role: 'presentation', action: me.getUrl(), method: me.getMethod(), target: me.target || '_self', style: 'display:none', cn: fieldsSpec }; if (uploadFields.length) { formSpec.encoding = formSpec.enctype = 'multipart/form-data'; } formEl = Ext.DomHelper.append(Ext.getBody(), formSpec); len = uploadFields.length; for (i = 0; i < len; ++i) { el = uploadFields[i].extractFileInput(); formEl.appendChild(el); uploadEls.push(el); } return { formEl: formEl, uploadFields: uploadFields, uploadEls: uploadEls }; }, getFieldConfig: function(name, value) { return { tag: 'input', type: 'hidden', name: name, value: Ext.String.htmlEncode(value) }; }, onSuccess: function(response) { var form = this.form, success = true, result = this.processResponse(response); if (result !== true && !result.success) { if (result.errors) { form.markInvalid(result.errors); } this.failureType = Ext.form.action.Action.SERVER_INVALID; success = false; } form.afterAction(this, success); }, handleResponse: function(response) { var form = this.form, errorReader = form.errorReader, rs, errors, i, len, records, result; if (errorReader) { rs = errorReader.read(response); records = rs.records; errors = []; if (records) { for(i = 0, len = records.length; i < len; i++) { errors[i] = records[i].data; } } if (errors.length < 1) { errors = null; } result = { success : rs.success, errors : errors }; } else { try { result = Ext.decode(response.responseText); } catch (e) { result = { success: false, errors: [] }; } } return result; } }); Ext.define('Ext.util.ComponentDragger', { extend: Ext.dd.DragTracker , autoStart: 500, constructor: function(comp, config) { this.comp = comp; this.initialConstrainTo = config.constrainTo; this.callParent([ config ]); }, onStart: function(e) { var me = this, comp = me.comp; me.startPosition = comp.getXY(); if (comp.ghost && !comp.liveDrag) { me.proxy = comp.ghost(); me.dragTarget = me.proxy.header.el; } if (me.constrain || me.constrainDelegate) { me.constrainTo = me.calculateConstrainRegion(); } if (comp.beginDrag) { comp.beginDrag(); } }, calculateConstrainRegion: function() { var me = this, comp = me.comp, constrainTo = me.initialConstrainTo, constraintInsets = comp.constraintInsets, constrainEl, delegateRegion, elRegion, dragEl = me.proxy ? me.proxy.el : comp.el, shadowSize = (!me.constrainDelegate && dragEl.shadow && comp.constrainShadow && !dragEl.shadowDisabled) ? dragEl.shadow.getShadowSize() : 0; if (!(constrainTo instanceof Ext.util.Region)) { constrainEl = Ext.fly(constrainTo); constrainTo = constrainEl.getViewRegion(); constrainTo.right = constrainTo.left + constrainEl.dom.clientWidth; } else { constrainTo = constrainTo.copy(); } if (constraintInsets) { constraintInsets = Ext.isObject(constraintInsets) ? constraintInsets : Ext.Element.parseBox(constraintInsets); constrainTo.adjust(constraintInsets.top, constraintInsets.right, constraintInsets.bottom, constraintInsets.length); } if (shadowSize) { constrainTo.adjust(shadowSize[0], -shadowSize[1], -shadowSize[2], shadowSize[3]); } if (!me.constrainDelegate) { delegateRegion = Ext.fly(me.dragTarget).getRegion(); elRegion = dragEl.getRegion(); constrainTo.adjust( delegateRegion.top - elRegion.top, delegateRegion.right - elRegion.right, delegateRegion.bottom - elRegion.bottom, delegateRegion.left - elRegion.left ); } return constrainTo; }, onDrag: function(e) { var me = this, comp = (me.proxy && !me.comp.liveDrag) ? me.proxy : me.comp, offset = me.getOffset(me.constrain || me.constrainDelegate ? 'dragTarget' : null); comp.setPagePosition(me.startPosition[0] + offset[0], me.startPosition[1] + offset[1]); }, onEnd: function(e) { var comp = this.comp; if (comp.isDestroyed || comp.destroying) { return; } if (this.proxy && !comp.liveDrag) { comp.unghost(); } if (comp.endDrag) { comp.endDrag(); } } }); Ext.define('Ext.window.Window', { extend: Ext.panel.Panel , alternateClassName: 'Ext.Window', alias: 'widget.window', baseCls: Ext.baseCSSPrefix + 'window', resizable: true, draggable: true, constrain: false, constrainHeader: false, plain: false, minimizable: false, maximizable: false, minHeight: 50, minWidth: 50, expandOnShow: true, collapsible: false, closable: true, hidden: true, autoRender: true, hideMode: 'offsets', floating: true, itemCls: Ext.baseCSSPrefix + 'window-item', initialAlphaNum: /^[a-z0-9]/, overlapHeader: true, ignoreHeaderBorderManagement: true, alwaysFramed: true, isRootCfg: { isRoot: true }, isWindow: true, ariaRole: 'dialog', initComponent: function() { var me = this; me.frame = false; me.callParent(); me.addEvents( 'resize', 'maximize', 'minimize', 'restore' ); if (me.plain) { me.addClsWithUI('plain'); } me.addStateEvents(['maximize', 'restore', 'resize', 'dragend']); }, getElConfig: function () { var me = this, elConfig; elConfig = me.callParent(); elConfig.tabIndex = -1; return elConfig; }, getState: function() { var me = this, state = me.callParent() || {}, maximized = !!me.maximized, ghostBox = me.ghostBox, pos; state.maximized = maximized; if (maximized) { pos = me.restorePos; } else if (ghostBox) { pos = [ghostBox.x, ghostBox.y]; } else { pos = me.getPosition(); } Ext.apply(state, { size: maximized ? me.restoreSize : me.getSize(), pos: pos }); return state; }, applyState: function(state){ var me = this; if (state) { me.maximized = state.maximized; if (me.maximized) { me.hasSavedRestore = true; me.restoreSize = state.size; me.restorePos = state.pos; } else { Ext.apply(me, { width: state.size.width, height: state.size.height, x: state.pos[0], y: state.pos[1] }); } } }, onRender: function(ct, position) { var me = this; me.callParent(arguments); me.focusEl = me.el; if (me.maximizable) { me.header.on({ scope: me, dblclick: me.toggleMaximize }); } }, afterRender: function() { var me = this, header = me.header, keyMap; me.callParent(); if (me.maximized) { me.maximized = false; me.maximize(); if (header) { header.removeCls(header.indicateDragCls) } } if (me.closable) { keyMap = me.getKeyMap(); keyMap.on(27, me.onEsc, me); } else { keyMap = me.keyMap; } if (keyMap && me.hidden) { keyMap.disable(); } }, initDraggable: function() { this.initSimpleDraggable(); }, initResizable: function(){ this.callParent(arguments); if (this.maximized) { this.resizer.disable(); } }, onEsc: function(k, e) { if (!Ext.FocusManager || !Ext.FocusManager.enabled || Ext.FocusManager.focusedCmp === this) { e.stopEvent(); this.close(); } }, beforeDestroy: function() { var me = this; if (me.rendered) { delete this.animateTarget; me.hide(); Ext.destroy( me.keyMap ); } me.callParent(); }, addTools: function() { var me = this; me.callParent(); if (me.minimizable) { me.addTool({ type: 'minimize', handler: Ext.Function.bind(me.minimize, me, []) }); } if (me.maximizable) { me.addTool({ type: 'maximize', handler: Ext.Function.bind(me.maximize, me, []) }); me.addTool({ type: 'restore', handler: Ext.Function.bind(me.restore, me, []), hidden: true }); } }, getFocusEl: function() { return this.getDefaultFocus(); }, getDefaultFocus: function() { var me = this, result, defaultComp = me.defaultButton || me.defaultFocus, selector; if (defaultComp !== undefined) { if (Ext.isNumber(defaultComp)) { result = me.query('button')[defaultComp]; } else if (Ext.isString(defaultComp)) { selector = defaultComp; if (selector.match(me.initialAlphaNum)) { result = me.down('#' + selector); } if (!result) { result = me.down(selector); } } else if (defaultComp.focus) { result = defaultComp; } } return result || me.el; }, onFocus: function() { var me = this, focusDescendant; if ((Ext.FocusManager && Ext.FocusManager.enabled) || ((focusDescendant = me.getDefaultFocus()) === me)) { me.callParent(arguments); } else { focusDescendant.focus(); } }, onShow: function() { var me = this; me.callParent(arguments); if (me.expandOnShow) { me.expand(false); } me.syncMonitorWindowResize(); if (me.keyMap) { me.keyMap.enable(); } }, doClose: function() { var me = this; if (me.hidden) { me.fireEvent('close', me); if (me.closeAction == 'destroy') { this.destroy(); } } else { me.hide(me.animateTarget, me.doClose, me); } }, afterHide: function() { var me = this; me.syncMonitorWindowResize(); if (me.keyMap) { me.keyMap.disable(); } me.callParent(arguments); }, onWindowResize: function() { var me = this, sizeModel; if (me.maximized) { me.fitContainer(); } else { sizeModel = me.getSizeModel(); if (sizeModel.width.natural || sizeModel.height.natural) { me.updateLayout(); } me.doConstrain(); } }, minimize: function() { this.fireEvent('minimize', this); return this; }, resumeHeaderLayout: function(changed) { this.header.resumeLayouts(changed ? this.isRootCfg : null); }, afterCollapse: function() { var me = this, header = me.header, tools = me.tools; if (header && me.maximizable) { header.suspendLayouts(); tools.maximize.hide(); tools.restore.hide(); this.resumeHeaderLayout(true); } if (me.resizer) { me.resizer.disable(); } me.callParent(arguments); }, afterExpand: function() { var me = this, header = me.header, tools = me.tools, changed; if (header) { header.suspendLayouts(); if (me.maximized) { tools.restore.show(); changed = true; } else if (me.maximizable) { tools.maximize.show(); changed = true; } this.resumeHeaderLayout(changed); } if (me.resizer) { me.resizer.enable(); } me.callParent(arguments); }, maximize: function(animate) { var me = this, header = me.header, tools = me.tools, width = me.width, height = me.height, restore, changed; if (!me.maximized) { me.expand(false); if (!me.hasSavedRestore) { restore = me.restoreSize = { width: Ext.isNumber(width) ? width : null, height: Ext.isNumber(height) ? height : null }; me.restorePos = me.getPosition(true); } if (header) { header.suspendLayouts(); if (tools.maximize) { tools.maximize.hide(); changed = true; } if (tools.restore) { tools.restore.show(); changed = true; } if (me.collapseTool) { me.collapseTool.hide(); changed = true; } me.resumeHeaderLayout(changed); } me.el.disableShadow(); if (me.dd) { me.dd.disable(); if (header) { header.removeCls(header.indicateDragCls) } } if (me.resizer) { me.resizer.disable(); } me.el.addCls(Ext.baseCSSPrefix + 'window-maximized'); me.container.addCls(Ext.baseCSSPrefix + 'window-maximized-ct'); me.syncMonitorWindowResize(); me.fitContainer(animate = (animate || !!me.animateTarget) ? { callback: function() { me.maximized = true; me.fireEvent('maximize', me); } } : null); if (!animate) { me.maximized = true; me.fireEvent('maximize', me); } } return me; }, restore: function(animate) { var me = this, tools = me.tools, header = me.header, newBox = me.restoreSize, changed; if (me.maximized) { me.hasSavedRestore = null; me.removeCls(Ext.baseCSSPrefix + 'window-maximized'); if (header) { header.suspendLayouts(); if (tools.restore) { tools.restore.hide(); changed = true; } if (tools.maximize) { tools.maximize.show(); changed = true; } if (me.collapseTool) { me.collapseTool.show(); changed = true; } me.resumeHeaderLayout(changed); } newBox.x = me.restorePos[0]; newBox.y = me.restorePos[1]; me.setBox(newBox, animate = (animate || !!me.animateTarget) ? { callback: function() { me.el.enableShadow(true); me.maximized = false; me.fireEvent('restore', me); } } : null); me.restorePos = me.restoreSize = null; if (me.dd) { me.dd.enable(); if (header) { header.addCls(header.indicateDragCls) } } if (me.resizer) { me.resizer.enable(); } me.container.removeCls(Ext.baseCSSPrefix + 'window-maximized-ct'); me.syncMonitorWindowResize(); if (!animate) { me.el.enableShadow(true); me.maximized = false; me.fireEvent('restore', me); } } return me; }, syncMonitorWindowResize: function () { var me = this, currentlyMonitoring = me._monitoringResize, yes = me.monitorResize || me.constrain || me.constrainHeader || me.maximized, veto = me.hidden || me.destroying || me.isDestroyed; if (yes && !veto) { if (!currentlyMonitoring) { Ext.EventManager.onWindowResize(me.onWindowResize, me, {delay: 1}); me._monitoringResize = true; } } else if (currentlyMonitoring) { Ext.EventManager.removeResizeListener(me.onWindowResize, me); me._monitoringResize = false; } }, toggleMaximize: function() { return this[this.maximized ? 'restore': 'maximize'](); }, createGhost: function() { var ghost = this.callParent(arguments); ghost.xtype = 'window'; return ghost; } }); Ext.define("Ext.form.Labelable", { isLabelable: true, autoEl: { tag: 'table', cellpadding: 0, role: 'presentation' }, childEls: [ 'labelCell', 'labelEl', 'bodyEl', 'sideErrorCell', 'errorEl', 'inputRow' ], labelableRenderTpl: [ 'id="{id}"
class="{inputRowCls}">', '', '', '{beforeLabelTpl}', '', ' class="{labelCls}"', ' style="{labelStyle}"', ' unselectable="on"', '>', '{beforeLabelTextTpl}', '{fieldLabel}', '', '{labelSeparator}', '', '', '{afterLabelTextTpl}', '', '{afterLabelTpl}', '', '
', '', '{beforeBodyEl}', '', '{beforeLabelTpl}', '', '{afterLabelTpl}', '', '{beforeSubTpl}', '{[values.$comp.getSubTplMarkup(values)]}', '{afterSubTpl}', '', '{afterBodyEl}', '', '', '', '', '', '', '{afterBodyEl}', '', '', '', { disableFormats: true } ], activeErrorsTpl: undefined, htmlActiveErrorsTpl: [ '', '
    ', '', '
    {fieldLabel}
    ', '
    ', '
  • {.}
  • ', '
', '
' ], plaintextActiveErrorsTpl: [ '', '', '{fieldLabel}\n', '', '\n{.}', '' ], isFieldLabelable: true, formItemCls: Ext.baseCSSPrefix + 'form-item', labelCls: Ext.baseCSSPrefix + 'form-item-label', errorMsgCls: Ext.baseCSSPrefix + 'form-error-msg', baseBodyCls: Ext.baseCSSPrefix + 'form-item-body', inputRowCls: Ext.baseCSSPrefix + 'form-item-input-row', fieldBodyCls: '', clearCls: Ext.baseCSSPrefix + 'clear', invalidCls : Ext.baseCSSPrefix + 'form-invalid', fieldLabel: undefined, labelAlign : 'left', labelWidth: 100, labelPad : 5, labelSeparator : ':', hideLabel: false, hideEmptyLabel: true, preventMark: false, autoFitErrors: true, msgTarget: 'qtip', noWrap: true, labelableInsertions: [ 'beforeBodyEl', 'afterBodyEl', 'beforeLabelTpl', 'afterLabelTpl', 'beforeSubTpl', 'afterSubTpl', 'beforeLabelTextTpl', 'afterLabelTextTpl', 'labelAttrTpl' ], labelableRenderProps: ['allowBlank', 'id', 'labelAlign', 'fieldBodyCls', 'extraFieldBodyCls', 'baseBodyCls', 'clearCls', 'labelSeparator', 'msgTarget', 'inputRowCls'], initLabelable: function() { var me = this, padding = me.padding; if (padding) { me.padding = undefined; me.extraMargins = Ext.Element.parseBox(padding); } if (!me.activeErrorsTpl) { if (me.msgTarget == 'title') { me.activeErrorsTpl = me.plaintextActiveErrorsTpl; } else { me.activeErrorsTpl = me.htmlActiveErrorsTpl; } } me.addCls(Ext.plainTableCls); me.addCls(me.formItemCls); me.lastActiveError = ''; me.addEvents( 'errorchange' ); me.enableBubble('errorchange'); }, trimLabelSeparator: function() { var me = this, separator = me.labelSeparator, label = me.fieldLabel || '', lastChar = label.substr(label.length - 1); return lastChar === separator ? label.slice(0, -1) : label; }, getFieldLabel: function() { return this.trimLabelSeparator(); }, setFieldLabel: function(label){ label = label || ''; var me = this, separator = me.labelSeparator, labelEl = me.labelEl; me.fieldLabel = label; if (me.rendered) { if (Ext.isEmpty(label) && me.hideEmptyLabel) { labelEl.parent().setDisplayed('none'); } else { if (separator) { label = me.trimLabelSeparator() + separator; } labelEl.update(label); labelEl.parent().setDisplayed(''); } me.updateLayout(); } }, getInsertionRenderData: function (data, names) { var i = names.length, name, value; while (i--) { name = names[i]; value = this[name]; if (value) { if (typeof value != 'string') { if (!value.isTemplate) { value = Ext.XTemplate.getTpl(this, name); } value = value.apply(data); } } data[name] = value || ''; } return data; }, getLabelableRenderData: function() { var me = this, data, tempEl, topLabel = me.labelAlign === 'top'; if (!Ext.form.Labelable.errorIconWidth) { tempEl = Ext.getBody().createChild({style: 'position:absolute', cls: Ext.baseCSSPrefix + 'form-invalid-icon'}); Ext.form.Labelable.errorIconWidth = tempEl.getWidth() + tempEl.getMargin('l'); tempEl.remove(); } data = Ext.copyTo({ inFormLayout : me.ownerLayout && me.ownerLayout.type === 'form', inputId : me.getInputId(), labelOnLeft : !topLabel, hideLabel : !me.hasVisibleLabel(), fieldLabel : me.getFieldLabel(), labelCellStyle : me.getLabelCellStyle(), labelCellAttrs : me.getLabelCellAttrs(), labelCls : me.getLabelCls(), labelStyle : me.getLabelStyle(), bodyColspan : me.getBodyColspan(), externalError : !me.autoFitErrors, errorMsgCls : me.getErrorMsgCls(), errorIconWidth : Ext.form.Labelable.errorIconWidth, boxLabel : me.boxLabel }, me, me.labelableRenderProps, true); me.getInsertionRenderData(data, me.labelableInsertions); return data; }, xhooks: { beforeRender: function() { var me = this; me.setFieldDefaults(me.getHierarchyState().fieldDefaults); if (me.ownerLayout) { me.addCls(Ext.baseCSSPrefix + me.ownerLayout.type + '-form-item'); } }, onRender: function() { var me = this, margins, side, style = {}; if (me.extraMargins) { margins = me.el.getMargin(); for (side in margins) { if (margins.hasOwnProperty(side)) { style['margin-' + side] = (margins[side] + me.extraMargins[side]) + 'px'; } } me.el.setStyle(style); } } }, hasVisibleLabel: function(){ if (this.hideLabel) { return false; } return !(this.hideEmptyLabel && !this.getFieldLabel()); }, getLabelWidth: function(){ var me = this; if (!me.hasVisibleLabel()) { return 0; } return me.labelWidth + me.labelPad; }, getBodyColspan: function() { var me = this, result; if (me.msgTarget === 'side' && (!me.autoFitErrors || me.hasActiveError())) { result = 1; } else { result = 2; } if (me.labelAlign !== 'top' && !me.hasVisibleLabel()) { result++; } return result; }, getLabelCls: function() { var labelCls = this.labelCls + ' ' + Ext.dom.Element.unselectableCls, labelClsExtra = this.labelClsExtra; return labelClsExtra ? labelCls + ' ' + labelClsExtra : labelCls; }, getLabelCellStyle: function() { var me = this, hideLabelCell = me.hideLabel || (!me.getFieldLabel() && me.hideEmptyLabel); return hideLabelCell ? 'display:none;' : ''; }, getErrorMsgCls: function() { var me = this, hideLabelCell = (me.hideLabel || (!me.fieldLabel && me.hideEmptyLabel)); return me.errorMsgCls + (!hideLabelCell && me.labelAlign === 'top' ? ' ' + Ext.baseCSSPrefix + 'lbl-top-err-icon' : ''); }, getLabelCellAttrs: function() { var me = this, labelAlign = me.labelAlign, result = ''; if (labelAlign !== 'top') { result = 'valign="top" halign="' + labelAlign + '" width="' + (me.labelWidth + me.labelPad) + '"'; } return result + ' class="' + Ext.baseCSSPrefix + 'field-label-cell"'; }, getLabelStyle: function(){ var me = this, labelPad = me.labelPad, labelStyle = ''; if (me.labelAlign !== 'top') { if (me.labelWidth) { labelStyle = 'width:' + me.labelWidth + 'px;'; } if (labelPad) { labelStyle += 'margin-right:' + labelPad + 'px;'; } } return labelStyle + (me.labelStyle || ''); }, getSubTplMarkup: function() { return ''; }, getInputId: function() { return ''; }, getActiveError : function() { return this.activeError || ''; }, hasActiveError: function() { return !!this.getActiveError(); }, setActiveError: function(msg) { this.setActiveErrors(msg); }, getActiveErrors: function() { return this.activeErrors || []; }, setActiveErrors: function(errors) { var me = this, tpl; errors = Ext.Array.from(errors); tpl = me.getTpl('activeErrorsTpl'); me.activeErrors = errors; me.activeError = tpl.apply({ fieldLabel: me.fieldLabel, errors: errors, listCls: Ext.plainListCls }); me.renderActiveError(); }, unsetActiveError: function() { delete this.activeError; delete this.activeErrors; this.renderActiveError(); }, renderActiveError: function() { var me = this, activeError = me.getActiveError(), hasError = !!activeError; if (activeError !== me.lastActiveError) { me.fireEvent('errorchange', me, activeError); me.lastActiveError = activeError; } if (me.rendered && !me.isDestroyed && !me.preventMark) { me.el[hasError ? 'addCls' : 'removeCls'](me.invalidCls); if (me.errorEl) { me.errorEl.dom.innerHTML = activeError; } } }, setFieldDefaults: function(defaults) { var key; for (key in defaults) { if (!this.hasOwnProperty(key)) { this[key] = defaults[key]; } } } }); Ext.define('Ext.form.field.Field', { isFormField : true, disabled : false, submitValue: true, validateOnChange: true, suspendCheckChange: 0, initField: function() { this.addEvents( 'change', 'validitychange', 'dirtychange' ); this.initValue(); }, initValue: function() { var me = this; me.value = me.transformOriginalValue(me.value); me.originalValue = me.lastValue = me.value; me.suspendCheckChange++; me.setValue(me.value); me.suspendCheckChange--; }, transformOriginalValue: Ext.identityFn, getName: function() { return this.name; }, getValue: function() { return this.value; }, setValue: function(value) { var me = this; me.value = value; me.checkChange(); return me; }, isEqual: function(value1, value2) { return String(value1) === String(value2); }, isEqualAsString: function(value1, value2){ return String(Ext.value(value1, '')) === String(Ext.value(value2, '')); }, getSubmitData: function() { var me = this, data = null; if (!me.disabled && me.submitValue) { data = {}; data[me.getName()] = '' + me.getValue(); } return data; }, getModelData: function(includeEmptyText, isSubmitting) { var me = this, data = null; if (!me.disabled && (me.submitValue || !isSubmitting)) { data = {}; data[me.getName()] = me.getValue(); } return data; }, reset : function(){ var me = this; me.beforeReset(); me.setValue(me.originalValue); me.clearInvalid(); delete me.wasValid; }, beforeReset: Ext.emptyFn, resetOriginalValue: function() { this.originalValue = this.getValue(); this.checkDirty(); }, checkChange: function() { var me = this, newVal, oldVal; if (!me.suspendCheckChange) { newVal = me.getValue(); oldVal = me.lastValue; if (!me.isDestroyed && me.didValueChange(newVal, oldVal)) { me.lastValue = newVal; me.fireEvent('change', me, newVal, oldVal); me.onChange(newVal, oldVal); } } }, didValueChange: function(newVal, oldVal){ return !this.isEqual(newVal, oldVal); }, onChange: function(newVal, oldVal) { if (this.validateOnChange) { this.validate(); } this.checkDirty(); }, isDirty : function() { var me = this; return !me.disabled && !me.isEqual(me.getValue(), me.originalValue); }, checkDirty: function() { var me = this, isDirty = me.isDirty(); if (isDirty !== me.wasDirty) { me.fireEvent('dirtychange', me, isDirty); me.onDirtyChange(isDirty); me.wasDirty = isDirty; } }, onDirtyChange: Ext.emptyFn, getErrors: function(value) { return []; }, isValid : function() { var me = this; return me.disabled || Ext.isEmpty(me.getErrors()); }, validate : function() { var me = this, isValid = me.isValid(); if (isValid !== me.wasValid) { me.wasValid = isValid; me.fireEvent('validitychange', me, isValid); } return isValid; }, batchChanges: function(fn) { try { this.suspendCheckChange++; fn(); } catch(e){ throw e; } finally { this.suspendCheckChange--; } this.checkChange(); }, isFileUpload: function() { return false; }, extractFileInput: function() { return null; }, markInvalid: Ext.emptyFn, clearInvalid: Ext.emptyFn }); Ext.define('Ext.layout.component.field.Field', { extend: Ext.layout.component.Auto , alias: 'layout.field', type: 'field', naturalSizingProp: 'size', beginLayout: function(ownerContext) { var me = this, owner = me.owner; me.callParent(arguments); ownerContext.labelStrategy = me.getLabelStrategy(); ownerContext.errorStrategy = me.getErrorStrategy(); ownerContext.labelContext = ownerContext.getEl('labelEl'); ownerContext.bodyCellContext = ownerContext.getEl('bodyEl'); ownerContext.inputContext = ownerContext.getEl('inputEl'); ownerContext.errorContext = ownerContext.getEl('errorEl'); if (Ext.isIE7m && Ext.isStrict && ownerContext.inputContext) { me.ieInputWidthAdjustment = ownerContext.inputContext.getPaddingInfo().width + ownerContext.inputContext.getBorderInfo().width; } ownerContext.labelStrategy.prepare(ownerContext, owner); ownerContext.errorStrategy.prepare(ownerContext, owner); }, beginLayoutCycle: function(ownerContext){ var me = this, owner = me.owner, widthModel = ownerContext.widthModel, ownerNaturalSize = owner[me.naturalSizingProp], width; me.callParent(arguments); if (widthModel.shrinkWrap) { me.beginLayoutShrinkWrap(ownerContext); } else if (widthModel.natural) { if (typeof ownerNaturalSize == 'number' && !owner.inputWidth) { me.beginLayoutFixed(ownerContext, (width = ownerNaturalSize * 6.5 + 20), 'px'); } else { me.beginLayoutShrinkWrap(ownerContext); } ownerContext.setWidth(width, false); } else { me.beginLayoutFixed(ownerContext, '100', '%'); } }, beginLayoutFixed: function (ownerContext, width, suffix) { var owner = ownerContext.target, inputEl = owner.inputEl, inputWidth = owner.inputWidth; owner.el.setStyle('table-layout', 'fixed'); owner.bodyEl.setStyle('width', width + suffix); if (inputEl) { if (inputWidth) { inputEl.setStyle('width', inputWidth + 'px'); } else { inputEl.setStyle('width', owner.stretchInputElFixed ? '100%' : ''); } } ownerContext.isFixed = true; }, beginLayoutShrinkWrap: function (ownerContext) { var owner = ownerContext.target, inputEl = owner.inputEl, inputWidth = owner.inputWidth; if (inputEl && inputEl.dom) { inputEl.dom.removeAttribute('size'); if (inputWidth) { inputEl.setStyle('width', inputWidth + 'px'); } else { inputEl.setStyle('width', ''); } } owner.el.setStyle('table-layout', 'auto'); owner.bodyEl.setStyle('width', ''); }, finishedLayout: function(ownerContext){ var owner = this.owner; this.callParent(arguments); ownerContext.labelStrategy.finishedLayout(ownerContext, owner); ownerContext.errorStrategy.finishedLayout(ownerContext, owner); }, calculateOwnerHeightFromContentHeight: function(ownerContext, contentHeight) { return contentHeight; }, measureContentHeight: function (ownerContext) { return ownerContext.el.getHeight(); }, measureContentWidth: function (ownerContext) { return ownerContext.el.getWidth(); }, measureLabelErrorHeight: function (ownerContext) { return ownerContext.labelStrategy.getHeight(ownerContext) + ownerContext.errorStrategy.getHeight(ownerContext); }, onFocus: function() { this.getErrorStrategy().onFocus(this.owner); }, getLabelStrategy: function() { var me = this, strategies = me.labelStrategies, labelAlign = me.owner.labelAlign; return strategies[labelAlign] || strategies.base; }, getErrorStrategy: function() { var me = this, owner = me.owner, strategies = me.errorStrategies, msgTarget = owner.msgTarget; return !owner.preventMark && Ext.isString(msgTarget) ? (strategies[msgTarget] || strategies.elementId) : strategies.none; }, labelStrategies: (function() { var base = { prepare: function(ownerContext, owner) { var cls = owner.labelCls + '-' + owner.labelAlign, labelEl = owner.labelEl; if (labelEl) { labelEl.addCls(cls); } }, getHeight: function () { return 0; }, finishedLayout: Ext.emptyFn }; return { base: base, top: Ext.applyIf({ getHeight: function (ownerContext) { var labelContext = ownerContext.labelContext, props = labelContext.props, height = props.height; if (height === undefined) { props.height = height = labelContext.el.getHeight() + labelContext.getMarginInfo().height; } return height; } }, base), left: base, right: base }; }()), errorStrategies: (function() { function showTip(owner) { var tip = Ext.layout.component.field.Field.tip, target; if (tip && tip.isVisible()) { target = tip.activeTarget; if (target && target.el === owner.getActionEl().dom) { tip.toFront(true); } } } var applyIf = Ext.applyIf, emptyFn = Ext.emptyFn, iconCls = Ext.baseCSSPrefix + 'form-invalid-icon', iconWidth, base = { prepare: function(ownerContext, owner) { var el = owner.errorEl; if (el) { el.setDisplayed(false); } }, getHeight: function () { return 0; }, onFocus: emptyFn, finishedLayout: emptyFn }; return { none: base, side: applyIf({ prepare: function(ownerContext, owner) { var errorEl = owner.errorEl, sideErrorCell = owner.sideErrorCell, displayError = owner.hasActiveError(), tempEl; if (!iconWidth) { iconWidth = (tempEl = Ext.getBody().createChild({style: 'position:absolute', cls: iconCls})).getWidth(); tempEl.remove(); } errorEl.addCls(iconCls); errorEl.set({'data-errorqtip': owner.getActiveError() || ''}); if (owner.autoFitErrors) { errorEl.setDisplayed(displayError); } else { errorEl.setVisible(displayError); } if (sideErrorCell && owner.autoFitErrors) { sideErrorCell.setDisplayed(displayError); } owner.bodyEl.dom.colSpan = owner.getBodyColspan(); Ext.layout.component.field.Field.initTip(); }, onFocus: showTip }, base), under: applyIf({ prepare: function(ownerContext, owner) { var errorEl = owner.errorEl, cls = Ext.baseCSSPrefix + 'form-invalid-under'; errorEl.addCls(cls); errorEl.setDisplayed(owner.hasActiveError()); }, getHeight: function (ownerContext) { var height = 0, errorContext, props; if (ownerContext.target.hasActiveError()) { errorContext = ownerContext.errorContext; props = errorContext.props; height = props.height; if (height === undefined) { props.height = height = errorContext.el.getHeight(); } } return height; } }, base), qtip: applyIf({ prepare: function(ownerContext, owner) { Ext.layout.component.field.Field.initTip(); owner.getActionEl().dom.setAttribute('data-errorqtip', owner.getActiveError() || ''); }, onFocus: showTip }, base), title: applyIf({ prepare: function(ownerContext, owner) { owner.getActionEl().dom.setAttribute('title', owner.getActiveError() || ''); } }, base), elementId: applyIf({ prepare: function(ownerContext, owner) { var targetEl = Ext.fly(owner.msgTarget); if (targetEl) { targetEl.dom.innerHTML = owner.getActiveError() || ''; targetEl.setDisplayed(owner.hasActiveError()); } } }, base) }; }()), statics: { initTip: function() { var tip = this.tip; if (!tip) { tip = this.tip = Ext.create('Ext.tip.QuickTip', { ui: 'form-invalid' }); tip.tagConfig = Ext.apply({}, {attribute: 'errorqtip'}, tip.tagConfig); } }, destroyTip: function() { var tip = this.tip; if (tip) { tip.destroy(); delete this.tip; } } } }); Ext.define('Ext.form.field.Base', { extend: Ext.Component , mixins: { labelable: Ext.form.Labelable , field: Ext.form.field.Field }, alias: 'widget.field', alternateClassName: ['Ext.form.Field', 'Ext.form.BaseField'], fieldSubTpl: [ ' name="{name}"
', ' value="{[Ext.util.Format.htmlEncode(values.value)]}"', ' placeholder="{placeholder}"', '{%if (values.maxLength !== undefined){%} maxlength="{maxLength}"{%}%}', ' readonly="readonly"', ' disabled="disabled"', ' tabIndex="{tabIdx}"', ' style="{fieldStyle}"', ' class="{fieldCls} {typeCls} {editableCls} {inputCls}" autocomplete="off"/>', { disableFormats: true } ], subTplInsertions: [ 'inputAttrTpl' ], inputType: 'text', invalidText : 'The value in this field is invalid', fieldCls : Ext.baseCSSPrefix + 'form-field', focusCls : 'form-focus', dirtyCls : Ext.baseCSSPrefix + 'form-dirty', checkChangeEvents: Ext.isIE && (!document.documentMode || document.documentMode < 9) ? ['change', 'propertychange', 'keyup'] : ['change', 'input', 'textInput', 'keyup', 'dragdrop'], checkChangeBuffer: 50, componentLayout: 'field', readOnly : false, readOnlyCls: Ext.baseCSSPrefix + 'form-readonly', validateOnBlur: true, hasFocus : false, baseCls: Ext.baseCSSPrefix + 'field', maskOnDisable: false, stretchInputElFixed: true, initComponent : function() { var me = this; me.callParent(); me.subTplData = me.subTplData || {}; me.addEvents( 'specialkey', 'writeablechange' ); me.initLabelable(); me.initField(); if (!me.name) { me.name = me.getInputId(); } if (me.readOnly) { me.addCls(me.readOnlyCls); } me.addCls(Ext.baseCSSPrefix + 'form-type-' + me.inputType); }, getInputId: function() { return this.inputId || (this.inputId = this.id + '-inputEl'); }, getSubTplData: function() { var me = this, type = me.inputType, inputId = me.getInputId(), data; data = Ext.apply({ id : inputId, cmpId : me.id, name : me.name || inputId, disabled : me.disabled, readOnly : me.readOnly, value : me.getRawValue(), type : type, fieldCls : me.fieldCls, fieldStyle : me.getFieldStyle(), tabIdx : me.tabIndex, inputCls : me.inputCls, typeCls : Ext.baseCSSPrefix + 'form-' + (type === 'password' ? 'text' : type), role : me.ariaRole }, me.subTplData); me.getInsertionRenderData(data, me.subTplInsertions); return data; }, applyRenderSelectors: function() { var me = this; me.callParent(); me.addChildEls('inputEl'); me.inputEl = me.el.getById(me.getInputId()); }, getSubTplMarkup: function() { return this.getTpl('fieldSubTpl').apply(this.getSubTplData()); }, initRenderTpl: function() { var me = this; if (!me.hasOwnProperty('renderTpl')) { me.renderTpl = me.getTpl('labelableRenderTpl'); } return me.callParent(); }, initRenderData: function() { return Ext.applyIf(this.callParent(), this.getLabelableRenderData()); }, setFieldStyle: function(style) { var me = this, inputEl = me.inputEl; if (inputEl) { inputEl.applyStyles(style); } me.fieldStyle = style; }, getFieldStyle: function() { var style = this.fieldStyle; return Ext.isObject(style) ? Ext.DomHelper.generateStyles(style, null, true) : style || ''; }, onRender : function() { this.callParent(arguments); this.renderActiveError(); }, getFocusEl: function() { return this.inputEl; }, isFileUpload: function() { return this.inputType === 'file'; }, getSubmitData: function() { var me = this, data = null, val; if (!me.disabled && me.submitValue) { val = me.getSubmitValue(); if (val !== null) { data = {}; data[me.getName()] = val; } } return data; }, getSubmitValue: function() { return this.processRawValue(this.getRawValue()); }, getRawValue: function() { var me = this, v = (me.inputEl ? me.inputEl.getValue() : Ext.value(me.rawValue, '')); me.rawValue = v; return v; }, setRawValue: function(value) { var me = this; value = Ext.value(me.transformRawValue(value), ''); me.rawValue = value; if (me.inputEl) { me.inputEl.dom.value = value; } return value; }, transformRawValue: Ext.identityFn, valueToRaw: function(value) { return '' + Ext.value(value, ''); }, rawToValue: Ext.identityFn, processRawValue: Ext.identityFn, getValue: function() { var me = this, val = me.rawToValue(me.processRawValue(me.getRawValue())); me.value = val; return val; }, setValue: function(value) { var me = this; me.setRawValue(me.valueToRaw(value)); return me.mixins.field.setValue.call(me, value); }, onBoxReady: function() { var me = this; me.callParent(); if (me.setReadOnlyOnBoxReady) { me.setReadOnly(me.readOnly); } }, onDisable: function() { var me = this, inputEl = me.inputEl; me.callParent(); if (inputEl) { inputEl.dom.disabled = true; if (me.hasActiveError()) { me.clearInvalid(); me.needsValidateOnEnable = true; } } }, onEnable: function() { var me = this, inputEl = me.inputEl; me.callParent(); if (inputEl) { inputEl.dom.disabled = false; if (me.needsValidateOnEnable) { delete me.needsValidateOnEnable; me.forceValidation = true; me.isValid(); delete me.forceValidation; } } }, setReadOnly: function(readOnly) { var me = this, inputEl = me.inputEl; readOnly = !!readOnly; me[readOnly ? 'addCls' : 'removeCls'](me.readOnlyCls); me.readOnly = readOnly; if (inputEl) { inputEl.dom.readOnly = readOnly; } else if (me.rendering) { me.setReadOnlyOnBoxReady = true; } me.fireEvent('writeablechange', me, readOnly); }, fireKey: function(e){ if(e.isSpecialKey()){ this.fireEvent('specialkey', this, new Ext.EventObjectImpl(e)); } }, initEvents : function(){ var me = this, inputEl = me.inputEl, onChangeTask, onChangeEvent, events = me.checkChangeEvents, e, eLen = events.length, event; if (inputEl) { me.mon(inputEl, Ext.EventManager.getKeyEvent(), me.fireKey, me); onChangeTask = new Ext.util.DelayedTask(me.checkChange, me); me.onChangeEvent = onChangeEvent = function() { onChangeTask.delay(me.checkChangeBuffer); }; for (e = 0; e < eLen; e++) { event = events[e]; if (event === 'propertychange') { me.usesPropertychange = true; } me.mon(inputEl, event, onChangeEvent); } } me.callParent(); }, doComponentLayout: function() { var me = this, inputEl = me.inputEl, usesPropertychange = me.usesPropertychange, ename = 'propertychange', onChangeEvent = me.onChangeEvent; if (usesPropertychange) { me.mun(inputEl, ename, onChangeEvent); } me.callParent(arguments); if (usesPropertychange) { me.mon(inputEl, ename, onChangeEvent); } }, onDirtyChange: function(isDirty) { this[isDirty ? 'addCls' : 'removeCls'](this.dirtyCls); }, isValid : function() { var me = this, disabled = me.disabled, validate = me.forceValidation || !disabled; return validate ? me.validateValue(me.processRawValue(me.getRawValue())) : disabled; }, validateValue: function(value) { var me = this, errors = me.getErrors(value), isValid = Ext.isEmpty(errors); if (!me.preventMark) { if (isValid) { me.clearInvalid(); } else { me.markInvalid(errors); } } return isValid; }, markInvalid : function(errors) { var me = this, oldMsg = me.getActiveError(), active; me.setActiveErrors(Ext.Array.from(errors)); active = me.getActiveError(); if (oldMsg !== active) { me.setError(active); } }, clearInvalid : function() { var me = this, hadError = me.hasActiveError(); delete me.needsValidateOnEnable; me.unsetActiveError(); if (hadError) { me.setError(''); } }, setError: function(active){ var me = this, msgTarget = me.msgTarget, prop; if (me.rendered) { if (msgTarget == 'title' || msgTarget == 'qtip') { if (me.rendered) { prop = msgTarget == 'qtip' ? 'data-errorqtip' : 'title'; } me.getActionEl().dom.setAttribute(prop, active || ''); } else { me.updateLayout(); } } }, renderActiveError: function() { var me = this, hasError = me.hasActiveError(); if (me.inputEl) { me.inputEl[hasError ? 'addCls' : 'removeCls'](me.invalidCls + '-field'); } me.mixins.labelable.renderActiveError.call(me); }, getActionEl: function() { return this.inputEl || this.el; } }); Ext.define('Ext.form.field.VTypes', (function(){ var alpha = /^[a-zA-Z_]+$/, alphanum = /^[a-zA-Z0-9_]+$/, email = /^(")?(?:[^\."])(?:(?:[\.])?(?:[\w\-!#$%&'*+/=?^_`{|}~]))*\1@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/, url = /(((^https?)|(^ftp)):\/\/((([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*)|(localhost|LOCALHOST))\/?)/i; return { singleton: true, alternateClassName: 'Ext.form.VTypes', 'email' : function(v){ return email.test(v); }, 'emailText' : 'This field should be an e-mail address in the format "[email protected]"', 'emailMask' : /[\w.\-@'"!#$%&'*+/=?^_`{|}~]/i, 'url' : function(v){ return url.test(v); }, 'urlText' : 'This field should be a URL in the format "http:/'+'/www.example.com"', 'alpha' : function(v){ return alpha.test(v); }, 'alphaText' : 'This field should only contain letters and _', 'alphaMask' : /[a-z_]/i, 'alphanum' : function(v){ return alphanum.test(v); }, 'alphanumText' : 'This field should only contain letters, numbers and _', 'alphanumMask' : /[a-z0-9_]/i }; }())); Ext.define('Ext.layout.component.field.Text', { extend: Ext.layout.component.field.Field , alias: 'layout.textfield', type: 'textfield', setWidthInDom: true, canGrowWidth: true, beginLayoutCycle: function(ownerContext) { this.callParent(arguments); if (ownerContext.heightModel.shrinkWrap) { ownerContext.inputContext.el.setStyle('height', ''); } }, measureContentWidth: function (ownerContext) { var me = this, owner = me.owner, width = me.callParent(arguments), inputContext = ownerContext.inputContext, inputEl, value, calcWidth, max, min; if (owner.grow && me.canGrowWidth && !ownerContext.state.growHandled) { inputEl = owner.inputEl; value = Ext.util.Format.htmlEncode(inputEl.dom.value || (owner.hasFocus ? '' : owner.emptyText) || ''); value += owner.growAppend; calcWidth = inputEl.getTextWidth(value) + inputContext.getFrameInfo().width; max = owner.growMax; min = Math.min(max, width); max = Math.max(owner.growMin, max, min); calcWidth = Ext.Number.constrain(calcWidth, owner.growMin, max); inputContext.setWidth(calcWidth); ownerContext.state.growHandled = true; inputContext.domBlock(me, 'width'); width = NaN; } return width; }, publishInnerHeight: function(ownerContext, height) { ownerContext.inputContext.setHeight(height - this.measureLabelErrorHeight(ownerContext)); }, beginLayoutFixed: function(ownerContext, width, suffix) { var me = this, ieInputWidthAdjustment = me.ieInputWidthAdjustment; if (ieInputWidthAdjustment) { me.adjustIEInputPadding(ownerContext); if(suffix === 'px') { width -= ieInputWidthAdjustment; } } me.callParent(arguments); }, adjustIEInputPadding: function(ownerContext) { this.owner.bodyEl.setStyle('padding-right', this.ieInputWidthAdjustment + 'px'); } }); Ext.define('Ext.form.field.Text', { extend: Ext.form.field.Base , alias: 'widget.textfield', alternateClassName: ['Ext.form.TextField', 'Ext.form.Text'], size: 20, growMin : 30, growMax : 800, growAppend: 'W', allowBlank : true, validateBlank: false, allowOnlyWhitespace: true, minLength : 0, maxLength : Number.MAX_VALUE, minLengthText : 'The minimum length for this field is {0}', maxLengthText : 'The maximum length for this field is {0}', blankText : 'This field is required', regexText : '', emptyCls : Ext.baseCSSPrefix + 'form-empty-field', requiredCls : Ext.baseCSSPrefix + 'form-required-field', componentLayout: 'textfield', valueContainsPlaceholder : false, ariaRole: 'textbox', initComponent: function () { var me = this; if (me.allowOnlyWhitespace === false) { me.allowBlank = false; } me.callParent(); me.addEvents( 'autosize', 'keydown', 'keyup', 'keypress' ); me.addStateEvents('change'); me.setGrowSizePolicy(); }, setGrowSizePolicy: function(){ if (this.grow) { this.shrinkWrap |= 1; } }, initEvents : function(){ var me = this, el = me.inputEl; me.callParent(); if(me.selectOnFocus || me.emptyText){ me.mon(el, 'mousedown', me.onMouseDown, me); } if(me.maskRe || (me.vtype && me.disableKeyFilter !== true && (me.maskRe = Ext.form.field.VTypes[me.vtype+'Mask']))){ me.mon(el, 'keypress', me.filterKeys, me); } if (me.enableKeyEvents) { me.mon(el, { scope: me, keyup: me.onKeyUp, keydown: me.onKeyDown, keypress: me.onKeyPress }); } }, isEqual: function(value1, value2) { return this.isEqualAsString(value1, value2); }, onChange: function(newVal, oldVal) { this.callParent(arguments); this.autoSize(); }, getSubTplData: function() { var me = this, value = me.getRawValue(), isEmpty = me.emptyText && value.length < 1, maxLength = me.maxLength, placeholder; if (me.enforceMaxLength) { if (maxLength === Number.MAX_VALUE) { maxLength = undefined; } } else { maxLength = undefined; } if (isEmpty) { if (Ext.supports.Placeholder) { placeholder = me.emptyText; } else { value = me.emptyText; me.valueContainsPlaceholder = true; } } return Ext.apply(me.callParent(), { maxLength : maxLength, readOnly : me.readOnly, placeholder : placeholder, value : value, fieldCls : me.fieldCls + ((isEmpty && (placeholder || value)) ? ' ' + me.emptyCls : '') + (me.allowBlank ? '' : ' ' + me.requiredCls) }); }, afterRender: function(){ this.autoSize(); this.callParent(); }, onMouseDown: function(e){ var me = this; if(!me.hasFocus){ me.mon(me.inputEl, 'mouseup', Ext.emptyFn, me, { single: true, preventDefault: true }); } }, processRawValue: function(value) { var me = this, stripRe = me.stripCharsRe, newValue; if (stripRe) { newValue = value.replace(stripRe, ''); if (newValue !== value) { me.setRawValue(newValue); value = newValue; } } return value; }, onDisable: function(){ this.callParent(); if (Ext.isIE) { this.inputEl.dom.unselectable = 'on'; } }, onEnable: function(){ this.callParent(); if (Ext.isIE) { this.inputEl.dom.unselectable = ''; } }, onKeyDown: function(e) { this.fireEvent('keydown', this, e); }, onKeyUp: function(e) { this.fireEvent('keyup', this, e); }, onKeyPress: function(e) { this.fireEvent('keypress', this, e); }, reset : function(){ this.callParent(); this.applyEmptyText(); }, applyEmptyText : function(){ var me = this, emptyText = me.emptyText, isEmpty; if (me.rendered && emptyText) { isEmpty = me.getRawValue().length < 1 && !me.hasFocus; if (Ext.supports.Placeholder) { me.inputEl.dom.placeholder = emptyText; } else if (isEmpty) { me.setRawValue(emptyText); me.valueContainsPlaceholder = true; } if (isEmpty) { me.inputEl.addCls(me.emptyCls); } me.autoSize(); } }, afterFirstLayout: function() { this.callParent(); if (Ext.isIE && this.disabled) { var el = this.inputEl; if (el) { el.dom.unselectable = 'on'; } } }, beforeFocus : function(){ var me = this, inputEl = me.inputEl, emptyText = me.emptyText, isEmpty; me.callParent(arguments); if ((emptyText && !Ext.supports.Placeholder) && (inputEl.dom.value === me.emptyText && me.valueContainsPlaceholder)) { me.setRawValue(''); isEmpty = true; inputEl.removeCls(me.emptyCls); me.valueContainsPlaceholder = false; } else if (Ext.supports.Placeholder) { inputEl.removeCls(me.emptyCls); } if (me.selectOnFocus || isEmpty) { if (Ext.isWebKit) { if (!me.inputFocusTask) { me.inputFocusTask = new Ext.util.DelayedTask(me.focusInput, me); } me.inputFocusTask.delay(1); } else { me.focusInput(); } } }, focusInput: function(){ var input = this.inputEl; if (input) { input = input.dom; if (input) { input.select(); } } }, onFocus: function() { var me = this; me.callParent(arguments); if (me.emptyText) { me.autoSize(); } }, postBlur : function(){ var task = this.inputFocusTask; this.callParent(arguments); this.applyEmptyText(); if (task) { task.cancel(); } }, filterKeys : function(e){ if (e.ctrlKey && !e.altKey) { return; } var key = e.getKey(), charCode = String.fromCharCode(e.getCharCode()); if((Ext.isGecko || Ext.isOpera) && (e.isNavKeyPress() || key === e.BACKSPACE || (key === e.DELETE && e.button === -1))){ return; } if((!Ext.isGecko && !Ext.isOpera) && e.isSpecialKey() && !charCode){ return; } if(!this.maskRe.test(charCode)){ e.stopEvent(); } }, getState: function() { return this.addPropertyToState(this.callParent(), 'value'); }, applyState: function(state) { this.callParent(arguments); if(state.hasOwnProperty('value')) { this.setValue(state.value); } }, getRawValue: function() { var me = this, v = me.callParent(); if (v === me.emptyText && me.valueContainsPlaceholder) { v = ''; } return v; }, setValue: function(value) { var me = this, inputEl = me.inputEl; if (inputEl && me.emptyText && !Ext.isEmpty(value)) { inputEl.removeCls(me.emptyCls); me.valueContainsPlaceholder = false; } me.callParent(arguments); me.applyEmptyText(); return me; }, getErrors: function(value) { var me = this, errors = me.callParent(arguments), validator = me.validator, vtype = me.vtype, vtypes = Ext.form.field.VTypes, regex = me.regex, format = Ext.String.format, msg, trimmed, isBlank; value = value || me.processRawValue(me.getRawValue()); if (Ext.isFunction(validator)) { msg = validator.call(me, value); if (msg !== true) { errors.push(msg); } } trimmed = me.allowOnlyWhitespace ? value : Ext.String.trim(value); if (trimmed.length < 1 || (value === me.emptyText && me.valueContainsPlaceholder)) { if (!me.allowBlank) { errors.push(me.blankText); } if (!me.validateBlank) { return errors; } isBlank = true; } if (!isBlank && value.length < me.minLength) { errors.push(format(me.minLengthText, me.minLength)); } if (value.length > me.maxLength) { errors.push(format(me.maxLengthText, me.maxLength)); } if (vtype) { if (!vtypes[vtype](value, me)) { errors.push(me.vtypeText || vtypes[vtype +'Text']); } } if (regex && !regex.test(value)) { errors.push(me.regexText || me.invalidText); } return errors; }, selectText : function(start, end){ var me = this, v = me.getRawValue(), doFocus = true, el = me.inputEl.dom, undef, range; if (v.length > 0) { start = start === undef ? 0 : start; end = end === undef ? v.length : end; if (el.setSelectionRange) { el.setSelectionRange(start, end); } else if(el.createTextRange) { range = el.createTextRange(); range.moveStart('character', start); range.moveEnd('character', end - v.length); range.select(); } doFocus = Ext.isGecko || Ext.isOpera; } if (doFocus) { me.focus(); } }, autoSize: function() { var me = this; if (me.grow && me.rendered) { me.autoSizing = true; me.updateLayout(); } }, afterComponentLayout: function() { var me = this, width; me.callParent(arguments); if (me.autoSizing) { width = me.inputEl.getWidth(); if (width !== me.lastInputWidth) { me.fireEvent('autosize', me, width); me.lastInputWidth = width; delete me.autoSizing; } } }, onDestroy: function(){ var me = this; me.callParent(); if (me.inputFocusTask) { me.inputFocusTask.cancel(); me.inputFocusTask = null; } } }); Ext.define('Ext.layout.component.field.TextArea', { extend: Ext.layout.component.field.Text , alias: 'layout.textareafield', type: 'textareafield', canGrowWidth: false, naturalSizingProp: 'cols', beginLayout: function(ownerContext){ this.callParent(arguments); ownerContext.target.inputEl.setStyle('height', ''); }, measureContentHeight: function (ownerContext) { var me = this, owner = me.owner, height = me.callParent(arguments), inputContext, inputEl, value, max, curWidth, calcHeight; if (owner.grow && !ownerContext.state.growHandled) { inputContext = ownerContext.inputContext; inputEl = owner.inputEl; curWidth = inputEl.getWidth(true); value = Ext.util.Format.htmlEncode(inputEl.dom.value) || ' '; value += owner.growAppend; value = value.replace(/\n/g, '
'); calcHeight = Ext.util.TextMetrics.measure(inputEl, value, curWidth).height + inputContext.getBorderInfo().height + inputContext.getPaddingInfo().height; calcHeight = Ext.Number.constrain(calcHeight, owner.growMin, owner.growMax); inputContext.setHeight(calcHeight); ownerContext.state.growHandled = true; inputContext.domBlock(me, 'height'); height = NaN; } return height; } }); Ext.define('Ext.form.field.TextArea', { extend: Ext.form.field.Text , alias: ['widget.textareafield', 'widget.textarea'], alternateClassName: 'Ext.form.TextArea', fieldSubTpl: [ '', { disableFormats: true } ], growMin: 60, growMax: 1000, growAppend: '\n-', cols: 20, rows: 4, enterIsSpecial: false, preventScrollbars: false, componentLayout: 'textareafield', setGrowSizePolicy: Ext.emptyFn, returnRe: /\r/g, inputCls: Ext.baseCSSPrefix + 'form-textarea', getSubTplData: function() { var me = this, fieldStyle = me.getFieldStyle(), ret = me.callParent(); if (me.grow) { if (me.preventScrollbars) { ret.fieldStyle = (fieldStyle||'') + ';overflow:hidden;height:' + me.growMin + 'px'; } } Ext.applyIf(ret, { cols: me.cols, rows: me.rows }); return ret; }, afterRender: function () { var me = this; me.callParent(arguments); me.needsMaxCheck = me.enforceMaxLength && me.maxLength !== Number.MAX_VALUE && !Ext.supports.TextAreaMaxLength; if (me.needsMaxCheck) { me.inputEl.on('paste', me.onPaste, me); } }, transformRawValue: function(value){ return this.stripReturns(value); }, transformOriginalValue: function(value){ return this.stripReturns(value); }, getValue: function(){ return this.stripReturns(this.callParent()); }, valueToRaw: function(value){ value = this.stripReturns(value); return this.callParent([value]); }, stripReturns: function(value){ if (value && typeof value === 'string') { value = value.replace(this.returnRe, ''); } return value; }, onPaste: function(e){ var me = this; if (!me.pasteTask) { me.pasteTask = new Ext.util.DelayedTask(me.pasteCheck, me); } me.pasteTask.delay(1); }, pasteCheck: function(){ var me = this, value = me.getValue(), max = me.maxLength; if (value.length > max) { value = value.substr(0, max); me.setValue(value); } }, fireKey: function(e) { var me = this, key = e.getKey(), value; if (e.isSpecialKey() && (me.enterIsSpecial || (key !== e.ENTER || e.hasModifier()))) { me.fireEvent('specialkey', me, e); } if (me.needsMaxCheck && key !== e.BACKSPACE && key !== e.DELETE && !e.isNavKeyPress() && !me.isCutCopyPasteSelectAll(e, key)) { value = me.getValue(); if (value.length >= me.maxLength) { e.stopEvent(); } } }, isCutCopyPasteSelectAll: function(e, key) { if (e.ctrlKey) { return key === e.A || key === e.C || key === e.V || key === e.X; } return false; }, autoSize: function() { var me = this, height; if (me.grow && me.rendered) { me.updateLayout(); height = me.inputEl.getHeight(); if (height !== me.lastInputHeight) { me.fireEvent('autosize', me, height); me.lastInputHeight = height; } } }, beforeDestroy: function(){ var task = this.pasteTask; if (task) { task.cancel(); this.pasteTask = null; } this.callParent(); } }); Ext.define('Ext.form.field.Display', { extend: Ext.form.field.Base , alias: 'widget.displayfield', alternateClassName: ['Ext.form.DisplayField', 'Ext.form.Display'], ariaRole: 'textbox', fieldSubTpl: [ '
style="{fieldStyle}"', ' class="{fieldCls}">{value}
', { compiled: true, disableFormats: true } ], readOnly: true, fieldCls: Ext.baseCSSPrefix + 'form-display-field', fieldBodyCls: Ext.baseCSSPrefix + 'form-display-field-body', htmlEncode: false, noWrap: false, validateOnChange: false, initEvents: Ext.emptyFn, submitValue: false, valueToRaw: function(value) { if (!value && value !== 0) { return ''; } else { return value; } }, isDirty: function(){ return false; }, isValid: function() { return true; }, validate: function() { return true; }, getRawValue: function() { return this.rawValue; }, setRawValue: function(value) { var me = this; value = Ext.value(value, ''); me.rawValue = value; if (me.rendered) { me.inputEl.dom.innerHTML = me.getDisplayValue(); me.updateLayout(); } return value; }, getDisplayValue: function() { var me = this, value = this.getRawValue(), display; if (me.renderer) { display = me.renderer.call(me.scope || me, value, me); } else { display = me.htmlEncode ? Ext.util.Format.htmlEncode(value) : value; } return display; }, getSubTplData: function() { var ret = this.callParent(arguments); ret.value = this.getDisplayValue(); return ret; } }); Ext.define('Ext.layout.container.Anchor', { alias: 'layout.anchor', extend: Ext.layout.container.Auto , alternateClassName: 'Ext.layout.AnchorLayout', type: 'anchor', defaultAnchor: '100%', parseAnchorRE: /^(r|right|b|bottom)$/i, manageOverflow: true, beginLayoutCycle: function (ownerContext) { var me = this, dimensions = 0, anchorSpec, childContext, childItems, i, length, target; me.callParent(arguments); childItems = ownerContext.childItems; length = childItems.length; for (i = 0; i < length; ++i) { childContext = childItems[i]; anchorSpec = childContext.target.anchorSpec; if (anchorSpec) { if (childContext.widthModel.calculated && anchorSpec.right) { dimensions |= 1; } if (childContext.heightModel.calculated && anchorSpec.bottom) { dimensions |= 2; } if (dimensions == 3) { break; } } } ownerContext.anchorDimensions = dimensions; }, calculateItems: function (ownerContext, containerSize) { var me = this, childItems = ownerContext.childItems, length = childItems.length, gotHeight = containerSize.gotHeight, gotWidth = containerSize.gotWidth, ownerHeight = containerSize.height, ownerWidth = containerSize.width, knownDimensions = (gotWidth ? 1 : 0) | (gotHeight ? 2 : 0), anchorDimensions = ownerContext.anchorDimensions, anchorSpec, childContext, childMargins, height, i, width; if (!anchorDimensions) { return true; } for (i = 0; i < length; i++) { childContext = childItems[i]; childMargins = childContext.getMarginInfo(); anchorSpec = childContext.target.anchorSpec; if (gotWidth && childContext.widthModel.calculated) { width = anchorSpec.right(ownerWidth) - childMargins.width; width = me.adjustWidthAnchor(width, childContext); childContext.setWidth(width); } if (gotHeight && childContext.heightModel.calculated) { height = anchorSpec.bottom(ownerHeight) - childMargins.height; height = me.adjustHeightAnchor(height, childContext); childContext.setHeight(height); } } return (knownDimensions & anchorDimensions) === anchorDimensions; }, anchorFactory: { offset: function (delta) { return function(v) { return v + delta; }; }, ratio: function (ratio) { return function(v) { return Math.floor(v * ratio); }; }, standard: function (diff) { return function(v) { return v - diff; }; } }, parseAnchor: function(a, start, cstart) { if (a && a != 'none') { var factory = this.anchorFactory, delta; if (this.parseAnchorRE.test(a)) { return factory.standard(cstart - start); } if (a.indexOf('%') != -1) { return factory.ratio(parseFloat(a.replace('%', '')) * 0.01); } delta = parseInt(a, 10); if (!isNaN(delta)) { return factory.offset(delta); } } return null; }, adjustWidthAnchor: function(value, childContext) { return value; }, adjustHeightAnchor: function(value, childContext) { return value; }, configureItem: function(item) { var me = this, owner = me.owner, anchor= item.anchor, anchorsArray, anchorWidth, anchorHeight; me.callParent(arguments); if (!item.anchor && item.items && !Ext.isNumber(item.width) && !(Ext.isIE6 && Ext.isStrict)) { item.anchor = anchor = me.defaultAnchor; } if (owner.anchorSize) { if (typeof owner.anchorSize == 'number') { anchorWidth = owner.anchorSize; } else { anchorWidth = owner.anchorSize.width; anchorHeight = owner.anchorSize.height; } } else { anchorWidth = owner.initialConfig.width; anchorHeight = owner.initialConfig.height; } if (anchor) { anchorsArray = anchor.split(' '); item.anchorSpec = { right: me.parseAnchor(anchorsArray[0], item.initialConfig.width, anchorWidth), bottom: me.parseAnchor(anchorsArray[1], item.initialConfig.height, anchorHeight) }; } }, sizePolicy: { $: { readsWidth: 1, readsHeight: 1, setsWidth: 0, setsHeight: 0 }, b: { readsWidth: 1, readsHeight: 0, setsWidth: 0, setsHeight: 1 }, r: { $: { readsWidth: 0, readsHeight: 1, setsWidth: 1, setsHeight: 0 }, b: { readsWidth: 0, readsHeight: 0, setsWidth: 1, setsHeight: 1 } } }, getItemSizePolicy: function (item) { var anchorSpec = item.anchorSpec, key = '$', policy = this.sizePolicy, sizeModel; if (anchorSpec) { sizeModel = this.owner.getSizeModel(); if (anchorSpec.right && !sizeModel.width.shrinkWrap) { policy = policy.r; } if (anchorSpec.bottom && !sizeModel.height.shrinkWrap) { key = 'b'; } } return policy[key]; } }); Ext.define('Ext.window.MessageBox', { extend: Ext.window.Window , alias: 'widget.messagebox', OK : 1, YES : 2, NO : 4, CANCEL : 8, OKCANCEL : 9, YESNO : 6, YESNOCANCEL : 14, INFO : Ext.baseCSSPrefix + 'message-box-info', WARNING : Ext.baseCSSPrefix + 'message-box-warning', QUESTION : Ext.baseCSSPrefix + 'message-box-question', ERROR : Ext.baseCSSPrefix + 'message-box-error', hideMode: 'offsets', closeAction: 'hide', resizable: false, title: ' ', defaultMinWidth: 250, defaultMaxWidth: 600, defaultMinHeight: 110, defaultMaxHeight: 500, minWidth: null, maxWidth: null, minHeight: null, maxHeight: null, constrain: true, cls: [Ext.baseCSSPrefix + 'message-box', Ext.baseCSSPrefix + 'hide-offsets'], layout: { type: 'vbox', align: 'stretch' }, shrinkWrapDock: true, defaultTextHeight : 75, minProgressWidth : 250, minPromptWidth: 250, buttonText: { ok: 'OK', yes: 'Yes', no: 'No', cancel: 'Cancel' }, buttonIds: [ 'ok', 'yes', 'no', 'cancel' ], titleText: { confirm: 'Confirm', prompt: 'Prompt', wait: 'Loading...', alert: 'Attention' }, iconHeight: 35, iconWidth: 50, ariaRole: 'alertdialog', makeButton: function(btnIdx) { var btnId = this.buttonIds[btnIdx]; return new Ext.button.Button({ handler: this.btnCallback, itemId: btnId, scope: this, text: this.buttonText[btnId], minWidth: 75 }); }, btnCallback: function(btn) { var me = this, value, field; if (me.cfg.prompt || me.cfg.multiline) { if (me.cfg.multiline) { field = me.textArea; } else { field = me.textField; } value = field.getValue(); field.reset(); } me.hide(); me.userCallback(btn.itemId, value, me.cfg); }, hide: function() { var me = this, cls = me.cfg.cls; me.progressBar.reset(); if (cls) { me.removeCls(cls); } me.callParent(arguments); }, constructor: function(cfg) { var me = this; me.callParent(arguments); me.minWidth = me.defaultMinWidth = (me.minWidth || me.defaultMinWidth); me.maxWidth = me.defaultMaxWidth = (me.maxWidth || me.defaultMaxWidth); me.minHeight = me.defaultMinHeight = (me.minHeight || me.defaultMinHeight); me.maxHeight = me.defaultMaxHeight = (me.maxHeight || me.defaultMaxHeight); }, initComponent: function(cfg) { var me = this, baseId = me.id, i, button; me.title = ' '; me.topContainer = new Ext.container.Container({ layout: 'hbox', padding: 10, style: { overflow: 'hidden' }, items: [ me.iconComponent = new Ext.Component({ width: me.iconWidth, height: me.iconHeight }), me.promptContainer = new Ext.container.Container({ flex: 1, layout: 'anchor', items: [ me.msg = new Ext.form.field.Display({ id: baseId + '-displayfield', cls: me.baseCls + '-text' }), me.textField = new Ext.form.field.Text({ id: baseId + '-textfield', anchor: '100%', enableKeyEvents: true, listeners: { keydown: me.onPromptKey, scope: me } }), me.textArea = new Ext.form.field.TextArea({ id: baseId + '-textarea', anchor: '100%', height: 75 }) ] }) ] }); me.progressBar = new Ext.ProgressBar({ id: baseId + '-progressbar', margin: '0 10 10 10' }); me.items = [me.topContainer, me.progressBar]; me.msgButtons = []; for (i = 0; i < 4; i++) { button = me.makeButton(i); me.msgButtons[button.itemId] = button; me.msgButtons.push(button); } me.bottomTb = new Ext.toolbar.Toolbar({ id: baseId + '-toolbar', ui: 'footer', dock: 'bottom', layout: { pack: 'center' }, items: [ me.msgButtons[0], me.msgButtons[1], me.msgButtons[2], me.msgButtons[3] ] }); me.dockedItems = [me.bottomTb]; me.on('close', me.onClose, me); me.callParent(); }, onClose: function(){ var btn = this.header.child('[type=close]'); btn.itemId = 'cancel'; this.btnCallback(btn); delete btn.itemId; }, onPromptKey: function(textField, e) { var me = this; if (e.keyCode === e.RETURN || e.keyCode === 10) { if (me.msgButtons.ok.isVisible()) { me.msgButtons.ok.handler.call(me, me.msgButtons.ok); } else if (me.msgButtons.yes.isVisible()) { me.msgButtons.yes.handler.call(me, me.msgButtons.yes); } } }, reconfigure: function(cfg) { var me = this, buttons = 0, hideToolbar = true, oldButtonText = me.buttonText, resizer = me.resizer, resizeTracker, width, height, i, textArea, textField, msg, progressBar, msgButtons; me.updateButtonText(); cfg = cfg || {}; me.cfg = cfg; if (cfg.width) { width = cfg.width; } if (cfg.height) { height = cfg.height; } me.minWidth = cfg.minWidth || me.defaultMinWidth; me.maxWidth = cfg.maxWidth || me.defaultMaxWidth; me.minHeight = cfg.minHeight || me.defaultMinHeight; me.maxHeight = cfg.maxHeight || me.defaultMaxHeight; if (resizer) { resizeTracker = resizer.resizeTracker; resizer.minWidth = resizeTracker.minWidth = me.minWidth; resizer.maxWidth = resizeTracker.maxWidth = me.maxWidth; resizer.minHeight = resizeTracker.minHeight = me.minHeight; resizer.maxHeight = resizeTracker.maxHeight = me.maxHeight; } delete me.defaultFocus; if (cfg.defaultFocus) { me.defaultFocus = cfg.defaultFocus; } me.animateTarget = cfg.animateTarget || undefined; me.modal = cfg.modal !== false; me.setTitle(cfg.title || ''); me.setIconCls(cfg.iconCls || ''); if (Ext.isObject(cfg.buttons)) { me.buttonText = cfg.buttons; buttons = 0; } else { me.buttonText = cfg.buttonText || me.buttonText; buttons = Ext.isNumber(cfg.buttons) ? cfg.buttons : 0; } buttons = buttons | me.updateButtonText(); me.buttonText = oldButtonText; Ext.suspendLayouts(); delete me.width; delete me.height; if (width || height) { if (width) { me.setWidth(width); } if (height) { me.setHeight(height); } } me.hidden = false; if (!me.rendered) { me.render(Ext.getBody()); } me.closable = cfg.closable !== false && !cfg.wait; me.header.child('[type=close]').setVisible(me.closable); if (!cfg.title && !me.closable && !cfg.iconCls) { me.header.hide(); } else { me.header.show(); } me.liveDrag = !cfg.proxyDrag; me.userCallback = Ext.Function.bind(cfg.callback ||cfg.fn || Ext.emptyFn, cfg.scope || Ext.global); me.setIcon(cfg.icon, cfg.iconWidth, cfg.iconHeight); msg = me.msg; if (cfg.msg) { msg.setValue(cfg.msg); msg.show(); } else { msg.hide(); } textArea = me.textArea; textField = me.textField; if (cfg.prompt || cfg.multiline) { me.multiline = cfg.multiline; if (cfg.multiline) { textArea.setValue(cfg.value); textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight); textArea.show(); textField.hide(); me.defaultFocus = textArea; } else { textField.setValue(cfg.value); textArea.hide(); textField.show(); me.defaultFocus = textField; } } else { textArea.hide(); textField.hide(); } progressBar = me.progressBar; if (cfg.progress || cfg.wait) { progressBar.show(); me.updateProgress(0, cfg.progressText); if(cfg.wait === true){ progressBar.wait(cfg.waitConfig); } } else { progressBar.hide(); } msgButtons = me.msgButtons; for (i = 0; i < 4; i++) { if (buttons & Math.pow(2, i)) { if (!me.defaultFocus) { me.defaultFocus = msgButtons[i]; } msgButtons[i].show(); hideToolbar = false; } else { msgButtons[i].hide(); } } if (hideToolbar) { me.bottomTb.hide(); } else { me.bottomTb.show(); } Ext.resumeLayouts(true); }, updateButtonText: function() { var me = this, buttonText = me.buttonText, buttons = 0, btnId, btn; for (btnId in buttonText) { if (buttonText.hasOwnProperty(btnId)) { btn = me.msgButtons[btnId]; if (btn) { if (me.cfg && me.cfg.buttonText) { buttons = buttons | Math.pow(2, Ext.Array.indexOf(me.buttonIds, btnId)); } if (btn.text != buttonText[btnId]) { btn.setText(buttonText[btnId]); } } } } return buttons; }, show: function(cfg) { var me = this, visibleFocusables; if (Ext.AbstractComponent.layoutSuspendCount) { Ext.on({ resumelayouts: function() { me.show(cfg); }, single: true }); return me; } me.reconfigure(cfg); if (cfg.cls) { me.addCls(cfg.cls); } visibleFocusables = me.query('textfield:not([hidden]),textarea:not([hidden]),button:not([hidden])'); me.preventFocusOnActivate = !visibleFocusables.length; me.hidden = true; me.callParent(); return me; }, onShow: function() { this.callParent(arguments); this.center(); }, updateText: function(text) { this.msg.setValue(text); }, setIcon : function(icon, width, height) { var me = this, iconCmp = me.iconComponent, cls = me.messageIconCls; if (cls) { iconCmp.removeCls(cls); } if (icon) { iconCmp.show(); iconCmp.setSize(width || me.iconWidth, height || me.iconHeight); iconCmp.addCls(Ext.baseCSSPrefix + 'dlg-icon'); iconCmp.addCls(me.messageIconCls = icon); } else { iconCmp.removeCls(Ext.baseCSSPrefix + 'dlg-icon'); iconCmp.hide(); } return me; }, updateProgress : function(value, progressText, msg){ this.progressBar.updateProgress(value, progressText); if (msg){ this.updateText(msg); } return this; }, onEsc: function() { if (this.closable !== false) { this.callParent(arguments); } }, confirm: function(cfg, msg, fn, scope) { if (Ext.isString(cfg)) { cfg = { title: cfg, icon: this.QUESTION, msg: msg, buttons: this.YESNO, callback: fn, scope: scope }; } return this.show(cfg); }, prompt : function(cfg, msg, fn, scope, multiline, value){ if (Ext.isString(cfg)) { cfg = { prompt: true, title: cfg, minWidth: this.minPromptWidth, msg: msg, buttons: this.OKCANCEL, callback: fn, scope: scope, multiline: multiline, value: value }; } return this.show(cfg); }, wait : function(cfg, title, config){ if (Ext.isString(cfg)) { cfg = { title : title, msg : cfg, closable: false, wait: true, modal: true, minWidth: this.minProgressWidth, waitConfig: config }; } return this.show(cfg); }, alert: function(cfg, msg, fn, scope) { if (Ext.isString(cfg)) { cfg = { title : cfg, msg : msg, buttons: this.OK, fn: fn, scope : scope, minWidth: this.minWidth }; } return this.show(cfg); }, progress : function(cfg, msg, progressText){ if (Ext.isString(cfg)) { cfg = { title: cfg, msg: msg, progress: true, progressText: progressText }; } return this.show(cfg); } }, function() { Ext.MessageBox = Ext.Msg = new this(); }); Ext.define('Ext.form.Basic', { extend: Ext.util.Observable , alternateClassName: 'Ext.form.BasicForm', constructor: function(owner, config) { var me = this, reader; me.owner = owner; me.checkValidityTask = new Ext.util.DelayedTask(me.checkValidity, me); me.checkDirtyTask = new Ext.util.DelayedTask(me.checkDirty, me); me.monitor = new Ext.container.Monitor({ selector: '[isFormField]:not([excludeForm])', scope: me, addHandler: me.onFieldAdd, removeHandler: me.onFieldRemove }); me.monitor.bind(owner); Ext.apply(me, config); if (Ext.isString(me.paramOrder)) { me.paramOrder = me.paramOrder.split(/[\s,|]/); } reader = me.reader; if (reader && !reader.isReader) { if (typeof reader === 'string') { reader = { type: reader }; } me.reader = Ext.createByAlias('reader.' + reader.type, reader); } reader = me.errorReader; if (reader && !reader.isReader) { if (typeof reader === 'string') { reader = { type: reader }; } me.errorReader = Ext.createByAlias('reader.' + reader.type, reader); } me.addEvents( 'beforeaction', 'actionfailed', 'actioncomplete', 'validitychange', 'dirtychange' ); me.callParent(); }, initialize : function() { this.initialized = true; this.onValidityChange(!this.hasInvalidField()); }, timeout: 30, paramsAsHash: false, waitTitle: 'Please Wait...', trackResetOnLoad: false, wasDirty: false, destroy: function() { var me = this, mon = me.monitor; if (mon) { mon.unbind(); me.monitor = null; } me.clearListeners(); me.checkValidityTask.cancel(); me.checkDirtyTask.cancel(); me.isDestroyed = true; }, onFieldAdd: function(field){ var me = this; me.mon(field, 'validitychange', me.checkValidityDelay, me); me.mon(field, 'dirtychange', me.checkDirtyDelay, me); if (me.initialized) { me.checkValidityDelay(); } }, onFieldRemove: function(field){ var me = this; me.mun(field, 'validitychange', me.checkValidityDelay, me); me.mun(field, 'dirtychange', me.checkDirtyDelay, me); if (me.initialized) { me.checkValidityDelay(); } }, getFields: function() { return this.monitor.getItems(); }, getBoundItems: function() { var boundItems = this._boundItems; if (!boundItems || boundItems.getCount() === 0) { boundItems = this._boundItems = new Ext.util.MixedCollection(); boundItems.addAll(this.owner.query('[formBind]')); } return boundItems; }, hasInvalidField: function() { return !!this.getFields().findBy(function(field) { var preventMark = field.preventMark, isValid; field.preventMark = true; isValid = field.isValid(); field.preventMark = preventMark; return !isValid; }); }, isValid: function() { var me = this, invalid; Ext.suspendLayouts(); invalid = me.getFields().filterBy(function(field) { return !field.validate(); }); Ext.resumeLayouts(true); return invalid.length < 1; }, checkValidity: function() { var me = this, valid; if (me.isDestroyed) { return; } valid = !me.hasInvalidField(); if (valid !== me.wasValid) { me.onValidityChange(valid); me.fireEvent('validitychange', me, valid); me.wasValid = valid; } }, checkValidityDelay: function(){ this.checkValidityTask.delay(10); }, onValidityChange: function(valid) { var boundItems = this.getBoundItems(), items, i, iLen, cmp; if (boundItems) { items = boundItems.items; iLen = items.length; for (i = 0; i < iLen; i++) { cmp = items[i]; if (cmp.disabled === valid) { cmp.setDisabled(!valid); } } } }, isDirty: function() { return !!this.getFields().findBy(function(f) { return f.isDirty(); }); }, checkDirtyDelay: function(){ this.checkDirtyTask.delay(10); }, checkDirty: function() { var me = this, dirty; if (me.isDestroyed) { return; } dirty = this.isDirty(); if (dirty !== this.wasDirty) { this.fireEvent('dirtychange', this, dirty); this.wasDirty = dirty; } }, hasUpload: function() { return !!this.getFields().findBy(function(f) { return f.isFileUpload(); }); }, doAction: function(action, options) { if (Ext.isString(action)) { action = Ext.ClassManager.instantiateByAlias('formaction.' + action, Ext.apply({}, options, {form: this})); } if (this.fireEvent('beforeaction', this, action) !== false) { this.beforeAction(action); Ext.defer(action.run, 100, action); } return this; }, submit: function(options) { options = options || {}; var me = this, action; if (options.standardSubmit || me.standardSubmit) { action = 'standardsubmit'; } else { action = me.api ? 'directsubmit' : 'submit'; } return me.doAction(action, options); }, load: function(options) { return this.doAction(this.api ? 'directload' : 'load', options); }, updateRecord: function(record) { record = record || this._record; if (!record) { return this; } var fields = record.fields.items, values = this.getFieldValues(), obj = {}, i = 0, len = fields.length, name; for (; i < len; ++i) { name = fields[i].name; if (values.hasOwnProperty(name)) { obj[name] = values[name]; } } record.beginEdit(); record.set(obj); record.endEdit(); return this; }, loadRecord: function(record) { this._record = record; return this.setValues(record.getData()); }, getRecord: function() { return this._record; }, beforeAction: function(action) { var me = this, waitMsg = action.waitMsg, maskCls = Ext.baseCSSPrefix + 'mask-loading', fields = me.getFields().items, f, fLen = fields.length, field, waitMsgTarget; for (f = 0; f < fLen; f++) { field = fields[f]; if (field.isFormField && field.syncValue) { field.syncValue(); } } if (waitMsg) { waitMsgTarget = me.waitMsgTarget; if (waitMsgTarget === true) { me.owner.el.mask(waitMsg, maskCls); } else if (waitMsgTarget) { waitMsgTarget = me.waitMsgTarget = Ext.get(waitMsgTarget); waitMsgTarget.mask(waitMsg, maskCls); } else { me.floatingAncestor = me.owner.up('[floating]'); if (me.floatingAncestor) { me.savePreventFocusOnActivate = me.floatingAncestor.preventFocusOnActivate; me.floatingAncestor.preventFocusOnActivate = true; } Ext.MessageBox.wait(waitMsg, action.waitTitle || me.waitTitle); } } }, afterAction: function(action, success) { var me = this; if (action.waitMsg) { var messageBox = Ext.MessageBox, waitMsgTarget = me.waitMsgTarget; if (waitMsgTarget === true) { me.owner.el.unmask(); } else if (waitMsgTarget) { waitMsgTarget.unmask(); } else { messageBox.hide(); } } if (me.floatingAncestor) { me.floatingAncestor.preventFocusOnActivate = me.savePreventFocusOnActivate; } if (success) { if (action.reset) { me.reset(); } Ext.callback(action.success, action.scope || action, [me, action]); me.fireEvent('actioncomplete', me, action); } else { Ext.callback(action.failure, action.scope || action, [me, action]); me.fireEvent('actionfailed', me, action); } }, findField: function(id) { return this.getFields().findBy(function(f) { return f.id === id || f.getName() === id; }); }, markInvalid: function(errors) { var me = this, e, eLen, error, value, key; function mark(fieldId, msg) { var field = me.findField(fieldId); if (field) { field.markInvalid(msg); } } if (Ext.isArray(errors)) { eLen = errors.length; for (e = 0; e < eLen; e++) { error = errors[e]; mark(error.id, error.msg); } } else if (errors instanceof Ext.data.Errors) { eLen = errors.items.length; for (e = 0; e < eLen; e++) { error = errors.items[e]; mark(error.field, error.message); } } else { for (key in errors) { if (errors.hasOwnProperty(key)) { value = errors[key]; mark(key, value, errors); } } } return this; }, setValues: function(values) { var me = this, v, vLen, val, field; function setVal(fieldId, val) { var field = me.findField(fieldId); if (field) { field.setValue(val); if (me.trackResetOnLoad) { field.resetOriginalValue(); } } } Ext.suspendLayouts(); if (Ext.isArray(values)) { vLen = values.length; for (v = 0; v < vLen; v++) { val = values[v]; setVal(val.id, val.value); } } else { Ext.iterate(values, setVal); } Ext.resumeLayouts(true); return this; }, getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues, isSubmitting) { var values = {}, fields = this.getFields().items, fLen = fields.length, isArray = Ext.isArray, field, data, val, bucket, name, f; for (f = 0; f < fLen; f++) { field = fields[f]; if (!dirtyOnly || field.isDirty()) { data = field[useDataValues ? 'getModelData' : 'getSubmitData'](includeEmptyText, isSubmitting); if (Ext.isObject(data)) { for (name in data) { if (data.hasOwnProperty(name)) { val = data[name]; if (includeEmptyText && val === '') { val = field.emptyText || ''; } if (!field.isRadio) { if (values.hasOwnProperty(name)) { bucket = values[name]; if (!isArray(bucket)) { bucket = values[name] = [bucket]; } if (isArray(val)) { values[name] = bucket.concat(val); } else { bucket.push(val); } } else { values[name] = val; } } else { values[name] = values[name] || val; } } } } } } if (asString) { values = Ext.Object.toQueryString(values); } return values; }, getFieldValues: function(dirtyOnly) { return this.getValues(false, dirtyOnly, false, true); }, clearInvalid: function() { Ext.suspendLayouts(); var me = this, fields = me.getFields().items, f, fLen = fields.length; for (f = 0; f < fLen; f++) { fields[f].clearInvalid(); } Ext.resumeLayouts(true); return me; }, reset: function(resetRecord) { Ext.suspendLayouts(); var me = this, fields = me.getFields().items, f, fLen = fields.length; for (f = 0; f < fLen; f++) { fields[f].reset(); } Ext.resumeLayouts(true); if (resetRecord === true) { delete me._record; } return me; }, applyToFields: function(obj) { var fields = this.getFields().items, f, fLen = fields.length; for (f = 0; f < fLen; f++) { Ext.apply(fields[f], obj); } return this; }, applyIfToFields: function(obj) { var fields = this.getFields().items, f, fLen = fields.length; for (f = 0; f < fLen; f++) { Ext.applyIf(fields[f], obj); } return this; } }); Ext.define('Ext.form.FieldAncestor', { xhooks: { initHierarchyState: function(hierarchyState) { if (this.fieldDefaults) { if (hierarchyState.fieldDefaults) { hierarchyState.fieldDefaults = Ext.apply(Ext.Object.chain(hierarchyState.fieldDefaults), this.fieldDefaults); } else { hierarchyState.fieldDefaults = this.fieldDefaults; } } } }, initFieldAncestor: function() { var me = this; me.addEvents( 'fieldvaliditychange', 'fielderrorchange' ); me.monitor = new Ext.container.Monitor({ scope: me, selector: '[isFormField]:not([excludeForm])', addHandler: me.onChildFieldAdd, removeHandler: me.onChildFieldRemove }); me.initFieldDefaults(); }, initMonitor: function() { this.monitor.bind(this); }, onChildFieldAdd: function(field) { var me = this; me.mon(field, 'errorchange', me.handleFieldErrorChange, me); me.mon(field, 'validitychange', me.handleFieldValidityChange, me); }, onChildFieldRemove: function(field) { var me = this; me.mun(field, 'errorchange', me.handleFieldErrorChange, me); me.mun(field, 'validitychange', me.handleFieldValidityChange, me); }, initFieldDefaults: function() { if (!this.fieldDefaults) { this.fieldDefaults = {}; } }, handleFieldValidityChange: function(field, isValid) { var me = this; if (field !== me) { me.fireEvent('fieldvaliditychange', me, field, isValid); me.onFieldValidityChange(field, isValid); } }, handleFieldErrorChange: function(labelable, activeError) { var me = this; if (labelable !== me) { me.fireEvent('fielderrorchange', me, labelable, activeError); me.onFieldErrorChange(labelable, activeError); } }, onFieldValidityChange: Ext.emptyFn, onFieldErrorChange: Ext.emptyFn, beforeDestroy: function(){ this.monitor.unbind(); this.callParent(); } }); Ext.define('Ext.layout.component.field.FieldContainer', { extend: Ext.layout.component.field.Field , alias: 'layout.fieldcontainer', type: 'fieldcontainer', waitForOuterHeightInDom: true, waitForOuterWidthInDom: true, beginLayout: function(ownerContext) { var owner = this.owner; this.callParent(arguments); ownerContext.hasRawContent = true; owner.bodyEl.setStyle('height', ''); owner.containerEl.setStyle('height', ''); ownerContext.containerElContext = ownerContext.getEl('containerEl'); }, measureContentHeight: function (ownerContext) { return ownerContext.hasDomProp('containerLayoutDone') ? this.callParent(arguments) : NaN; }, measureContentWidth: function (ownerContext) { return ownerContext.hasDomProp('containerLayoutDone') ? this.callParent(arguments) : NaN; }, publishInnerWidth: function (ownerContext, width) { var bodyContext = ownerContext.bodyCellContext, innerWidth = bodyContext.el.getWidth(); bodyContext.setWidth(innerWidth, false); ownerContext.containerElContext.setWidth(innerWidth, false); }, publishInnerHeight: function (ownerContext, height) { var bodyContext = ownerContext.bodyCellContext, containerElContext = ownerContext.containerElContext; height -= this.measureLabelErrorHeight(ownerContext); bodyContext.setHeight(height); containerElContext.setHeight(height); } }); Ext.define('Ext.form.FieldContainer', { extend: Ext.container.Container , mixins: { labelable: Ext.form.Labelable , fieldAncestor: Ext.form.FieldAncestor }, alias: 'widget.fieldcontainer', componentLayout: 'fieldcontainer', componentCls: Ext.baseCSSPrefix + 'form-fieldcontainer', customOverflowEl: 'containerEl', childEls: [ 'containerEl' ], combineLabels: false, labelConnector: ', ', combineErrors: false, maskOnDisable: false, invalidCls: '', fieldSubTpl: [ '' ], initComponent: function() { var me = this; me.initLabelable(); me.initFieldAncestor(); me.callParent(); me.initMonitor(); }, getOverflowEl: function(){ return this.containerEl; }, onAdd: function(item) { var me = this; if (item.isLabelable && Ext.isGecko && me.layout.type === 'absolute' && !me.hideLabel && me.labelAlign !== 'top') { item.x += (me.labelWidth + me.labelPad); } me.callParent(arguments); if (item.isLabelable && me.combineLabels) { item.oldHideLabel = item.hideLabel; item.hideLabel = true; } me.updateLabel(); }, onRemove: function(item, isDestroying) { var me = this; me.callParent(arguments); if (!isDestroying) { if (item.isLabelable && me.combineLabels) { item.hideLabel = item.oldHideLabel; } me.updateLabel(); } }, initRenderTpl: function() { var me = this; if (!me.hasOwnProperty('renderTpl')) { me.renderTpl = me.getTpl('labelableRenderTpl'); } return me.callParent(); }, initRenderData: function() { var me = this, data = me.callParent(); data.containerElCls = me.containerElCls; return Ext.applyIf(data, me.getLabelableRenderData()); }, getFieldLabel: function() { var label = this.fieldLabel || ''; if (!label && this.combineLabels) { label = Ext.Array.map(this.query('[isFieldLabelable]'), function(field) { return field.getFieldLabel(); }).join(this.labelConnector); } return label; }, getSubTplData: function() { var ret = this.initRenderData(); Ext.apply(ret, this.subTplData); return ret; }, getSubTplMarkup: function() { var me = this, tpl = me.getTpl('fieldSubTpl'), html; if (!tpl.renderContent) { me.setupRenderTpl(tpl); } html = tpl.apply(me.getSubTplData()); return html; }, updateLabel: function() { var me = this, label = me.labelEl; if (label) { me.setFieldLabel(me.getFieldLabel()); } }, onFieldErrorChange: function(field, activeError) { if (this.combineErrors) { var me = this, oldError = me.getActiveError(), invalidFields = Ext.Array.filter(me.query('[isFormField]'), function(field) { return field.hasActiveError(); }), newErrors = me.getCombinedErrors(invalidFields); if (newErrors) { me.setActiveErrors(newErrors); } else { me.unsetActiveError(); } if (oldError !== me.getActiveError()) { me.doComponentLayout(); } } }, getCombinedErrors: function(invalidFields) { var errors = [], f, fLen = invalidFields.length, field, activeErrors, a, aLen, error, label; for (f = 0; f < fLen; f++) { field = invalidFields[f]; activeErrors = field.getActiveErrors(); aLen = activeErrors.length; for (a = 0; a < aLen; a++) { error = activeErrors[a]; label = field.getFieldLabel(); errors.push((label ? label + ': ' : '') + error); } } return errors; }, getTargetEl: function() { return this.containerEl; }, applyTargetCls: function(targetCls) { var containerElCls = this.containerElCls; this.containerElCls = containerElCls ? containerElCls + ' ' + targetCls : targetCls; } }); Ext.define('Ext.layout.container.CheckboxGroup', { extend: Ext.layout.container.Container , alias: ['layout.checkboxgroup'], autoFlex: true, type: 'checkboxgroup', createsInnerCt: true, childEls: [ 'innerCt' ], renderTpl: [ '', '', '', '', '', '
' ], lastOwnerItemsGeneration : null, beginLayout: function(ownerContext) { var me = this, columns, numCols, i, width, cwidth, totalFlex = 0, flexedCols = 0, autoFlex = me.autoFlex, innerCtStyle = me.innerCt.dom.style; me.callParent(arguments); columns = me.columnNodes; ownerContext.innerCtContext = ownerContext.getEl('innerCt', me); if (!ownerContext.widthModel.shrinkWrap) { numCols = columns.length; if (me.columnsArray) { for (i = 0; i < numCols; i++) { width = me.owner.columns[i]; if (width < 1) { totalFlex += width; flexedCols++; } } for (i = 0; i < numCols; i++) { width = me.owner.columns[i]; if (width < 1) { cwidth = ((width / totalFlex) * 100) + '%'; } else { cwidth = width + 'px'; } columns[i].style.width = cwidth; } } else { for (i = 0; i < numCols; i++) { cwidth = autoFlex ? (1 / numCols * 100) + '%' : ''; columns[i].style.width = cwidth; flexedCols++; } } if (!flexedCols) { innerCtStyle.tableLayout = 'fixed'; innerCtStyle.width = ''; } else if (flexedCols < numCols) { innerCtStyle.tableLayout = 'fixed'; innerCtStyle.width = '100%'; } else { innerCtStyle.tableLayout = 'auto'; if (autoFlex) { innerCtStyle.width = '100%'; } else { innerCtStyle.width = ''; } } } else { innerCtStyle.tableLayout = 'auto'; innerCtStyle.width = ''; } }, cacheElements: function () { var me = this; me.callParent(); me.rowEl = me.innerCt.down('tr'); me.columnNodes = me.rowEl.dom.childNodes; }, calculate: function(ownerContext) { var me = this, targetContext, widthShrinkWrap, heightShrinkWrap, shrinkWrap, table, targetPadding; if (!ownerContext.getDomProp('containerChildrenSizeDone')) { me.done = false; } else { targetContext = ownerContext.innerCtContext; widthShrinkWrap = ownerContext.widthModel.shrinkWrap; heightShrinkWrap = ownerContext.heightModel.shrinkWrap; shrinkWrap = heightShrinkWrap || widthShrinkWrap; table = targetContext.el.dom; targetPadding = shrinkWrap && targetContext.getPaddingInfo(); if (widthShrinkWrap) { ownerContext.setContentWidth(table.offsetWidth + targetPadding.width, true); } if (heightShrinkWrap) { ownerContext.setContentHeight(table.offsetHeight + targetPadding.height, true); } } }, doRenderColumn: function (out, renderData, columnIndex) { var me = renderData.$layout, owner = me.owner, columnCount = renderData.columnCount, items = owner.items.items, itemCount = items.length, item, itemIndex, rowCount, increment, tree; if (owner.vertical) { rowCount = Math.ceil(itemCount / columnCount); itemIndex = columnIndex * rowCount; itemCount = Math.min(itemCount, itemIndex + rowCount); increment = 1; } else { itemIndex = columnIndex; increment = columnCount; } for ( ; itemIndex < itemCount; itemIndex += increment) { item = items[itemIndex]; me.configureItem(item); tree = item.getRenderTree(); Ext.DomHelper.generateMarkup(tree, out); } }, getColumnCount: function() { var me = this, owner = me.owner, ownerColumns = owner.columns; if (me.columnsArray) { return ownerColumns.length; } if (Ext.isNumber(ownerColumns)) { return ownerColumns; } return owner.items.length; }, getItemSizePolicy: function (item) { return this.autoSizePolicy; }, getRenderData: function () { var me = this, data = me.callParent(), owner = me.owner, i, columns = me.getColumnCount(), width, column, cwidth, autoFlex = me.autoFlex, totalFlex = 0, flexedCols = 0; if (me.columnsArray) { for (i=0; i < columns; i++) { width = me.owner.columns[i]; if (width < 1) { totalFlex += width; flexedCols++; } } } data.colCls = owner.groupCls; data.columnCount = columns; data.columns = []; for (i = 0; i < columns; i++) { column = (data.columns[i] = {}); if (me.columnsArray) { width = me.owner.columns[i]; if (width < 1) { cwidth = ((width / totalFlex) * 100) + '%'; } else { cwidth = width + 'px'; } column.style = 'width:' + cwidth; } else { column.style = 'width:' + (1 / columns * 100) + '%'; flexedCols++; } } data.tableStyle = !flexedCols ? 'table-layout:fixed;' : (flexedCols < columns) ? 'table-layout:fixed;width:100%' : (autoFlex) ? 'table-layout:auto;width:100%' : 'table-layout:auto;'; return data; }, initLayout: function () { var me = this, owner = me.owner; me.columnsArray = Ext.isArray(owner.columns); me.autoColumns = !owner.columns || owner.columns === 'auto'; me.vertical = owner.vertical; me.callParent(); }, isValidParent: function() { return true; }, setupRenderTpl: function (renderTpl) { this.callParent(arguments); renderTpl.renderColumn = this.doRenderColumn; }, renderChildren: function () { var me = this, generation = me.owner.items.generation; if (me.lastOwnerItemsGeneration !== generation) { me.lastOwnerItemsGeneration = generation; me.renderItems(me.getLayoutItems()); } }, renderItems : function(items) { var me = this, itemCount = items.length, i, item, rowCount, columnCount, rowIndex, columnIndex; if (itemCount) { Ext.suspendLayouts(); if (me.autoColumns) { me.addMissingColumns(itemCount); } columnCount = me.columnNodes.length; rowCount = Math.ceil(itemCount / columnCount); for (i = 0; i < itemCount; i++) { item = items[i]; rowIndex = me.getRenderRowIndex(i, rowCount, columnCount); columnIndex = me.getRenderColumnIndex(i, rowCount, columnCount); if (!item.rendered) { me.renderItem(item, rowIndex, columnIndex); } else if (!me.isItemAtPosition(item, rowIndex, columnIndex)) { me.moveItem(item, rowIndex, columnIndex); } } if (me.autoColumns) { me.removeExceedingColumns(itemCount); } Ext.resumeLayouts(true); } }, isItemAtPosition : function(item, rowIndex, columnIndex) { return item.el.dom === this.getNodeAt(rowIndex, columnIndex); }, getRenderColumnIndex : function(itemIndex, rowCount, columnCount) { if (this.vertical) { return Math.floor(itemIndex / rowCount); } else { return itemIndex % columnCount; } }, getRenderRowIndex : function(itemIndex, rowCount, columnCount) { var me = this; if (me.vertical) { return itemIndex % rowCount; } else { return Math.floor(itemIndex / columnCount); } }, getNodeAt : function(rowIndex, columnIndex) { return this.columnNodes[columnIndex].childNodes[rowIndex]; }, addMissingColumns : function(itemsCount) { var me = this, existingColumnsCount = me.columnNodes.length, missingColumnsCount, row, cls, i; if (existingColumnsCount < itemsCount) { missingColumnsCount = itemsCount - existingColumnsCount; row = me.rowEl; cls = me.owner.groupCls; for (i = 0; i < missingColumnsCount; i++) { row.createChild({ cls: cls, tag: 'td', vAlign: 'top', role: 'presentation' }); } } }, removeExceedingColumns : function(itemsCount) { var me = this, existingColumnsCount = me.columnNodes.length, exceedingColumnsCount, row, i; if (existingColumnsCount > itemsCount) { exceedingColumnsCount = existingColumnsCount - itemsCount; row = me.rowEl; for (i = 0; i < exceedingColumnsCount; i++) { row.last().remove(); } } }, renderItem : function(item, rowIndex, columnIndex) { var me = this; me.configureItem(item); item.render(Ext.get(me.columnNodes[columnIndex]), rowIndex); me.afterRenderItem(item); }, moveItem : function(item, rowIndex, columnIndex) { var me = this, column = me.columnNodes[columnIndex], targetNode = column.childNodes[rowIndex]; column.insertBefore(item.el.dom, targetNode || null); } }); Ext.define('Ext.form.CheckboxManager', { extend: Ext.util.MixedCollection , singleton: true, getByName: function(name, formId) { return this.filterBy(function(item) { return item.name == name && item.getFormId() == formId; }); } }); Ext.define('Ext.form.field.Checkbox', { extend: Ext.form.field.Base , alias: ['widget.checkboxfield', 'widget.checkbox'], alternateClassName: 'Ext.form.Checkbox', componentLayout: 'field', stretchInputElFixed: false, childEls: [ 'boxLabelEl' ], fieldSubTpl: [ '', { disableFormats: true, compiled: true } ], subTplInsertions: [ 'beforeBoxLabelTpl', 'afterBoxLabelTpl', 'beforeBoxLabelTextTpl', 'afterBoxLabelTextTpl', 'boxLabelAttrTpl', 'inputAttrTpl' ], isCheckbox: true, focusCls: 'form-checkbox-focus', extraFieldBodyCls: Ext.baseCSSPrefix + 'form-cb-wrap', checked: false, checkedCls: Ext.baseCSSPrefix + 'form-cb-checked', boxLabelCls: Ext.baseCSSPrefix + 'form-cb-label', boxLabelAlign: 'after', afterLabelCls: Ext.baseCSSPrefix + 'form-cb-after', wrapInnerCls: Ext.baseCSSPrefix + 'form-cb-wrap-inner', noBoxLabelCls: Ext.baseCSSPrefix + 'form-cb-wrap-inner-no-box-label', inputValue: 'on', checkChangeEvents: [], inputType: 'checkbox', ariaRole: 'checkbox', onRe: /^on$/i, inputCls: Ext.baseCSSPrefix + 'form-cb', initComponent: function() { var me = this, value = me.value; if (value !== undefined) { me.checked = me.isChecked(value, me.inputValue); } me.callParent(arguments); me.getManager().add(me); }, initValue: function() { var me = this, checked = !!me.checked; me.originalValue = me.lastValue = checked; me.setValue(checked); }, getElConfig: function() { var me = this; if (me.isChecked(me.rawValue, me.inputValue)) { me.addCls(me.checkedCls); } return me.callParent(); }, getSubTplData: function() { var me = this, boxLabel = me.boxLabel, boxLabelAlign = me.boxLabelAlign, labelAlignedBefore = boxLabel && boxLabelAlign === 'before'; return Ext.apply(me.callParent(), { disabled: me.readOnly || me.disabled, wrapInnerCls: me.wrapInnerCls, boxLabel: boxLabel, boxLabelCls: me.boxLabelCls, boxLabelAlign: boxLabelAlign, labelAlignedBefore: labelAlignedBefore, afterLabelCls: labelAlignedBefore ? me.afterLabelCls : '', noBoxLabelCls: !boxLabel ? me.noBoxLabelCls : '', role: me.ariaRole }); }, initEvents: function() { var me = this; me.callParent(); me.mon(me.inputEl, 'click', me.onBoxClick, me); }, setBoxLabel: function(boxLabel){ var me = this; me.boxLabel = boxLabel; if (me.rendered) { me.boxLabelEl.update(boxLabel); } }, onBoxClick: function(e) { var me = this; if (!me.disabled && !me.readOnly) { this.setValue(!this.checked); } }, getRawValue: function() { return this.checked; }, getValue: function() { return this.checked; }, getSubmitValue: function() { var unchecked = this.uncheckedValue, uncheckedVal = Ext.isDefined(unchecked) ? unchecked : null; return this.checked ? this.inputValue : uncheckedVal; }, isChecked: function(rawValue, inputValue) { return (rawValue === true || rawValue === 'true' || rawValue === '1' || rawValue === 1 || (((Ext.isString(rawValue) || Ext.isNumber(rawValue)) && inputValue) ? rawValue == inputValue : this.onRe.test(rawValue))); }, setRawValue: function(value) { var me = this, inputEl = me.inputEl, checked = me.isChecked(value, me.inputValue); if (inputEl) { me[checked ? 'addCls' : 'removeCls'](me.checkedCls); } me.checked = me.rawValue = checked; return checked; }, setValue: function(checked) { var me = this, boxes, i, len, box; if (Ext.isArray(checked)) { boxes = me.getManager().getByName(me.name, me.getFormId()).items; len = boxes.length; for (i = 0; i < len; ++i) { box = boxes[i]; box.setValue(Ext.Array.contains(checked, box.inputValue)); } } else { me.callParent(arguments); } return me; }, valueToRaw: function(value) { return value; }, onChange: function(newVal, oldVal) { var me = this, handler = me.handler; if (handler) { handler.call(me.scope || me, me, newVal); } me.callParent(arguments); }, resetOriginalValue: function( fromBoxInGroup){ var me = this, boxes, box, len, i; if (!fromBoxInGroup) { boxes = me.getManager().getByName(me.name, me.getFormId()).items; len = boxes.length; for (i = 0; i < len; ++i) { box = boxes[i]; if (box !== me) { boxes[i].resetOriginalValue(true); } } } me.callParent(); }, beforeDestroy: function(){ this.callParent(); this.getManager().removeAtKey(this.id); }, getManager: function() { return Ext.form.CheckboxManager; }, onEnable: function() { var me = this, inputEl = me.inputEl; me.callParent(); if (inputEl) { inputEl.dom.disabled = me.readOnly; } }, setReadOnly: function(readOnly) { var me = this, inputEl = me.inputEl; if (inputEl) { inputEl.dom.disabled = !!readOnly || me.disabled; } me.callParent(arguments); }, getFormId: function(){ var me = this, form; if (!me.formId) { form = me.up('form'); if (form) { me.formId = form.id; } } return me.formId; } }); Ext.define('Ext.form.CheckboxGroup', { extend: Ext.form.FieldContainer , mixins: { field: Ext.form.field.Field }, alias: 'widget.checkboxgroup', columns : 'auto', vertical : false, allowBlank : true, blankText : "You must select at least one item in this group", defaultType : 'checkboxfield', groupCls : Ext.baseCSSPrefix + 'form-check-group', extraFieldBodyCls: Ext.baseCSSPrefix + 'form-checkboxgroup-body', layout: 'checkboxgroup', componentCls: Ext.baseCSSPrefix + 'form-checkboxgroup', ariaRole: 'group', initComponent: function() { var me = this; me.callParent(); me.initField(); }, initValue: function() { var me = this, valueCfg = me.value; me.originalValue = me.lastValue = valueCfg || me.getValue(); if (valueCfg) { me.setValue(valueCfg); } }, onAdd: function(item) { var me = this, items, len, i; if (item.isCheckbox) { me.mon(item, 'change', me.checkChange, me); } else if (item.isContainer) { items = item.items.items; for (i = 0, len = items.length; i < len; i++) { me.onAdd(items[i]); } } me.callParent(arguments); }, onRemove: function(item) { var me = this, items, len, i; if (item.isCheckbox) { me.mun(item, 'change', me.checkChange, me); } else if (item.isContainer) { items = item.items.items; for (i = 0, len = items.length; i < len; i++) { me.onRemove(items[i]); } } me.callParent(arguments); }, isEqual: function(value1, value2) { var toQueryString = Ext.Object.toQueryString; return toQueryString(value1) === toQueryString(value2); }, getErrors: function() { var errors = []; if (!this.allowBlank && Ext.isEmpty(this.getChecked())) { errors.push(this.blankText); } return errors; }, getBoxes: function(query) { return this.query('[isCheckbox]' + (query||'')); }, eachBox: function(fn, scope) { Ext.Array.forEach(this.getBoxes(), fn, scope || this); }, getChecked: function() { return this.getBoxes('[checked]'); }, isDirty: function(){ var boxes = this.getBoxes(), b , bLen = boxes.length; for (b = 0; b < bLen; b++) { if (boxes[b].isDirty()) { return true; } } }, setReadOnly: function(readOnly) { var boxes = this.getBoxes(), b, bLen = boxes.length; for (b = 0; b < bLen; b++) { boxes[b].setReadOnly(readOnly); } this.readOnly = readOnly; }, reset: function() { var me = this, hadError = me.hasActiveError(), preventMark = me.preventMark; me.preventMark = true; me.batchChanges(function() { var boxes = me.getBoxes(), b, bLen = boxes.length; for (b = 0; b < bLen; b++) { boxes[b].reset(); } }); me.preventMark = preventMark; me.unsetActiveError(); if (hadError) { me.updateLayout(); } }, resetOriginalValue: function(){ var me = this, boxes = me.getBoxes(), b, bLen = boxes.length; for (b = 0; b < bLen; b++) { boxes[b].resetOriginalValue(); } me.originalValue = me.getValue(); me.checkDirty(); }, setValue: function(value) { var me = this, boxes = me.getBoxes(), b, bLen = boxes.length, box, name, cbValue; me.batchChanges(function() { for (b = 0; b < bLen; b++) { box = boxes[b]; name = box.getName(); cbValue = false; if (value && value.hasOwnProperty(name)) { if (Ext.isArray(value[name])) { cbValue = Ext.Array.contains(value[name], box.inputValue); } else { cbValue = value[name]; } } box.setValue(cbValue); } }); return me; }, getValue: function() { var values = {}, boxes = this.getBoxes(), b, bLen = boxes.length, box, name, inputValue, bucket; for (b = 0; b < bLen; b++) { box = boxes[b]; name = box.getName(); inputValue = box.inputValue; if (box.getValue()) { if (values.hasOwnProperty(name)) { bucket = values[name]; if (!Ext.isArray(bucket)) { bucket = values[name] = [bucket]; } bucket.push(inputValue); } else { values[name] = inputValue; } } } return values; }, getSubmitData: function() { return null; }, getModelData: function() { return null; }, validate: function() { var me = this, errors, isValid, wasValid; if (me.disabled) { isValid = true; } else { errors = me.getErrors(); isValid = Ext.isEmpty(errors); wasValid = me.wasValid; if (isValid) { me.unsetActiveError(); } else { me.setActiveError(errors); } } if (isValid !== wasValid) { me.wasValid = isValid; me.fireEvent('validitychange', me, isValid); me.updateLayout(); } return isValid; } }, function() { this.borrow(Ext.form.field.Base, ['markInvalid', 'clearInvalid', 'setError']); }); Ext.define('Ext.form.FieldSet', { extend: Ext.container.Container , mixins: { fieldAncestor: Ext.form.FieldAncestor }, alias: 'widget.fieldset', collapsed: false, toggleOnTitleClick : true, baseCls: Ext.baseCSSPrefix + 'fieldset', layout: 'anchor', componentLayout: 'fieldset', ariaRole: null, autoEl: 'fieldset', childEls: [ 'body' ], renderTpl: [ '{%this.renderLegend(out,values);%}', '' ], stateEvents : [ 'collapse', 'expand' ], maskOnDisable: false, beforeDestroy: function(){ var me = this, legend = me.legend; if (legend) { delete legend.ownerCt; legend.destroy(); me.legend = null; } me.callParent(); }, initComponent: function() { var me = this, baseCls = me.baseCls; me.initFieldAncestor(); me.callParent(); me.layout.managePadding = me.layout.manageOverflow = false; me.addEvents( "beforeexpand", "beforecollapse", "expand", "collapse" ); if (me.collapsed) { me.addCls(baseCls + '-collapsed'); me.collapse(); } if (me.title || me.checkboxToggle || me.collapsible) { me.addTitleClasses(); me.legend = Ext.widget(me.createLegendCt()); } me.initMonitor(); }, initPadding: function(targetEl) { var me = this, body = me.getProtoBody(), padding = me.padding, bodyPadding; if (padding !== undefined) { if (Ext.isIEQuirks || Ext.isIE8m) { padding = me.parseBox(padding); bodyPadding = Ext.Element.parseBox(0); bodyPadding.top = padding.top; padding.top = 0; body.setStyle('padding', me.unitizeBox(bodyPadding)); } targetEl.setStyle('padding', me.unitizeBox(padding)); } }, getProtoBody: function () { var me = this, body = me.protoBody; if (!body) { me.protoBody = body = new Ext.util.ProtoElement({ styleProp: 'bodyStyle', styleIsText: true }); } return body; }, initRenderData: function() { var me = this, data = me.callParent(); data.bodyTargetCls = me.bodyTargetCls; me.protoBody.writeTo(data); delete me.protoBody; return data; }, getState: function () { var state = this.callParent(); state = this.addPropertyToState(state, 'collapsed'); return state; }, afterCollapse: Ext.emptyFn, afterExpand: Ext.emptyFn, collapsedHorizontal: function () { return true; }, collapsedVertical: function () { return true; }, createLegendCt: function () { var me = this, items = [], legend = { xtype: 'container', baseCls: me.baseCls + '-header', id: me.id + '-legend', autoEl: 'legend', ariaRole: null, ariaLabelledBy: '.' + me.baseCls + '-header-text', items: items, ownerCt: me, shrinkWrap: true, ownerLayout: me.componentLayout }; if (me.checkboxToggle) { items.push(me.createCheckboxCmp()); } else if (me.collapsible) { items.push(me.createToggleCmp()); } items.push(me.createTitleCmp()); return legend; }, createTitleCmp: function() { var me = this, cfg = { xtype : 'component', html : me.title, cls : me.baseCls + '-header-text', id : me.id + '-legendTitle' }; if (me.collapsible && me.toggleOnTitleClick) { cfg.listeners = { click : { element: 'el', scope : me, fn : me.toggle } }; cfg.cls += ' ' + me.baseCls + '-header-text-collapsible'; } return (me.titleCmp = Ext.widget(cfg)); }, createCheckboxCmp: function() { var me = this, suffix = '-checkbox'; me.checkboxCmp = Ext.widget({ xtype: 'checkbox', hideEmptyLabel: true, name: me.checkboxName || me.id + suffix, cls: me.baseCls + '-header' + suffix, id: me.id + '-legendChk', checked: !me.collapsed, msgTarget: 'none', listeners: { change: me.onCheckChange, scope: me } }); return me.checkboxCmp; }, createToggleCmp: function() { var me = this; me.toggleCmp = Ext.widget({ xtype: 'tool', height: 15, width: 15, type: 'toggle', handler: me.toggle, id: me.id + '-legendToggle', scope: me }); return me.toggleCmp; }, doRenderLegend: function (out, renderData) { var me = renderData.$comp, legend = me.legend, tree; if (legend) { legend.ownerLayout.configureItem(legend); tree = legend.getRenderTree(); Ext.DomHelper.generateMarkup(tree, out); } }, finishRender: function () { var legend = this.legend; this.callParent(); if (legend) { legend.finishRender(); } }, getCollapsed: function () { return this.collapsed ? 'top' : false; }, getCollapsedDockedItems: function () { var legend = this.legend; return legend ? [ legend ] : []; }, setTitle: function(title) { var me = this, legend = me.legend, baseCls = me.baseCls; me.title = title; if (me.rendered) { if (!legend) { me.legend = legend = Ext.widget(me.createLegendCt()); me.addTitleClasses(); legend.ownerLayout.configureItem(legend); legend.render(me.el, 0); } me.titleCmp.update(title); } else if (legend) { me.titleCmp.update(title); } else { me.addTitleClasses(); me.legend = Ext.widget(me.createLegendCt()); } return me; }, addTitleClasses: function(){ var me = this, title = me.title, baseCls = me.baseCls; if (title) { me.addCls(baseCls + '-with-title'); } if (title || me.checkboxToggle || me.collapsible) { me.addCls(baseCls + '-with-legend'); } }, applyTargetCls: function(targetCls) { this.bodyTargetCls = targetCls; }, getTargetEl : function() { return this.body || this.frameBody || this.el; }, getDefaultContentTarget: function() { return this.body; }, expand : function(){ return this.setExpanded(true); }, collapse : function() { return this.setExpanded(false); }, setExpanded: function(expanded) { var me = this, checkboxCmp = me.checkboxCmp, operation = expanded ? 'expand' : 'collapse'; if (!me.rendered || me.fireEvent('before' + operation, me) !== false) { expanded = !!expanded; if (checkboxCmp) { checkboxCmp.setValue(expanded); } if (expanded) { me.removeCls(me.baseCls + '-collapsed'); } else { me.addCls(me.baseCls + '-collapsed'); } me.collapsed = !expanded; if (expanded) { delete me.getHierarchyState().collapsed; } else { me.getHierarchyState().collapsed = true; } if (me.rendered) { me.updateLayout({ isRoot: false }); me.fireEvent(operation, me); } } return me; }, getRefItems: function(deep) { var refItems = this.callParent(arguments), legend = this.legend; if (legend) { refItems.unshift(legend); if (deep) { refItems.unshift.apply(refItems, legend.getRefItems(true)); } } return refItems; }, toggle: function() { this.setExpanded(!!this.collapsed); }, onCheckChange: function(cmp, checked) { this.setExpanded(checked); }, setupRenderTpl: function (renderTpl) { this.callParent(arguments); renderTpl.renderLegend = this.doRenderLegend; } }); Ext.define('Ext.form.Label', { extend: Ext.Component , alias: 'widget.label', autoEl: 'label', maskOnDisable: false, getElConfig: function(){ var me = this; me.html = me.text ? Ext.util.Format.htmlEncode(me.text) : (me.html || ''); return Ext.apply(me.callParent(), { htmlFor: me.forId || '' }); }, setText : function(text, encode){ var me = this; encode = encode !== false; if(encode) { me.text = text; delete me.html; } else { me.html = text; delete me.text; } if(me.rendered){ me.el.dom.innerHTML = encode !== false ? Ext.util.Format.htmlEncode(text) : text; me.updateLayout(); } return me; } }); Ext.define('Ext.form.Panel', { extend: Ext.panel.Panel , mixins: { fieldAncestor: Ext.form.FieldAncestor }, alias: 'widget.form', alternateClassName: ['Ext.FormPanel', 'Ext.form.FormPanel'], layout: 'anchor', ariaRole: 'form', basicFormConfigs: [ 'api', 'baseParams', 'errorReader', 'jsonSubmit', 'method', 'paramOrder', 'paramsAsHash', 'reader', 'standardSubmit', 'timeout', 'trackResetOnLoad', 'url', 'waitMsgTarget', 'waitTitle' ], initComponent: function() { var me = this; if (me.frame) { me.border = false; } me.initFieldAncestor(); me.callParent(); me.relayEvents(me.form, [ 'beforeaction', 'actionfailed', 'actioncomplete', 'validitychange', 'dirtychange' ]); if (me.pollForChanges) { me.startPolling(me.pollInterval || 500); } }, initItems: function() { this.callParent(); this.initMonitor(); this.form = this.createForm(); }, afterFirstLayout: function() { this.callParent(arguments); this.form.initialize(); }, createForm: function() { var cfg = {}, props = this.basicFormConfigs, len = props.length, i = 0, prop; for (; i < len; ++i) { prop = props[i]; cfg[prop] = this[prop]; } return new Ext.form.Basic(this, cfg); }, getForm: function() { return this.form; }, loadRecord: function(record) { return this.getForm().loadRecord(record); }, getRecord: function() { return this.getForm().getRecord(); }, updateRecord: function(record) { return this.getForm().updateRecord(record); }, getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) { return this.getForm().getValues(asString, dirtyOnly, includeEmptyText, useDataValues); }, isDirty: function () { return this.form.isDirty(); }, isValid: function () { return this.form.isValid(); }, hasInvalidField: function () { return this.form.hasInvalidField(); }, beforeDestroy: function() { this.stopPolling(); this.form.destroy(); this.callParent(); }, load: function(options) { this.form.load(options); }, submit: function(options) { this.form.submit(options); }, startPolling: function(interval) { this.stopPolling(); var task = new Ext.util.TaskRunner(interval); task.start({ interval: 0, run: this.checkChange, scope: this }); this.pollTask = task; }, stopPolling: function() { var task = this.pollTask; if (task) { task.stopAll(); delete this.pollTask; } }, checkChange: function() { var fields = this.form.getFields().items, f, fLen = fields.length; for (f = 0; f < fLen; f++) { fields[f].checkChange(); } } }); Ext.define('Ext.form.RadioManager', { extend: Ext.util.MixedCollection , singleton: true, getByName: function(name, formId) { return this.filterBy(function(item) { return item.name == name && item.getFormId() == formId; }); }, getWithValue: function(name, value, formId) { return this.filterBy(function(item) { return item.name == name && item.inputValue == value && item.getFormId() == formId; }); }, getChecked: function(name, formId) { return this.findBy(function(item) { return item.name == name && item.checked && item.getFormId() == formId; }); } }); Ext.define('Ext.form.field.Radio', { extend: Ext.form.field.Checkbox , alias: ['widget.radiofield', 'widget.radio'], alternateClassName: 'Ext.form.Radio', isRadio: true, focusCls: 'form-radio-focus', inputType: 'radio', ariaRole: 'radio', formId: null, getGroupValue: function() { var selected = this.getManager().getChecked(this.name, this.getFormId()); return selected ? selected.inputValue : null; }, onBoxClick: function(e) { var me = this; if (!me.disabled && !me.readOnly) { this.setValue(true); } }, onRemoved: function(){ this.callParent(arguments); this.formId = null; }, setValue: function(v) { var me = this, active; if (Ext.isBoolean(v)) { me.callParent(arguments); } else { active = me.getManager().getWithValue(me.name, v, me.getFormId()).getAt(0); if (active) { active.setValue(true); } } return me; }, getSubmitValue: function() { return this.checked ? this.inputValue : null; }, getModelData: function() { var o = this.callParent(arguments); if (o) { o[this.getName()] = this.getSubmitValue(); } return o; }, onChange: function(newVal, oldVal) { var me = this, r, rLen, radio, radios; me.callParent(arguments); if (newVal) { radios = me.getManager().getByName(me.name, me.getFormId()).items; rLen = radios.length; for (r = 0; r < rLen; r++) { radio = radios[r]; if (radio !== me) { radio.setValue(false); } } } }, getManager: function() { return Ext.form.RadioManager; } }); Ext.define('Ext.form.RadioGroup', { extend: Ext.form.CheckboxGroup , alias: 'widget.radiogroup', allowBlank : true, blankText : 'You must select one item in this group', defaultType : 'radiofield', groupCls : Ext.baseCSSPrefix + 'form-radio-group', ariaRole: 'radiogroup', getBoxes: function(query) { return this.query('[isRadio]' + (query||'')); }, checkChange: function() { var value = this.getValue(), key = Ext.Object.getKeys(value)[0]; if (Ext.isArray(value[key])) { return; } this.callParent(arguments); }, setValue: function(value) { var cbValue, first, formId, radios, i, len, name; if (Ext.isObject(value)) { for (name in value) { if (value.hasOwnProperty(name)) { cbValue = value[name]; first = this.items.first(); formId = first ? first.getFormId() : null; radios = Ext.form.RadioManager.getWithValue(name, cbValue, formId).items; len = radios.length; for (i = 0; i < len; ++i) { radios[i].setValue(true); } } } } return this; } }); Ext.define('Ext.form.action.DirectLoad', { extend: Ext.form.action.Load , alternateClassName: 'Ext.form.Action.DirectLoad', alias: 'formaction.directload', type: 'directload', run: function() { var me = this, form = me.form, api = form.api, fn = api.load, method, args; if (typeof fn !== 'function') { api.load = fn = Ext.direct.Manager.parseMethod(fn); } method = fn.directCfg.method; args = method.getArgs(me.getParams(), form.paramOrder, form.paramsAsHash); args.push(me.onComplete, me); fn.apply(window, args); }, processResponse: function(result) { return (this.result = result); }, onComplete: function(data, response) { if (data) { this.onSuccess(data); } else { this.onFailure(null); } } }); Ext.define('Ext.form.action.DirectSubmit', { extend: Ext.form.action.Submit , alternateClassName: 'Ext.form.Action.DirectSubmit', alias: 'formaction.directsubmit', type: 'directsubmit', doSubmit: function() { var me = this, form = me.form, api = form.api, fn = api.submit, callback = Ext.Function.bind(me.onComplete, me), formInfo = me.buildForm(), options; if (typeof fn !== 'function') { api.submit = fn = Ext.direct.Manager.parseMethod(fn); me.cleanup(formInfo); } if (me.timeout || form.timeout) { options = { timeout: me.timeout * 1000 || form.timeout * 1000 }; } fn.call(window, formInfo.formEl, callback, me, options); me.cleanup(formInfo); }, processResponse: function(result) { return (this.result = result); }, onComplete: function(data, response){ if (data) { this.onSuccess(data); } else { this.onFailure(null); } } }); Ext.define('Ext.form.action.StandardSubmit', { extend: Ext.form.action.Submit , alias: 'formaction.standardsubmit', doSubmit: function() { var formInfo = this.buildForm(); formInfo.formEl.submit(); this.cleanup(formInfo); } }); Ext.define('Ext.layout.component.field.Trigger', { alias: 'layout.triggerfield', extend: Ext.layout.component.field.Field , type: 'triggerfield', setWidthInDom: true, borderWidths: {}, beginLayout: function(ownerContext) { var me = this, owner = me.owner, flags; ownerContext.triggerWrap = ownerContext.getEl('triggerWrap'); me.callParent(arguments); flags = owner.getTriggerStateFlags(); if (flags != owner.lastTriggerStateFlags) { owner.lastTriggerStateFlags = flags; me.updateEditState(); } }, beginLayoutCycle: function(ownerContext){ this.callParent(arguments); if (ownerContext.widthModel.shrinkWrap && !this.owner.inputWidth) { ownerContext.inputContext.el.setStyle('width', ''); } }, beginLayoutFixed: function (ownerContext, width, suffix) { var me = this, owner = ownerContext.target, ieInputWidthAdjustment = me.ieInputWidthAdjustment || 0, inputWidth = '100%', triggerWrap = owner.triggerWrap; me.callParent(arguments); owner.inputCell.setStyle('width', '100%'); if(ieInputWidthAdjustment) { me.adjustIEInputPadding(ownerContext); if(suffix === 'px') { if (owner.inputWidth) { inputWidth = owner.inputWidth - me.getExtraWidth(ownerContext); } else { inputWidth = width - ieInputWidthAdjustment - me.getExtraWidth(ownerContext); } inputWidth += 'px'; } } owner.inputEl.setStyle('width', inputWidth); inputWidth = owner.inputWidth; if (inputWidth) { triggerWrap.setStyle('width', inputWidth + (ieInputWidthAdjustment) + 'px'); } else { triggerWrap.setStyle('width', width + suffix); } triggerWrap.setStyle('table-layout', 'fixed'); }, adjustIEInputPadding: function(ownerContext) { this.owner.inputCell.setStyle('padding-right', this.ieInputWidthAdjustment + 'px'); }, getExtraWidth: function(ownerContext) { var me = this, owner = me.owner, borderWidths = me.borderWidths, ui = owner.ui + owner.triggerEl.getCount(); if (!(ui in borderWidths)) { borderWidths[ui] = ownerContext.triggerWrap.getBorderInfo().width } return borderWidths[ui] + owner.getTriggerWidth(); }, beginLayoutShrinkWrap: function (ownerContext) { var owner = ownerContext.target, emptyString = '', inputWidth = owner.inputWidth, triggerWrap = owner.triggerWrap; this.callParent(arguments); if (inputWidth) { triggerWrap.setStyle('width', inputWidth + 'px'); inputWidth = (inputWidth - this.getExtraWidth(ownerContext)) + 'px'; owner.inputEl.setStyle('width', inputWidth); owner.inputCell.setStyle('width', inputWidth); } else { owner.inputCell.setStyle('width', emptyString); owner.inputEl.setStyle('width', emptyString); triggerWrap.setStyle('width', emptyString); triggerWrap.setStyle('table-layout', 'auto'); } }, getTextWidth: function () { var me = this, owner = me.owner, inputEl = owner.inputEl, value; value = (inputEl.dom.value || (owner.hasFocus ? '' : owner.emptyText) || '') + owner.growAppend; return inputEl.getTextWidth(value); }, publishOwnerWidth: function(ownerContext, width) { var owner = this.owner; this.callParent(arguments); if (!owner.grow && !owner.inputWidth) { width -= this.getExtraWidth(ownerContext); if (owner.labelAlign != 'top') { width -= owner.getLabelWidth(); } ownerContext.inputContext.setWidth(width); } }, publishInnerHeight: function(ownerContext, height) { ownerContext.inputContext.setHeight(height - this.measureLabelErrorHeight(ownerContext)); }, measureContentWidth: function (ownerContext) { var me = this, owner = me.owner, width = me.callParent(arguments), inputContext = ownerContext.inputContext, calcWidth, max, min; if (owner.grow && !ownerContext.state.growHandled) { calcWidth = me.getTextWidth() + ownerContext.inputContext.getFrameInfo().width; max = owner.growMax; min = Math.min(max, width); max = Math.max(owner.growMin, max, min); calcWidth = Ext.Number.constrain(calcWidth, owner.growMin, max); inputContext.setWidth(calcWidth); ownerContext.state.growHandled = true; inputContext.domBlock(me, 'width'); width = NaN; } else if (!owner.inputWidth) { width -= me.getExtraWidth(ownerContext); } return width; }, updateEditState: function() { var me = this, owner = me.owner, inputEl = owner.inputEl, noeditCls = Ext.baseCSSPrefix + 'trigger-noedit', displayed, readOnly; if (me.owner.readOnly) { inputEl.addCls(noeditCls); readOnly = true; displayed = false; } else { if (me.owner.editable) { inputEl.removeCls(noeditCls); readOnly = false; } else { inputEl.addCls(noeditCls); readOnly = true; } displayed = !me.owner.hideTrigger; } owner.triggerCell.setDisplayed(displayed); inputEl.dom.readOnly = readOnly; } }); Ext.define('Ext.form.field.Trigger', { extend: Ext.form.field.Text , alias: ['widget.triggerfield', 'widget.trigger'], alternateClassName: ['Ext.form.TriggerField', 'Ext.form.TwinTriggerField', 'Ext.form.Trigger'], childEls: [ { name: 'triggerCell', select: '.' + Ext.baseCSSPrefix + 'trigger-cell' }, { name: 'triggerEl', select: '.' + Ext.baseCSSPrefix + 'form-trigger' }, 'triggerWrap', 'inputCell' ], triggerBaseCls: Ext.baseCSSPrefix + 'form-trigger', triggerWrapCls: Ext.baseCSSPrefix + 'form-trigger-wrap', triggerNoEditCls: Ext.baseCSSPrefix + 'trigger-noedit', hideTrigger: false, editable: true, readOnly: false, repeatTriggerClick: false, autoSize: Ext.emptyFn, monitorTab: true, mimicing: false, triggerIndexRe: /trigger-index-(\d+)/, extraTriggerCls: '', componentLayout: 'triggerfield', initComponent: function() { this.wrapFocusCls = this.triggerWrapCls + '-focus'; this.callParent(arguments); }, getSubTplMarkup: function(values) { var me = this, childElCls = values.childElCls, field = me.callParent(arguments); return [ '', '', '', '', me.getTriggerMarkup(), '', '', '' ].join(''); }, getSubTplData: function(){ var me = this, data = me.callParent(), readOnly = me.readOnly === true, editable = me.editable !== false; return Ext.apply(data, { editableCls: (readOnly || !editable) ? ' ' + me.triggerNoEditCls : '', readOnly: !editable || readOnly }); }, getLabelableRenderData: function() { var me = this, triggerWrapCls = me.triggerWrapCls, result = me.callParent(arguments); return Ext.applyIf(result, { triggerWrapCls: triggerWrapCls, triggerMarkup: me.getTriggerMarkup() }); }, getTriggerMarkup: function() { var me = this, i = 0, hideTrigger = (me.readOnly || me.hideTrigger), triggerCls, triggerBaseCls = me.triggerBaseCls, triggerConfigs = [], unselectableCls = Ext.dom.Element.unselectableCls, style = 'width:' + me.triggerWidth + 'px;' + (hideTrigger ? 'display:none;' : ''), cls = me.extraTriggerCls + ' ' + Ext.baseCSSPrefix + 'trigger-cell ' + unselectableCls; if (!me.trigger1Cls) { me.trigger1Cls = me.triggerCls; } for (i = 0; (triggerCls = me['trigger' + (i + 1) + 'Cls']) || i < 1; i++) { triggerConfigs.push({ tag: 'td', role: 'presentation', valign: 'top', cls: cls, style: style, cn: { cls: [Ext.baseCSSPrefix + 'trigger-index-' + i, triggerBaseCls, triggerCls].join(' '), role: 'presentation' } }); } triggerConfigs[0].cn.cls += ' ' + triggerBaseCls + '-first'; return Ext.DomHelper.markup(triggerConfigs); }, disableCheck: function() { return !this.disabled; }, beforeRender: function() { var me = this, triggerBaseCls = me.triggerBaseCls, tempEl; if (!me.triggerWidth) { tempEl = Ext.getBody().createChild({ role: 'presentation', style: 'position: absolute;', cls: Ext.baseCSSPrefix + 'form-trigger' }); Ext.form.field.Trigger.prototype.triggerWidth = tempEl.getWidth(); tempEl.remove(); } me.callParent(); if (triggerBaseCls != Ext.baseCSSPrefix + 'form-trigger') { me.addChildEls({ name: 'triggerEl', select: '.' + triggerBaseCls }); } me.lastTriggerStateFlags = me.getTriggerStateFlags(); }, onRender: function() { var me = this; me.callParent(arguments); me.doc = Ext.getDoc(); me.initTrigger(); }, getTriggerWidth: function() { var me = this, totalTriggerWidth = 0; if (me.triggerWrap && !me.hideTrigger && !me.readOnly) { totalTriggerWidth = me.triggerEl.getCount() * me.triggerWidth; } return totalTriggerWidth; }, setHideTrigger: function(hideTrigger) { if (hideTrigger != this.hideTrigger) { this.hideTrigger = hideTrigger; this.updateLayout(); } }, setEditable: function(editable) { if (editable != this.editable) { this.editable = editable; this.updateLayout(); } }, setReadOnly: function(readOnly) { var me = this, old = me.readOnly; me.callParent(arguments); if (readOnly != old) { me.updateLayout(); } }, initTrigger: function() { var me = this, triggerWrap = me.triggerWrap, triggerEl = me.triggerEl, disableCheck = me.disableCheck, els, len, el, i, idx, cls; if (me.repeatTriggerClick) { me.triggerRepeater = new Ext.util.ClickRepeater(triggerWrap, { preventDefault: true, handler: me.onTriggerWrapClick, listeners: { mouseup: me.onTriggerWrapMouseup, scope: me }, scope: me }); } else { me.mon(triggerWrap, { click: me.onTriggerWrapClick, mouseup: me.onTriggerWrapMouseup, scope: me }); } triggerEl.setVisibilityMode(Ext.Element.DISPLAY); triggerEl.addClsOnOver(me.triggerBaseCls + '-over', disableCheck, me); els = triggerEl.elements; len = els.length; for (i = 0; i < len; i++) { el = els[i]; idx = i + 1; cls = me['trigger' + (idx) + 'Cls']; if (cls) { el.addClsOnOver(cls + '-over', disableCheck, me); el.addClsOnClick(cls + '-click', disableCheck, me); } } triggerEl.addClsOnClick(me.triggerBaseCls + '-click', disableCheck, me); }, onDestroy: function() { var me = this; Ext.destroyMembers(me, 'triggerRepeater', 'triggerWrap', 'triggerEl'); delete me.doc; me.callParent(); }, onFocus: function() { var me = this; me.callParent(arguments); if (!me.mimicing) { me.bodyEl.addCls(me.wrapFocusCls); me.mimicing = true; me.mon(me.doc, 'mousedown', me.mimicBlur, me, { delay: 10 }); if (me.monitorTab) { me.on('specialkey', me.checkTab, me); } } }, checkTab: function(me, e) { if (!this.ignoreMonitorTab && e.getKey() == e.TAB) { this.triggerBlur(); } }, getTriggerStateFlags: function () { var me = this, state = 0; if (me.readOnly) { state += 1; } if (me.editable) { state += 2; } if (me.hideTrigger) { state += 4; } return state; }, onBlur: function() { var me = this, blurTask = me.blurTask; if (me.blurring) { me.triggerBlur(); } }, mimicBlur: function(e) { if (!this.isDestroyed && !this.bodyEl.contains(e.target) && this.validateBlur(e)) { this.triggerBlur(e); } }, triggerBlur: function(e) { var me = this; me.mimicing = false; me.mun(me.doc, 'mousedown', me.mimicBlur, me); if (me.monitorTab && me.inputEl) { me.un('specialkey', me.checkTab, me); } Ext.form.field.Trigger.superclass.onBlur.call(me, e); if (me.bodyEl) { me.bodyEl.removeCls(me.wrapFocusCls); } }, validateBlur: function(e) { return true; }, onTriggerWrapClick: function() { var me = this, targetEl, match, triggerClickMethod, event; event = arguments[me.triggerRepeater ? 1 : 0]; if (event && !me.readOnly && !me.disabled) { targetEl = event.getTarget('.' + me.triggerBaseCls, null); match = targetEl && targetEl.className.match(me.triggerIndexRe); if (match) { triggerClickMethod = me['onTrigger' + (parseInt(match[1], 10) + 1) + 'Click'] || me.onTriggerClick; if (triggerClickMethod) { triggerClickMethod.call(me, event); } } } }, onTriggerWrapMouseup: Ext.emptyFn, onTriggerClick: Ext.emptyFn }); Ext.define('Ext.form.field.Picker', { extend: Ext.form.field.Trigger , alias: 'widget.pickerfield', alternateClassName: 'Ext.form.Picker', matchFieldWidth: true, pickerAlign: 'tl-bl?', openCls: Ext.baseCSSPrefix + 'pickerfield-open', editable: true, initComponent: function() { this.callParent(); this.addEvents( 'expand', 'collapse', 'select' ); }, initEvents: function() { var me = this; me.callParent(); me.keyNav = new Ext.util.KeyNav(me.inputEl, { down: me.onDownArrow, esc: { handler: me.onEsc, scope: me, defaultEventAction: false }, scope: me, forceKeyDown: true }); if (!me.editable) { me.mon(me.inputEl, 'click', me.onTriggerClick, me); } if (Ext.isGecko) { me.inputEl.dom.setAttribute('autocomplete', 'off'); } }, onEsc: function(e) { if (Ext.isIE) { e.preventDefault(); } if (this.isExpanded) { this.collapse(); e.stopEvent(); } }, onDownArrow: function(e) { if (!this.isExpanded) { this.onTriggerClick(); } }, expand: function() { var me = this, bodyEl, picker, collapseIf; if (me.rendered && !me.isExpanded && !me.isDestroyed) { me.expanding = true; bodyEl = me.bodyEl; picker = me.getPicker(); collapseIf = me.collapseIf; picker.show(); me.isExpanded = true; me.alignPicker(); bodyEl.addCls(me.openCls); me.mon(Ext.getDoc(), { mousewheel: collapseIf, mousedown: collapseIf, scope: me }); Ext.EventManager.onWindowResize(me.alignPicker, me); me.fireEvent('expand', me); me.onExpand(); delete me.expanding; } }, onExpand: Ext.emptyFn, alignPicker: function() { var me = this, picker = me.getPicker(); if (me.isExpanded) { if (me.matchFieldWidth) { picker.setWidth(me.bodyEl.getWidth()); } if (picker.isFloating()) { me.doAlign(); } } }, doAlign: function(){ var me = this, picker = me.picker, aboveSfx = '-above', isAbove; me.picker.alignTo(me.triggerWrap, me.pickerAlign, me.pickerOffset); isAbove = picker.el.getY() < me.inputEl.getY(); me.bodyEl[isAbove ? 'addCls' : 'removeCls'](me.openCls + aboveSfx); picker[isAbove ? 'addCls' : 'removeCls'](picker.baseCls + aboveSfx); }, collapse: function() { if (this.isExpanded && !this.isDestroyed) { var me = this, openCls = me.openCls, picker = me.picker, doc = Ext.getDoc(), collapseIf = me.collapseIf, aboveSfx = '-above'; picker.hide(); me.isExpanded = false; me.bodyEl.removeCls([openCls, openCls + aboveSfx]); picker.el.removeCls(picker.baseCls + aboveSfx); doc.un('mousewheel', collapseIf, me); doc.un('mousedown', collapseIf, me); Ext.EventManager.removeResizeListener(me.alignPicker, me); me.fireEvent('collapse', me); me.onCollapse(); } }, onCollapse: Ext.emptyFn, collapseIf: function(e) { var me = this; if (!me.isDestroyed && !e.within(me.bodyEl, false, true) && !e.within(me.picker.el, false, true) && !me.isEventWithinPickerLoadMask(e)) { me.collapse(); } }, getPicker: function() { var me = this; return me.picker || (me.picker = me.createPicker()); }, createPicker: Ext.emptyFn, onTriggerClick: function() { var me = this; if (!me.readOnly && !me.disabled) { if (me.isExpanded) { me.collapse(); } else { me.expand(); } me.inputEl.focus(); } }, triggerBlur: function() { var picker = this.picker; this.callParent(arguments); if (picker && picker.isVisible()) { picker.hide(); } }, mimicBlur: function(e) { var me = this, picker = me.picker; if (!picker || !e.within(picker.el, false, true) && !me.isEventWithinPickerLoadMask(e)) { me.callParent(arguments); } }, onDestroy : function(){ var me = this, picker = me.picker; Ext.EventManager.removeResizeListener(me.alignPicker, me); Ext.destroy(me.keyNav); if (picker) { delete picker.pickerField; picker.destroy(); } me.callParent(); }, isEventWithinPickerLoadMask: function(e) { var loadMask = this.picker.loadMask; return loadMask ? e.within(loadMask.maskEl, false, true) || e.within(loadMask.el, false, true) : false; } }); Ext.define('Ext.selection.Model', { extend: Ext.util.Observable , alternateClassName: 'Ext.AbstractSelectionModel', mixins: { bindable: Ext.util.Bindable }, allowDeselect: undefined, toggleOnClick: true, selected: null, pruneRemoved: true, suspendChange: 0, constructor: function(cfg) { var me = this; cfg = cfg || {}; Ext.apply(me, cfg); me.addEvents( 'selectionchange', 'focuschange' ); me.modes = { SINGLE: true, SIMPLE: true, MULTI: true }; me.setSelectionMode(cfg.mode || me.mode); me.selected = new Ext.util.MixedCollection(null, me.getSelectionId); me.callParent(arguments); }, bindStore: function(store, initial){ var me = this; me.mixins.bindable.bindStore.apply(me, arguments); if(me.store && !initial) { me.refresh(); } }, getStoreListeners: function() { var me = this; return { add: me.onStoreAdd, clear: me.onStoreClear, bulkremove: me.onStoreRemove, update: me.onStoreUpdate, load: me.onStoreLoad, idchanged: me.onModelIdChanged, refresh: me.onStoreRefresh }; }, suspendChanges: function(){ ++this.suspendChange; }, resumeChanges: function(){ if (this.suspendChange) { --this.suspendChange; } }, selectAll: function(suppressEvent) { var me = this, selections = me.store.getRange(), i = 0, len = selections.length, start = me.getSelection().length; me.suspendChanges(); for (; i < len; i++) { me.doSelect(selections[i], true, suppressEvent); } me.resumeChanges(); if (!suppressEvent) { me.maybeFireSelectionChange(me.getSelection().length !== start); } }, deselectAll: function(suppressEvent) { var me = this, selections = me.getSelection(), selIndexes = {}, store = me.store, start = selections.length, i, l, rec; for (i = 0, l = selections.length; i < l; i++) { rec = selections[i]; selIndexes[rec.internalId] = store.indexOf(rec); } selections = Ext.Array.sort(selections, function(r1, r2){ var idx1 = selIndexes[r1.internalId], idx2 = selIndexes[r2.internalId]; return idx1 < idx2 ? -1 : 1; }); me.suspendChanges(); me.doDeselect(selections, suppressEvent); me.resumeChanges(); if (!suppressEvent) { me.maybeFireSelectionChange(me.getSelection().length !== start); } }, selectWithEvent: function(record, e) { var me = this, isSelected = me.isSelected(record), shift = e.shiftKey, ctrl = e.ctrlKey, start = me.selectionStart, selected = me.getSelection(), len = selected.length, allowDeselect = me.allowDeselect, toDeselect, i, item; switch (me.selectionMode) { case 'MULTI': if (shift && start) { me.selectRange(start, record, ctrl); } else if (ctrl && isSelected) { me.doDeselect(record, false); } else if (ctrl) { me.doSelect(record, true, false); } else if (isSelected && !shift && !ctrl && len > 1) { toDeselect = []; for (i = 0; i < len; ++i) { item = selected[i]; if (item !== record) { toDeselect.push(item); } } me.doDeselect(toDeselect); } else if (!isSelected) { me.doSelect(record, false); } break; case 'SIMPLE': if (isSelected) { me.doDeselect(record); } else { me.doSelect(record, true); } break; case 'SINGLE': if (allowDeselect && !ctrl) { allowDeselect = me.toggleOnClick; } if (allowDeselect && isSelected) { me.doDeselect(record); } else { me.doSelect(record, false); } break; } if (!shift) { if (me.isSelected(record)) { me.selectionStart = record; } else { me.selectionStart = null; } } }, afterKeyNavigate: function(e, record) { var me = this, recIdx, fromIdx, isSelected = me.isSelected(record), from = (me.selectionStart && me.isSelected(me.lastFocused)) ? me.selectionStart : (me.selectionStart = me.lastFocused), key = e.getCharCode(), isSpace = key === e.SPACE, direction = key === e.UP || key === e.PAGE_UP ? 'up' : (key === e.DOWN || key === e.DOWN ? 'down' : null); switch (me.selectionMode) { case 'MULTI': if (isSpace) { if (e.shiftKey) { me.selectRange(from, record, e.ctrlKey); } else { if (isSelected) { me.doDeselect(record, e.ctrlKey); me.setLastFocused(null); me.setLastFocused(record); } else { me.doSelect(record, e.ctrlKey); } } } else if (e.shiftKey && from) { fromIdx = me.store.indexOf(from); recIdx = me.store.indexOf(record); if (direction === 'up' && fromIdx <= recIdx) { me.deselectRange(me.lastFocused, recIdx + 1); } else if (direction === 'down' && fromIdx >= recIdx) { me.deselectRange(me.lastFocused, recIdx - 1); } else if (from !== record) { me.selectRange(from, record, e.ctrlKey); } me.lastSelected = record; me.setLastFocused(record); } else if (e.ctrlKey && isSelected) { me.setLastFocused(record); } else if (e.ctrlKey) { me.setLastFocused(record); } else { me.doSelect(record, false); } break; case 'SIMPLE': if (isSelected) { me.doDeselect(record); } else { me.doSelect(record, true); } break; case 'SINGLE': if (isSpace) { if (isSelected) { me.doDeselect(record); me.setLastFocused(record); } else { me.doSelect(record); } } else if (e.ctrlKey) { me.setLastFocused(record); } else if (me.allowDeselect && isSelected) { me.doDeselect(record); } else { me.doSelect(record, false); } break; } if (!e.shiftKey) { if (me.isSelected(record)) { me.selectionStart = record; } } }, selectRange : function(startRow, endRow, keepExisting) { var me = this, store = me.store, selected = me.selected.items, result, i, len, toSelect, toDeselect, idx, rec; if (me.isLocked()){ return; } result = me.normalizeRowRange(startRow, endRow); startRow = result[0]; endRow = result[1]; toSelect = []; for (i = startRow; i <= endRow; i++){ if (!me.isSelected(store.getAt(i))) { toSelect.push(store.getAt(i)); } } if (!keepExisting) { toDeselect = []; me.suspendChanges(); for (i = 0, len = selected.length; i < len; ++i) { rec = selected[i]; idx = store.indexOf(rec); if (idx < startRow || idx > endRow) { toDeselect.push(rec) } } for (i = 0, len = toDeselect.length; i < len; ++i) { me.doDeselect(toDeselect[i]); } me.resumeChanges(); } me.doMultiSelect(toSelect, true); }, deselectRange : function(startRow, endRow) { var me = this, store = me.store, result, i, toDeselect, record; if (me.isLocked()){ return; } result = me.normalizeRowRange(startRow, endRow); startRow = result[0]; endRow = result[1]; toDeselect = []; for (i = startRow; i <= endRow; i++) { record = store.getAt(i); if (me.isSelected(record)) { toDeselect.push(record); } } me.doDeselect(toDeselect); }, normalizeRowRange: function(startRow, endRow) { var store = this.store, tmp; if (!Ext.isNumber(startRow)) { startRow = store.indexOf(startRow); } startRow = Math.max(0, startRow); if (!Ext.isNumber(endRow)) { endRow = store.indexOf(endRow); } endRow = Math.min(endRow, store.getCount() - 1); if (startRow > endRow){ tmp = endRow; endRow = startRow; startRow = tmp; } return [startRow, endRow]; }, onModelIdChanged: function(store, model, oldId, newId, oldInternalId) { this.selected.updateKey(oldInternalId, newId); }, select: function(records, keepExisting, suppressEvent) { if (Ext.isDefined(records)) { this.doSelect(records, keepExisting, suppressEvent); } }, deselect: function(records, suppressEvent) { this.doDeselect(records, suppressEvent); }, doSelect: function(records, keepExisting, suppressEvent) { var me = this, record; if (me.locked || !me.store) { return; } if (typeof records === "number") { record = me.store.getAt(records); if (!record) { return; } records = [record]; } if (me.selectionMode == "SINGLE" && records) { record = records.length ? records[0] : records; me.doSingleSelect(record, suppressEvent); } else { me.doMultiSelect(records, keepExisting, suppressEvent); } }, doMultiSelect: function(records, keepExisting, suppressEvent) { var me = this, selected = me.selected, change = false, result, i, len, record, commit; if (me.locked) { return; } records = !Ext.isArray(records) ? [records] : records; len = records.length; if (!keepExisting && selected.getCount() > 0) { result = me.deselectDuringSelect(records, selected.getRange(), suppressEvent); if (result[0]) { me.maybeFireSelectionChange(result[1] > 0 && !suppressEvent); return; } } commit = function() { selected.add(record); change = true; }; for (i = 0; i < len; i++) { record = records[i]; if (me.isSelected(record)) { continue; } me.lastSelected = record; me.onSelectChange(record, true, suppressEvent, commit); } if (!me.preventFocus) { me.setLastFocused(record, suppressEvent); } me.maybeFireSelectionChange(change && !suppressEvent); }, deselectDuringSelect: function(toSelect, selected, suppressEvent) { var me = this, len = selected.length, changed = 0, failed = false, item, i; me.suspendChanges(); for (i = 0; i < len; ++i) { item = selected[i]; if (!Ext.Array.contains(toSelect, item)) { if (me.doDeselect(item, suppressEvent)) { ++changed; } else { failed = true; } } } me.resumeChanges(); return [failed, changed]; }, doDeselect: function(records, suppressEvent) { var me = this, selected = me.selected, i = 0, len, record, attempted = 0, accepted = 0, commit; if (me.locked || !me.store) { return false; } if (typeof records === "number") { record = me.store.getAt(records); if (!record) { return false; } records = [record]; } else if (!Ext.isArray(records)) { records = [records]; } commit = function() { ++accepted; selected.remove(record); }; len = records.length; me.suspendChanges(); for (; i < len; i++) { record = records[i]; if (me.isSelected(record)) { if (me.lastSelected === record) { me.lastSelected = selected.last(); if (me.lastFocused === record) { me.setLastFocused(null); } } ++attempted; me.onSelectChange(record, false, suppressEvent, commit); } } me.resumeChanges(); me.maybeFireSelectionChange(accepted > 0 && !suppressEvent); return accepted === attempted; }, doSingleSelect: function(record, suppressEvent) { var me = this, changed = false, selected = me.selected, commit; if (me.locked) { return; } if (me.isSelected(record)) { return; } if (selected.getCount()) { me.suspendChanges(); if (!me.doDeselect(me.lastSelected, suppressEvent)) { me.resumeChanges(); return; } me.resumeChanges(); } commit = function() { selected.add(record); me.lastSelected = record; changed = true; }; me.onSelectChange(record, true, suppressEvent, commit); if (changed) { if (!suppressEvent && !me.preventFocus) { me.setLastFocused(record); } me.maybeFireSelectionChange(!suppressEvent); } }, setLastFocused: function(record, supressFocus) { var me = this, recordBeforeLast = me.lastFocused; if (record !== recordBeforeLast) { me.lastFocused = record; me.onLastFocusChanged(recordBeforeLast, record, supressFocus); } }, isFocused: function(record) { return record === this.getLastFocused(); }, maybeFireSelectionChange: function(fireEvent) { var me = this; if (fireEvent && !me.suspendChange) { me.fireEvent('selectionchange', me, me.getSelection()); } }, getLastSelected: function() { return this.lastSelected; }, getLastFocused: function() { return this.lastFocused; }, getSelection: function() { return this.selected.getRange(); }, getSelectionMode: function() { return this.selectionMode; }, setSelectionMode: function(selMode) { selMode = selMode ? selMode.toUpperCase() : 'SINGLE'; this.selectionMode = this.modes[selMode] ? selMode : 'SINGLE'; }, isLocked: function() { return this.locked; }, setLocked: function(locked) { this.locked = !!locked; }, isRangeSelected: function(startRow, endRow) { var me = this, store = me.store, i, result; result = me.normalizeRowRange(startRow, endRow); startRow = result[0]; endRow = result[1]; for (i = startRow; i <= endRow; i++) { if (!me.isSelected(store.getAt(i))) { return false; } } return true; }, isSelected: function(record) { record = Ext.isNumber(record) ? this.store.getAt(record) : record; return this.selected.contains(record); }, hasSelection: function() { return this.selected.getCount() > 0; }, getSelectionId: function(record){ return record.internalId; }, pruneIf: function() { var me = this, selected = me.selected, toRemove = [], len = selected.length, i, item; if (me.pruneRemoved) { for (i = 0; i < len; i++) { item = selected.getAt(i); if (!this.storeHasSelected(item)) { toRemove.push(item); } } if (toRemove.length) { for (i = 0, len = toRemove.length; i < len; i++) { selected.remove(toRemove[i]); } me.maybeFireSelectionChange(true); } } }, storeHasSelected: function(record) { var store = this.store, records, len, id, i; if (record.hasId() && store.getById(record.getId())) { return true; } else { records = store.data.items; len = records.length; id = record.internalId; for (i = 0; i < len; ++i) { if (id === records[i].internalId) { return true; } } } return false; }, refresh: function() { var me = this, store = me.store, rec, toBeSelected = [], toBeReAdded = [], oldSelections = me.getSelection(), len = oldSelections.length, selection, change, i = 0, lastFocused = me.getLastFocused(); if (!store) { return; } for (; i < len; i++) { selection = oldSelections[i]; if (store.indexOf(selection) !== -1) { toBeSelected.push(selection); } else if (!me.pruneRemoved) { rec = store.getById(selection.getId()); if (rec) { toBeSelected.push(rec); } else { toBeReAdded.push(selection) } } if (me.mode === 'SINGLE' && toBeReAdded.length) { break; } } if (me.selected.getCount() != (toBeSelected.length + toBeReAdded.length)) { change = true; } me.clearSelections(); if (store.indexOf(lastFocused) !== -1) { me.setLastFocused(lastFocused, true); } if (toBeSelected.length) { me.doSelect(toBeSelected, false, true); } if (toBeReAdded.length) { me.selected.addAll(toBeReAdded); if (!me.lastSelected) { me.lastSelected = toBeReAdded[toBeReAdded.length - 1]; } } me.maybeFireSelectionChange(change); }, clearSelections: function() { this.selected.clear(); this.lastSelected = null; this.setLastFocused(null); }, onStoreAdd: Ext.emptyFn, onStoreClear: function() { if (this.selected.getCount() > 0) { this.clearSelections(); this.maybeFireSelectionChange(true); } }, onStoreRemove: function(store, records, indexes, isMove) { var me = this; if (me.selectionStart && Ext.Array.contains(records, me.selectionStart)) { me.selectionStart = null; } if (isMove || me.locked || !me.pruneRemoved) { return; } me.deselectDeletedRecords(records); }, deselectDeletedRecords: function(records) { var me = this, selected = me.selected, i, length = records.length, removed = 0, record; for (i = 0; i < length; i++) { record = records[i]; if (selected.remove(record)) { if (me.lastSelected == record) { me.lastSelected = null; } if (me.getLastFocused() == record) { me.setLastFocused(null); } ++removed; } } if (removed) { me.maybeFireSelectionChange(true); } }, getCount: function() { return this.selected.getCount(); }, onUpdate: Ext.emptyFn, destroy: function(){ this.clearListeners(); }, onStoreUpdate: Ext.emptyFn, onStoreRefresh: Ext.emptyFn, onStoreLoad: Ext.emptyFn, onSelectChange: function(record, isSelected, suppressEvent, commitFn) { var me = this, eventName = isSelected ? 'select' : 'deselect'; if ((suppressEvent || me.fireEvent('before' + eventName, me, record)) !== false && commitFn() !== false) { if (!suppressEvent) { me.fireEvent(eventName, me, record); } } }, onLastFocusChanged: function(oldFocused, newFocused) { this.fireEvent('focuschange', this, oldFocused, newFocused); }, onEditorKey: Ext.emptyFn, beforeViewRender: function(view) { this.views = this.views || []; this.views.push(view); this.bindStore(view.getStore(), true); }, bindComponent: Ext.emptyFn }); Ext.define('Ext.selection.DataViewModel', { extend: Ext.selection.Model , deselectOnContainerClick: true, enableKeyNav: true, constructor: function(cfg){ this.addEvents( 'beforedeselect', 'beforeselect', 'deselect', 'select' ); this.callParent(arguments); }, bindComponent: function(view) { var me = this, eventListeners = { refresh: me.refresh, scope: me }; me.view = view; me.bindStore(view.getStore()); eventListeners[view.triggerEvent] = me.onItemClick; eventListeners[view.triggerCtEvent] = me.onContainerClick; view.on(eventListeners); if (me.enableKeyNav) { me.initKeyNav(view); } }, onUpdate: function(record){ var view = this.view; if (view && this.isSelected(record)) { view.onItemSelect(record); } }, onItemClick: function(view, record, item, index, e) { this.selectWithEvent(record, e); }, onContainerClick: function() { if (this.deselectOnContainerClick) { this.deselectAll(); } }, initKeyNav: function(view) { var me = this; if (!view.rendered) { view.on({ render: Ext.Function.bind(me.initKeyNav, me, [view]), single: true }); return; } view.el.set({ tabIndex: -1 }); me.keyNav = new Ext.util.KeyNav({ target: view.el, ignoreInputFields: true, down: Ext.pass(me.onNavKey, [1], me), right: Ext.pass(me.onNavKey, [1], me), left: Ext.pass(me.onNavKey, [-1], me), up: Ext.pass(me.onNavKey, [-1], me), scope: me }); }, onNavKey: function(step) { step = step || 1; var me = this, view = me.view, selected = me.getSelection()[0], numRecords = me.view.store.getCount(), idx; if (selected) { idx = view.indexOf(view.getNode(selected)) + step; } else { idx = 0; } if (idx < 0) { idx = numRecords - 1; } else if (idx >= numRecords) { idx = 0; } me.select(idx); }, onSelectChange: function(record, isSelected, suppressEvent, commitFn) { var me = this, view = me.view, eventName = isSelected ? 'select' : 'deselect'; if ((suppressEvent || me.fireEvent('before' + eventName, me, record)) !== false && commitFn() !== false) { if (view) { if (isSelected) { view.onItemSelect(record); } else { view.onItemDeselect(record); } } if (!suppressEvent) { me.fireEvent(eventName, me, record); } } }, onLastFocusChanged: function(oldFocus, newFocus, suppressFocus){ var view = this.view; if (view && !suppressFocus && newFocus) { view.focusNode(newFocus); this.fireEvent('focuschange', this, oldFocus, newFocus); } }, destroy: function(){ Ext.destroy(this.keyNav); this.callParent(); } }); Ext.define('Ext.view.AbstractView', { extend: Ext.Component , mixins: { bindable: Ext.util.Bindable }, inheritableStatics: { getRecord: function(node) { return this.getBoundView(node).getRecord(node); }, getBoundView: function(node) { return Ext.getCmp(node.boundView); } }, deferInitialRefresh: true, itemCls: Ext.baseCSSPrefix + 'dataview-item', loadingText: 'Loading...', loadMask: true, loadingUseMsg: true, selectedItemCls: Ext.baseCSSPrefix + 'item-selected', emptyText: "", deferEmptyText: true, trackOver: false, blockRefresh: false, preserveScrollOnRefresh: false, ariaRole: 'listbox', itemAriaRole: 'option', last: false, triggerEvent: 'itemclick', triggerCtEvent: 'containerclick', addCmpEvents: function() { }, initComponent : function(){ var me = this, isDef = Ext.isDefined, itemTpl = me.itemTpl, memberFn = {}; if (itemTpl) { if (Ext.isArray(itemTpl)) { itemTpl = itemTpl.join(''); } else if (Ext.isObject(itemTpl)) { memberFn = Ext.apply(memberFn, itemTpl.initialConfig); itemTpl = itemTpl.html; } if (!me.itemSelector) { me.itemSelector = '.' + me.itemCls; } itemTpl = Ext.String.format('
{1}
', me.itemCls, itemTpl, me.itemAriaRole); me.tpl = new Ext.XTemplate(itemTpl, memberFn); } me.callParent(); me.tpl = me.getTpl('tpl'); if (me.overItemCls) { me.trackOver = true; } me.addEvents( 'beforerefresh', 'refresh', 'viewready', 'itemupdate', 'itemadd', 'itemremove' ); me.addCmpEvents(); me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store'); if (!me.dataSource) { me.dataSource = me.store; } me.bindStore(me.dataSource, true, 'dataSource'); if (!me.all) { me.all = new Ext.CompositeElementLite(); } me.scrollState = { top: 0, left: 0 }; me.on({ scroll: me.onViewScroll, element: 'el', scope: me }); }, onRender: function() { var me = this, mask = me.loadMask, maskStore = me.getMaskStore(), cfg = { target: me, msg: me.loadingText, msgCls: me.loadingCls, useMsg: me.loadingUseMsg, store: maskStore }; me.callParent(arguments); if (mask && !maskStore.proxy.isSynchronous) { if (Ext.isObject(mask)) { cfg = Ext.apply(cfg, mask); } me.loadMask = new Ext.LoadMask(cfg); me.loadMask.on({ scope: me, beforeshow: me.onMaskBeforeShow, hide: me.onMaskHide }); } }, finishRender: function() { var me = this; me.callParent(arguments); if (!me.up('[collapsed],[hidden]')) { me.doFirstRefresh(me.dataSource); } }, onBoxReady: function() { var me = this; me.callParent(arguments); if (!me.firstRefreshDone) { me.doFirstRefresh(me.dataSource); } }, getMaskStore: function(){ return this.store; }, onMaskBeforeShow: function(){ var me = this, loadingHeight = me.loadingHeight; if (loadingHeight && loadingHeight > me.getHeight()) { me.hasLoadingHeight = true; me.oldMinHeight = me.minHeight; me.minHeight = loadingHeight; me.updateLayout(); } }, onMaskHide: function(){ var me = this; if (!me.destroying && me.hasLoadingHeight) { me.minHeight = me.oldMinHeight; me.updateLayout(); delete me.hasLoadingHeight; } }, beforeRender: function() { this.callParent(arguments); this.getSelectionModel().beforeViewRender(this); }, afterRender: function() { this.callParent(arguments); this.getSelectionModel().bindComponent(this); }, getSelectionModel: function(){ var me = this, mode = 'SINGLE'; if (me.simpleSelect) { mode = 'SIMPLE'; } else if (me.multiSelect) { mode = 'MULTI'; } if (!me.selModel || !me.selModel.events) { me.selModel = new Ext.selection.DataViewModel(Ext.apply({ allowDeselect: me.allowDeselect, mode: mode }, me.selModel)); } if (!me.selModel.hasRelaySetup) { me.relayEvents(me.selModel, [ 'selectionchange', 'beforeselect', 'beforedeselect', 'select', 'deselect', 'focuschange' ]); me.selModel.hasRelaySetup = true; } if (me.disableSelection) { me.selModel.locked = true; } return me.selModel; }, refresh: function() { var me = this, targetEl, targetParent, oldDisplay, nextSibling, dom, records; if (!me.rendered || me.isDestroyed) { return; } if (!me.hasListeners.beforerefresh || me.fireEvent('beforerefresh', me) !== false) { targetEl = me.getTargetEl(); records = me.getViewRange(); dom = targetEl.dom; if (!me.preserveScrollOnRefresh) { targetParent = dom.parentNode; oldDisplay = dom.style.display; dom.style.display = 'none'; nextSibling = dom.nextSibling; targetParent.removeChild(dom); } if (me.refreshCounter) { me.clearViewEl(); } else { me.fixedNodes = targetEl.dom.childNodes.length; me.refreshCounter = 1; } me.tpl.append(targetEl, me.collectData(records, me.all.startIndex)); if (records.length < 1) { if (!this.store.loading && (!me.deferEmptyText || me.hasFirstRefresh)) { Ext.core.DomHelper.insertHtml('beforeEnd', targetEl.dom, me.emptyText); } me.all.clear(); } else { me.collectNodes(targetEl.dom); me.updateIndexes(0); } if (me.hasFirstRefresh) { if (me.refreshSelmodelOnRefresh !== false) { me.selModel.refresh(); } else { me.selModel.pruneIf(); } } me.hasFirstRefresh = true; if (!me.preserveScrollOnRefresh) { targetParent.insertBefore(dom, nextSibling); dom.style.display = oldDisplay; } this.refreshSize(); me.fireEvent('refresh', me); if (!me.viewReady) { me.viewReady = true; me.fireEvent('viewready', me); } } }, collectNodes: function(targetEl) { this.all.fill(Ext.query(this.getItemSelector(), Ext.getDom(targetEl)), this.all.startIndex); }, getViewRange: function() { return this.dataSource.getRange(); }, refreshSize: function() { var sizeModel = this.getSizeModel(); if (sizeModel.height.shrinkWrap || sizeModel.width.shrinkWrap) { this.updateLayout(); } }, clearViewEl: function(){ var me = this, el = me.getTargetEl(); if (me.fixedNodes) { while (el.dom.childNodes[me.fixedNodes]) { el.dom.removeChild(el.dom.childNodes[me.fixedNodes]); } } else { el.update(''); } me.refreshCounter++; }, onViewScroll: Ext.emptyFn, onIdChanged: Ext.emptyFn, saveScrollState: function() { if (this.rendered) { var dom = this.el.dom, state = this.scrollState; state.left = dom.scrollLeft; state.top = dom.scrollTop; } }, restoreScrollState: function() { if (this.rendered) { var dom = this.el.dom, state = this.scrollState; dom.scrollLeft = state.left; dom.scrollTop = state.top; } }, prepareData: function(data, index, record) { var associatedData, attr, hasCopied; if (record) { associatedData = record.getAssociatedData(); for (attr in associatedData) { if (associatedData.hasOwnProperty(attr)) { if (!hasCopied) { data = Ext.Object.chain(data); hasCopied = true; } data[attr] = associatedData[attr]; } } } return data; }, collectData: function(records, startIndex){ var data = [], i = 0, len = records.length, record; for (; i < len; i++) { record = records[i]; data[i] = this.prepareData(record.data, startIndex + i, record); } return data; }, bufferRender : function(records, index) { var me = this, div = me.renderBuffer || (me.renderBuffer = document.createElement('div')); me.tpl.overwrite(div, me.collectData(records, index)); return Ext.DomQuery.select(me.getItemSelector(), div); }, getNodeContainer: function() { return this.getTargetEl(); }, onUpdate : function(ds, record){ var me = this, index, node; if (me.viewReady) { index = me.dataSource.indexOf(record); if (index > -1) { node = me.bufferRender([record], index)[0]; if (me.getNode(record)) { me.all.replaceElement(index, node, true); me.updateIndexes(index, index); me.selModel.onUpdate(record); if (me.hasListeners.itemupdate) { me.fireEvent('itemupdate', record, index, node); } return node; } } } }, onAdd : function(store, records, index) { var me = this, nodes; if (me.rendered) { if (me.all.getCount() === 0) { me.refresh(); nodes = me.all.slice(); } else { nodes = me.doAdd(records, index); if (me.refreshSelmodelOnRefresh !== false) { me.selModel.refresh(); } me.updateIndexes(index); me.refreshSize(); } if (me.hasListeners.itemadd) { me.fireEvent('itemadd', records, index, nodes); } } }, doAdd: function(records, index) { var me = this, nodes = me.bufferRender(records, index, true), all = me.all, count = all.getCount(), i, l, nodeContainer, fragment; if (count === 0) { nodeContainer = this.getNodeContainer(); fragment = document.createDocumentFragment(); for (i = 0, l = nodes.length; i < l; i++) { fragment.appendChild(nodes[i]); } nodeContainer.appendChild(fragment); } else if (index < count) { if (index === 0) { all.item(index).insertSibling(nodes, 'before', true); } else { all.item(index - 1).insertSibling(nodes, 'after', true); } } else { all.last().insertSibling(nodes, 'after', true); } all.insert(index, nodes); return nodes; }, onRemove : function(ds, records, indexes) { var me = this, fireItemRemove = me.hasListeners.itemremove, i, record, index; if (me.all.getCount()) { if (me.dataSource.getCount() === 0) { if (fireItemRemove) { for (i = indexes.length - 1; i >= 0; --i) { me.fireEvent('itemremove', records[i], indexes[i]); } } me.refresh(); } else { for (i = indexes.length - 1; i >= 0; --i) { record = records[i]; index = indexes[i]; me.doRemove(record, index); if (fireItemRemove) { me.fireEvent('itemremove', record, index); } } me.updateIndexes(indexes[0]); } this.refreshSize(); } }, doRemove: function(record, index) { this.all.removeElement(index, true); }, refreshNode : function(index) { this.onUpdate(this.dataSource, this.dataSource.getAt(index)); }, updateIndexes : function(startIndex, endIndex) { var nodes = this.all.elements, records = this.getViewRange(), i; startIndex = startIndex || 0; endIndex = endIndex || ((endIndex === 0) ? 0 : (nodes.length - 1)); for (i = startIndex; i <= endIndex; i++) { nodes[i].viewIndex = i; nodes[i].viewRecordId = records[i].internalId; if (!nodes[i].boundView) { nodes[i].boundView = this.id; } } }, getStore : function() { return this.store; }, bindStore : function(store, initial, propName) { var me = this; me.mixins.bindable.bindStore.apply(me, arguments); if (!initial) { me.getSelectionModel().bindStore(store); } if (me.componentLayoutCounter) { me.doFirstRefresh(store); } }, doFirstRefresh: function(store) { var me = this; me.firstRefreshDone = true; if (store && !store.loading) { if (me.deferInitialRefresh) { me.applyFirstRefresh(); } else { me.refresh(); } } }, applyFirstRefresh: function(){ var me = this; if (me.isDestroyed) { return; } if (me.up('[isCollapsingOrExpanding]')) { Ext.Function.defer(me.applyFirstRefresh, 100, me); } else { Ext.Function.defer(function () { if (!me.isDestroyed) { me.refresh(); } }, 1); } }, onUnbindStore: function(store) { this.setMaskBind(null); }, onBindStore: function(store, initial, propName) { this.setMaskBind(store); if (!initial && propName === 'store') { this.bindStore(store, false, 'dataSource'); } }, setMaskBind: function(store) { var mask = this.loadMask; if (mask && mask.bindStore) { mask.bindStore(store); } }, getStoreListeners: function() { var me = this; return { idchanged: me.onIdChanged, refresh: me.onDataRefresh, add: me.onAdd, bulkremove: me.onRemove, update: me.onUpdate, clear: me.refresh }; }, onDataRefresh: function() { this.refreshView(); }, refreshView: function() { var me = this, blockedByAncestor = !me.firstRefreshDone && (!me.rendered || me.up('[collapsed],[isCollapsingOrExpanding],[hidden]')); if (blockedByAncestor) { me.deferInitialRefresh = false; } else if (me.blockRefresh !== true) { me.firstRefreshDone = true; me.refresh(); } }, findItemByChild: function(node){ return Ext.fly(node).findParent(this.getItemSelector(), this.getTargetEl()); }, findTargetByEvent: function(e) { return e.getTarget(this.getItemSelector(), this.getTargetEl()); }, getSelectedNodes: function(){ var nodes = [], records = this.selModel.getSelection(), ln = records.length, i = 0; for (; i < ln; i++) { nodes.push(this.getNode(records[i])); } return nodes; }, getRecords: function(nodes) { var records = [], i = 0, len = nodes.length, data = this.dataSource.data; for (; i < len; i++) { records[records.length] = data.getByKey(nodes[i].viewRecordId); } return records; }, getRecord: function(node){ return this.dataSource.data.getByKey(Ext.getDom(node).viewRecordId); }, isSelected : function(node) { var r = this.getRecord(node); return this.selModel.isSelected(r); }, select: function(records, keepExisting, suppressEvent) { this.selModel.select(records, keepExisting, suppressEvent); }, deselect: function(records, suppressEvent) { this.selModel.deselect(records, suppressEvent); }, getNode : function(nodeInfo) { if ((!nodeInfo && nodeInfo !== 0) || !this.rendered) { return null; } if (Ext.isString(nodeInfo)) { return document.getElementById(nodeInfo); } if (Ext.isNumber(nodeInfo)) { return this.all.elements[nodeInfo]; } if (nodeInfo.isModel) { return this.getNodeByRecord(nodeInfo); } return nodeInfo; }, getNodeByRecord: function(record) { var ns = this.all.elements, ln = ns.length, i = 0; for (; i < ln; i++) { if (ns[i].viewRecordId === record.internalId) { return ns[i]; } } return null; }, getNodes: function(start, end) { var all = this.all; if (end === undefined) { end = all.getCount(); } else { end++; } return all.slice(start||0, end); }, indexOf: function(node) { node = this.getNode(node); if (!node && node !== 0) { return -1; } if (Ext.isNumber(node.viewIndex)) { return node.viewIndex; } return this.all.indexOf(node); }, onDestroy : function() { var me = this; me.all.clear(); me.callParent(); me.bindStore(null); me.selModel.destroy(); }, onItemSelect: function(record) { var node = this.getNode(record); if (node) { Ext.fly(node).addCls(this.selectedItemCls); } }, onItemDeselect: function(record) { var node = this.getNode(record); if (node) { Ext.fly(node).removeCls(this.selectedItemCls); } }, getItemSelector: function() { return this.itemSelector; } }, function() { Ext.deprecate('extjs', '4.0', function() { Ext.view.AbstractView.override({ getSelectionCount : function(){ if (Ext.global.console) { Ext.global.console.warn("DataView: getSelectionCount will be removed, please interact with the Ext.selection.DataViewModel"); } return this.selModel.getSelection().length; }, getSelectedRecords : function(){ if (Ext.global.console) { Ext.global.console.warn("DataView: getSelectedRecords will be removed, please interact with the Ext.selection.DataViewModel"); } return this.selModel.getSelection(); }, select: function(records, keepExisting, supressEvents) { if (Ext.global.console) { Ext.global.console.warn("DataView: select will be removed, please access select through a DataView's SelectionModel, ie: view.getSelectionModel().select()"); } var sm = this.getSelectionModel(); return sm.select.apply(sm, arguments); }, clearSelections: function() { if (Ext.global.console) { Ext.global.console.warn("DataView: clearSelections will be removed, please access deselectAll through DataView's SelectionModel, ie: view.getSelectionModel().deselectAll()"); } var sm = this.getSelectionModel(); return sm.deselectAll(); } }); }); }); Ext.define('Ext.view.View', { extend: Ext.view.AbstractView , alternateClassName: 'Ext.DataView', alias: 'widget.dataview', deferHighlight: Ext.isIE7m ? 100 : 0, mouseOverOutBuffer: 20, inputTagRe: /^textarea$|^input$/i, inheritableStatics: { EventMap: { mousedown: 'MouseDown', mouseup: 'MouseUp', click: 'Click', dblclick: 'DblClick', contextmenu: 'ContextMenu', mouseover: 'MouseOver', mouseout: 'MouseOut', mouseenter: 'MouseEnter', mouseleave: 'MouseLeave', keydown: 'KeyDown', focus: 'Focus' } }, initComponent: function() { var me = this; me.callParent(); if (me.mouseOverOutBuffer) { me.handleMouseOver = Ext.Function.createBuffered(me.handleMouseOver, me.mouseOverOutBuffer, me); me.handleMouseOut = Ext.Function.createBuffered(me.handleMouseOut, me.mouseOverOutBuffer, me); me.lastMouseOverEvent = new Ext.EventObjectImpl(); me.lastMouseOutEvent = new Ext.EventObjectImpl(); } else if (me.deferHighlight){ me.setHighlightedItem = Ext.Function.createBuffered(me.setHighlightedItem, me.deferHighlight, me); } }, addCmpEvents: function() { this.addEvents( 'beforeitemmousedown', 'beforeitemmouseup', 'beforeitemmouseenter', 'beforeitemmouseleave', 'beforeitemclick', 'beforeitemdblclick', 'beforeitemcontextmenu', 'beforeitemkeydown', 'itemmousedown', 'itemmouseup', 'itemmouseenter', 'itemmouseleave', 'itemclick', 'itemdblclick', 'itemcontextmenu', 'itemkeydown', 'beforecontainermousedown', 'beforecontainermouseup', 'beforecontainermouseover', 'beforecontainermouseout', 'beforecontainerclick', 'beforecontainerdblclick', 'beforecontainercontextmenu', 'beforecontainerkeydown', 'containermouseup', 'containermouseover', 'containermouseout', 'containerclick', 'containerdblclick', 'containercontextmenu', 'containerkeydown', 'selectionchange', 'beforeselect', 'beforedeselect', 'select', 'deselect', 'focuschange', 'highlightitem', 'unhighlightitem' ); }, getFocusEl: function() { return this.getTargetEl(); }, afterRender: function() { var me = this, buffer = me.mouseOverOutBuffer; me.callParent(); me.mon(me.getTargetEl(), { scope: me, freezeEvent: true, click: me.handleEvent, mousedown: me.handleEvent, mouseup: me.handleEvent, dblclick: me.handleEvent, contextmenu: me.handleEvent, keydown: me.handleEvent, mouseover: buffer ? me.onMouseOver : me.handleMouseOver, mouseout: buffer ? me.onMouseOut : me.handleMouseOut }); }, onMouseOver: function(e) { var me = this; me.lastMouseOverEvent.setEvent(e.browserEvent, true); me.handleMouseOver(me.lastMouseOverEvent); }, onMouseOut: function(e) { var me = this; if (!me._mouseOutPending) { me._mouseOutPending = true; me.lastMouseOutEvent.setEvent(e.browserEvent, true); me.handleMouseOut(me.lastMouseOutEvent); } }, handleMouseOver: function(e) { var me = this, itemSelector = me.dataRowSelector || me.itemSelector, item = e.getTarget(itemSelector); if (!me.isDestroyed) { if (item) { if (me.mouseOverItem !== item && me.el.contains(item)) { me.mouseOverItem = e.item = item; e.newType = 'mouseenter'; me.handleEvent(e); } } else { e.item = e.newType = null; me.handleEvent(e); } } }, handleMouseOut: function(e) { var me = this, itemSelector = me.dataRowSelector || me.itemSelector, item = e.getTarget(itemSelector), sourceView; if (!me.isDestroyed) { me._mouseOutPending = false; if (item) { if (e.getRelatedTarget(itemSelector) !== item && me.mouseOverItem === item) { sourceView = me.self.getBoundView(item); e.item = item; e.newType = 'mouseleave'; sourceView.handleEvent(e); sourceView.mouseOverItem = null; } } else { e.item = e.newType = null; me.handleEvent(e); } } e.newType = e.item = null; }, handleEvent: function(e) { var me = this, key = e.type == 'keydown' && e.getKey(); if (me.processUIEvent(e) !== false) { me.processSpecialEvent(e); } if (key === e.SPACE) { if (!me.inputTagRe.test(e.getTarget().tagName)) { e.stopEvent(); } } }, processItemEvent: Ext.emptyFn, processContainerEvent: Ext.emptyFn, processSpecialEvent: Ext.emptyFn, processUIEvent: function(e) { if (!Ext.getBody().isAncestor(e.target)) { return; } var me = this, item = e.getTarget(me.dataRowSelector || me.itemSelector, me.getTargetEl()), map = me.statics().EventMap, index, record, type = e.type, newType = e.type, sm; if (e.newType) { newType = e.newType; item = e.item; } if (!item && type == 'keydown') { sm = me.getSelectionModel(); record = sm.lastFocused || sm.getLastSelected(); if (record) { item = me.getNode(record, true); } } if (item) { if (!record) { record = me.getRecord(item); } index = me.indexInStore ? me.indexInStore(record) : me.indexOf(item); if (!record || me.processItemEvent(record, item, index, e) === false) { return false; } if ( (me['onBeforeItem' + map[newType]](record, item, index, e) === false) || (me.fireEvent('beforeitem' + newType, me, record, item, index, e) === false) || (me['onItem' + map[newType]](record, item, index, e) === false) ) { return false; } me.fireEvent('item' + newType, me, record, item, index, e); } else { if ( (me.processContainerEvent(e) === false) || (me['onBeforeContainer' + map[type]](e) === false) || (me.fireEvent('beforecontainer' + type, me, e) === false) || (me['onContainer' + map[type]](e) === false) ) { return false; } me.fireEvent('container' + type, me, e); } return true; }, onItemMouseEnter: function(record, item, index, e) { if (this.trackOver) { this.highlightItem(item); } }, onItemMouseLeave : function(record, item, index, e) { if (this.trackOver) { this.clearHighlight(); } }, onItemMouseDown: Ext.emptyFn, onItemMouseUp: Ext.emptyFn, onItemFocus: Ext.emptyFn, onItemClick: Ext.emptyFn, onItemDblClick: Ext.emptyFn, onItemContextMenu: Ext.emptyFn, onItemKeyDown: Ext.emptyFn, onBeforeItemMouseDown: Ext.emptyFn, onBeforeItemMouseUp: Ext.emptyFn, onBeforeItemFocus: Ext.emptyFn, onBeforeItemMouseEnter: Ext.emptyFn, onBeforeItemMouseLeave: Ext.emptyFn, onBeforeItemClick: Ext.emptyFn, onBeforeItemDblClick: Ext.emptyFn, onBeforeItemContextMenu: Ext.emptyFn, onBeforeItemKeyDown: Ext.emptyFn, onContainerMouseDown: Ext.emptyFn, onContainerMouseUp: Ext.emptyFn, onContainerMouseOver: Ext.emptyFn, onContainerMouseOut: Ext.emptyFn, onContainerClick: Ext.emptyFn, onContainerDblClick: Ext.emptyFn, onContainerContextMenu: Ext.emptyFn, onContainerKeyDown: Ext.emptyFn, onBeforeContainerMouseDown: Ext.emptyFn, onBeforeContainerMouseUp: Ext.emptyFn, onBeforeContainerMouseOver: Ext.emptyFn, onBeforeContainerMouseOut: Ext.emptyFn, onBeforeContainerClick: Ext.emptyFn, onBeforeContainerDblClick: Ext.emptyFn, onBeforeContainerContextMenu: Ext.emptyFn, onBeforeContainerKeyDown: Ext.emptyFn, setHighlightedItem: function(item){ var me = this, highlighted = me.highlightedItem, overItemCls = me.overItemCls, beforeOverItemCls = me.beforeOverItemCls, previous; if (highlighted != item){ if (highlighted) { Ext.fly(highlighted).removeCls(overItemCls); previous = highlighted.previousSibling; if (beforeOverItemCls && previous) { Ext.fly(previous).removeCls(beforeOverItemCls); } me.fireEvent('unhighlightitem', me, highlighted); } me.highlightedItem = item; if (item) { Ext.fly(item).addCls(me.overItemCls); previous = item.previousSibling; if (beforeOverItemCls && previous) { Ext.fly(previous).addCls(beforeOverItemCls); } me.fireEvent('highlightitem', me, item); } } }, highlightItem: function(item) { this.setHighlightedItem(item); }, clearHighlight: function() { this.setHighlightedItem(undefined); }, onUpdate: function(store, record){ var me = this, node, newNode, highlighted; if (me.viewReady) { node = me.getNode(record); newNode = me.callParent(arguments); highlighted = me.highlightedItem; if (highlighted && highlighted === node) { delete me.highlightedItem; if (newNode) { me.highlightItem(newNode); } } } }, refresh: function() { this.clearHighlight(); this.callParent(arguments); }, focusNode: function(rec){ var me = this, node = me.getNode(rec, true), el = me.el, adjustmentY = 0, adjustmentX = 0, elRegion = el.getRegion(), nodeRegion; elRegion.bottom = elRegion.top + el.dom.clientHeight; elRegion.right = elRegion.left + el.dom.clientWidth; if (node) { nodeRegion = Ext.fly(node).getRegion(); if (nodeRegion.top < elRegion.top) { adjustmentY = nodeRegion.top - elRegion.top; } else if (nodeRegion.bottom > elRegion.bottom) { adjustmentY = nodeRegion.bottom - elRegion.bottom; } if (nodeRegion.left < elRegion.left) { adjustmentX = nodeRegion.left - elRegion.left; } else if (nodeRegion.right > elRegion.right) { adjustmentX = nodeRegion.right - elRegion.right; } if (adjustmentX || adjustmentY) { me.scrollBy(adjustmentX, adjustmentY, false); } el.focus(); } }, bindStore: function (store, initial, propertyName) { var dataSource = this[propertyName]; if (dataSource && dataSource.isFeatureStore) { if (store.isFeatureStore) { this.bindStoreListeners(store); dataSource.bindStore(dataSource.store); } else { dataSource.bindStore(store); } } else { this.callParent(arguments); } } }); Ext.define('Ext.layout.component.BoundList', { extend: Ext.layout.component.Auto , alias: 'layout.boundlist', type: 'component', beginLayout: function(ownerContext) { var me = this, owner = me.owner, toolbar = owner.pagingToolbar; me.callParent(arguments); if (owner.floating) { ownerContext.savedXY = owner.getXY(); owner.setXY([0, -9999]); } if (toolbar) { ownerContext.toolbarContext = ownerContext.context.getCmp(toolbar); } ownerContext.listContext = ownerContext.getEl('listEl'); }, beginLayoutCycle: function(ownerContext){ var owner = this.owner; this.callParent(arguments); if (ownerContext.heightModel.auto) { owner.el.setHeight('auto'); owner.listEl.setHeight('auto'); } }, getLayoutItems: function() { var toolbar = this.owner.pagingToolbar; return toolbar ? [toolbar] : []; }, isValidParent: function() { return true; }, finishedLayout: function(ownerContext) { var xy = ownerContext.savedXY; this.callParent(arguments); if (xy) { this.owner.setXY(xy); } }, measureContentWidth: function(ownerContext) { return this.owner.listEl.getWidth(); }, measureContentHeight: function(ownerContext) { return this.owner.listEl.getHeight(); }, publishInnerHeight: function(ownerContext, height) { var toolbar = ownerContext.toolbarContext, toolbarHeight = 0; if (toolbar) { toolbarHeight = toolbar.getProp('height'); } if (toolbarHeight === undefined) { this.done = false; } else { ownerContext.listContext.setHeight(height - ownerContext.getFrameInfo().height - toolbarHeight); } }, calculateOwnerHeightFromContentHeight: function(ownerContext){ var height = this.callParent(arguments), toolbar = ownerContext.toolbarContext; if (toolbar) { height += toolbar.getProp('height'); } return height; } }); Ext.define('Ext.toolbar.TextItem', { extend: Ext.toolbar.Item , alias: 'widget.tbtext', alternateClassName: 'Ext.Toolbar.TextItem', text: '', renderTpl: '{text}', baseCls: Ext.baseCSSPrefix + 'toolbar-text', ariaRole: null, beforeRender : function() { var me = this; me.callParent(); Ext.apply(me.renderData, { text: me.text }); }, setText : function(text) { var me = this; me.text = text; if (me.rendered) { me.el.update(text); me.updateLayout(); } } }); Ext.define('Ext.form.field.Spinner', { extend: Ext.form.field.Trigger , alias: 'widget.spinnerfield', alternateClassName: 'Ext.form.Spinner', trigger1Cls: Ext.baseCSSPrefix + 'form-spinner-up', trigger2Cls: Ext.baseCSSPrefix + 'form-spinner-down', spinUpEnabled: true, spinDownEnabled: true, keyNavEnabled: true, mouseWheelEnabled: true, repeatTriggerClick: true, onSpinUp: Ext.emptyFn, onSpinDown: Ext.emptyFn, ariaRole: 'spinbutton', triggerTpl: '' + '' + '' + '' + '', initComponent: function() { this.callParent(); this.addEvents( 'spin', 'spinup', 'spindown' ); }, onRender: function() { var me = this, triggers; me.callParent(arguments); triggers = me.triggerEl; me.spinUpEl = triggers.item(0); me.spinDownEl = triggers.item(1); me.triggerCell = me.spinUpEl.parent(); if (me.keyNavEnabled) { me.spinnerKeyNav = new Ext.util.KeyNav(me.inputEl, { scope: me, up: me.spinUp, down: me.spinDown }); } if (me.mouseWheelEnabled) { me.mon(me.bodyEl, 'mousewheel', me.onMouseWheel, me); } }, getSubTplMarkup: function(values) { var me = this, childElCls = values.childElCls, field = Ext.form.field.Base.prototype.getSubTplMarkup.apply(me, arguments); return '' + '' + '' + me.getTriggerMarkup() + ''; }, getTriggerMarkup: function() { return this.getTpl('triggerTpl').apply(this.getTriggerData()); }, getTriggerData: function(){ var me = this, hideTrigger = (me.readOnly || me.hideTrigger); return { triggerCls: Ext.baseCSSPrefix + 'trigger-cell', triggerStyle: hideTrigger ? 'display:none' : '', spinnerUpCls: !me.spinUpEnabled ? me.trigger1Cls + '-disabled': '', spinnerDownCls: !me.spinDownEnabled ? me.trigger2Cls + '-disabled': '' }; }, getTriggerWidth: function() { var me = this, totalTriggerWidth = 0; if (me.triggerWrap && !me.hideTrigger && !me.readOnly) { totalTriggerWidth = me.triggerWidth; } return totalTriggerWidth; }, onTrigger1Click: function() { this.spinUp(); }, onTrigger2Click: function() { this.spinDown(); }, onTriggerWrapMouseup: function() { this.inputEl.focus(); }, spinUp: function() { var me = this; if (me.spinUpEnabled && !me.disabled) { me.fireEvent('spin', me, 'up'); me.fireEvent('spinup', me); me.onSpinUp(); } }, spinDown: function() { var me = this; if (me.spinDownEnabled && !me.disabled) { me.fireEvent('spin', me, 'down'); me.fireEvent('spindown', me); me.onSpinDown(); } }, setSpinUpEnabled: function(enabled) { var me = this, wasEnabled = me.spinUpEnabled; me.spinUpEnabled = enabled; if (wasEnabled !== enabled && me.rendered) { me.spinUpEl[enabled ? 'removeCls' : 'addCls'](me.trigger1Cls + '-disabled'); } }, setSpinDownEnabled: function(enabled) { var me = this, wasEnabled = me.spinDownEnabled; me.spinDownEnabled = enabled; if (wasEnabled !== enabled && me.rendered) { me.spinDownEl[enabled ? 'removeCls' : 'addCls'](me.trigger2Cls + '-disabled'); } }, onMouseWheel: function(e) { var me = this, delta; if (me.hasFocus) { delta = e.getWheelDelta(); if (delta > 0) { me.spinUp(); } else if (delta < 0) { me.spinDown(); } e.stopEvent(); } }, onDestroy: function() { Ext.destroyMembers(this, 'spinnerKeyNav', 'spinUpEl', 'spinDownEl'); this.callParent(); } }); Ext.define('Ext.form.field.Number', { extend: Ext.form.field.Spinner , alias: 'widget.numberfield', alternateClassName: ['Ext.form.NumberField', 'Ext.form.Number'], allowExponential: true, allowDecimals : true, decimalSeparator : null, submitLocaleSeparator: true, decimalPrecision : 2, minValue: Number.NEGATIVE_INFINITY, maxValue: Number.MAX_VALUE, step: 1, minText : 'The minimum value for this field is {0}', maxText : 'The maximum value for this field is {0}', nanText : '{0} is not a valid number', negativeText : 'The value cannot be negative', baseChars : '0123456789', autoStripChars: false, initComponent: function() { var me = this; if (me.decimalSeparator === null) { me.decimalSeparator = Ext.util.Format.decimalSeparator; } me.callParent(); me.setMinValue(me.minValue); me.setMaxValue(me.maxValue); }, getErrors: function(value) { var me = this, errors = me.callParent(arguments), format = Ext.String.format, num; value = Ext.isDefined(value) ? value : this.processRawValue(this.getRawValue()); if (value.length < 1) { return errors; } value = String(value).replace(me.decimalSeparator, '.'); if(isNaN(value)){ errors.push(format(me.nanText, value)); } num = me.parseValue(value); if (me.minValue === 0 && num < 0) { errors.push(this.negativeText); } else if (num < me.minValue) { errors.push(format(me.minText, me.minValue)); } if (num > me.maxValue) { errors.push(format(me.maxText, me.maxValue)); } return errors; }, rawToValue: function(rawValue) { var value = this.fixPrecision(this.parseValue(rawValue)); if (value === null) { value = rawValue || null; } return value; }, valueToRaw: function(value) { var me = this, decimalSeparator = me.decimalSeparator; value = me.parseValue(value); value = me.fixPrecision(value); value = Ext.isNumber(value) ? value : parseFloat(String(value).replace(decimalSeparator, '.')); value = isNaN(value) ? '' : String(value).replace('.', decimalSeparator); return value; }, getSubmitValue: function() { var me = this, value = me.callParent(); if (!me.submitLocaleSeparator) { value = value.replace(me.decimalSeparator, '.'); } return value; }, onChange: function() { this.toggleSpinners(); this.callParent(arguments); }, toggleSpinners: function(){ var me = this, value = me.getValue(), valueIsNull = value === null, enabled; if (me.spinUpEnabled || me.spinUpDisabledByToggle) { enabled = valueIsNull || value < me.maxValue; me.setSpinUpEnabled(enabled, true); } if (me.spinDownEnabled || me.spinDownDisabledByToggle) { enabled = valueIsNull || value > me.minValue; me.setSpinDownEnabled(enabled, true); } }, setMinValue : function(value) { var me = this, allowed; me.minValue = Ext.Number.from(value, Number.NEGATIVE_INFINITY); me.toggleSpinners(); if (me.disableKeyFilter !== true) { allowed = me.baseChars + ''; if (me.allowExponential) { allowed += me.decimalSeparator + 'e+-'; } else { if (me.allowDecimals) { allowed += me.decimalSeparator; } if (me.minValue < 0) { allowed += '-'; } } allowed = Ext.String.escapeRegex(allowed); me.maskRe = new RegExp('[' + allowed + ']'); if (me.autoStripChars) { me.stripCharsRe = new RegExp('[^' + allowed + ']', 'gi'); } } }, setMaxValue: function(value) { this.maxValue = Ext.Number.from(value, Number.MAX_VALUE); this.toggleSpinners(); }, parseValue : function(value) { value = parseFloat(String(value).replace(this.decimalSeparator, '.')); return isNaN(value) ? null : value; }, fixPrecision : function(value) { var me = this, nan = isNaN(value), precision = me.decimalPrecision; if (nan || !value) { return nan ? '' : value; } else if (!me.allowDecimals || precision <= 0) { precision = 0; } return parseFloat(Ext.Number.toFixed(parseFloat(value), precision)); }, beforeBlur : function() { var me = this, v = me.parseValue(me.getRawValue()); if (!Ext.isEmpty(v)) { me.setValue(v); } }, setSpinUpEnabled: function(enabled, internal){ this.callParent(arguments); if (!internal) { delete this.spinUpDisabledByToggle; } else { this.spinUpDisabledByToggle = !enabled; } }, onSpinUp: function() { var me = this; if (!me.readOnly) { me.setSpinValue(Ext.Number.constrain(me.getValue() + me.step, me.minValue, me.maxValue)); } }, setSpinDownEnabled: function(enabled, internal){ this.callParent(arguments); if (!internal) { delete this.spinDownDisabledByToggle; } else { this.spinDownDisabledByToggle = !enabled; } }, onSpinDown: function() { var me = this; if (!me.readOnly) { me.setSpinValue(Ext.Number.constrain(me.getValue() - me.step, me.minValue, me.maxValue)); } }, setSpinValue: function(value) { var me = this, len; if (me.enforceMaxLength) { if (me.fixPrecision(value).toString().length > me.maxLength) { return; } } me.setValue(value); } }); Ext.define('Ext.toolbar.Paging', { extend: Ext.toolbar.Toolbar , alias: 'widget.pagingtoolbar', alternateClassName: 'Ext.PagingToolbar', mixins: { bindable: Ext.util.Bindable }, displayInfo: false, prependButtons: false, displayMsg : 'Displaying {0} - {1} of {2}', emptyMsg : 'No data to display', beforePageText : 'Page', afterPageText : 'of {0}', firstText : 'First Page', prevText : 'Previous Page', nextText : 'Next Page', lastText : 'Last Page', refreshText : 'Refresh', inputItemWidth : 30, getPagingItems: function() { var me = this; return [{ itemId: 'first', tooltip: me.firstText, overflowText: me.firstText, iconCls: Ext.baseCSSPrefix + 'tbar-page-first', disabled: true, handler: me.moveFirst, scope: me },{ itemId: 'prev', tooltip: me.prevText, overflowText: me.prevText, iconCls: Ext.baseCSSPrefix + 'tbar-page-prev', disabled: true, handler: me.movePrevious, scope: me }, '-', me.beforePageText, { xtype: 'numberfield', itemId: 'inputItem', name: 'inputItem', cls: Ext.baseCSSPrefix + 'tbar-page-number', allowDecimals: false, minValue: 1, hideTrigger: true, enableKeyEvents: true, keyNavEnabled: false, selectOnFocus: true, submitValue: false, isFormField: false, width: me.inputItemWidth, margins: '-1 2 3 2', listeners: { scope: me, keydown: me.onPagingKeyDown, blur: me.onPagingBlur } },{ xtype: 'tbtext', itemId: 'afterTextItem', text: Ext.String.format(me.afterPageText, 1) }, '-', { itemId: 'next', tooltip: me.nextText, overflowText: me.nextText, iconCls: Ext.baseCSSPrefix + 'tbar-page-next', disabled: true, handler: me.moveNext, scope: me },{ itemId: 'last', tooltip: me.lastText, overflowText: me.lastText, iconCls: Ext.baseCSSPrefix + 'tbar-page-last', disabled: true, handler: me.moveLast, scope: me }, '-', { itemId: 'refresh', tooltip: me.refreshText, overflowText: me.refreshText, iconCls: Ext.baseCSSPrefix + 'tbar-loading', disabled: me.store.isLoading(), handler: me.doRefresh, scope: me }]; }, initComponent : function(){ var me = this, userItems = me.items || me.buttons || [], pagingItems; me.bindStore(me.store || 'ext-empty-store', true); pagingItems = me.getPagingItems(); if (me.prependButtons) { me.items = userItems.concat(pagingItems); } else { me.items = pagingItems.concat(userItems); } delete me.buttons; if (me.displayInfo) { me.items.push('->'); me.items.push({xtype: 'tbtext', itemId: 'displayItem'}); } me.callParent(); me.addEvents( 'change', 'beforechange' ); }, beforeRender: function() { this.callParent(arguments); if (!this.store.isLoading()) { this.onLoad(); } }, updateInfo : function(){ var me = this, displayItem = me.child('#displayItem'), store = me.store, pageData = me.getPageData(), count, msg; if (displayItem) { count = store.getCount(); if (count === 0) { msg = me.emptyMsg; } else { msg = Ext.String.format( me.displayMsg, pageData.fromRecord, pageData.toRecord, pageData.total ); } displayItem.setText(msg); } }, onLoad : function(){ var me = this, pageData, currPage, pageCount, afterText, count, isEmpty, item; count = me.store.getCount(); isEmpty = count === 0; if (!isEmpty) { pageData = me.getPageData(); currPage = pageData.currentPage; pageCount = pageData.pageCount; if (currPage > pageCount) { me.store.loadPage(pageCount); return; } afterText = Ext.String.format(me.afterPageText, isNaN(pageCount) ? 1 : pageCount); } else { currPage = 0; pageCount = 0; afterText = Ext.String.format(me.afterPageText, 0); } Ext.suspendLayouts(); item = me.child('#afterTextItem'); if (item) { item.setText(afterText); } item = me.getInputItem(); if (item) { item.setDisabled(isEmpty).setValue(currPage); } me.setChildDisabled('#first', currPage === 1 || isEmpty); me.setChildDisabled('#prev', currPage === 1 || isEmpty); me.setChildDisabled('#next', currPage === pageCount || isEmpty); me.setChildDisabled('#last', currPage === pageCount || isEmpty); me.setChildDisabled('#refresh', false); me.updateInfo(); Ext.resumeLayouts(true); me.fireEvent('change', me, pageData); }, setChildDisabled: function(selector, disabled){ var item = this.child(selector); if (item) { item.setDisabled(disabled); } }, getPageData : function(){ var store = this.store, totalCount = store.getTotalCount(); return { total : totalCount, currentPage : store.currentPage, pageCount: Math.ceil(totalCount / store.pageSize), fromRecord: ((store.currentPage - 1) * store.pageSize) + 1, toRecord: Math.min(store.currentPage * store.pageSize, totalCount) }; }, onLoadError : function(){ this.setChildDisabled('#refresh', false); }, getInputItem: function(){ return this.child('#inputItem'); }, readPageFromInput : function(pageData){ var inputItem = this.getInputItem(), pageNum = false, v; if (inputItem) { v = inputItem.getValue(); pageNum = parseInt(v, 10); if (!v || isNaN(pageNum)) { inputItem.setValue(pageData.currentPage); return false; } } return pageNum; }, onPagingBlur : function(e){ var inputItem = this.getInputItem(), curPage; if (inputItem) { curPage = this.getPageData().currentPage; inputItem.setValue(curPage); } }, onPagingKeyDown : function(field, e){ this.processKeyEvent(field, e); }, processKeyEvent: function(field, e) { var me = this, k = e.getKey(), pageData = me.getPageData(), increment = e.shiftKey ? 10 : 1, pageNum; if (k == e.RETURN) { e.stopEvent(); pageNum = me.readPageFromInput(pageData); if (pageNum !== false) { pageNum = Math.min(Math.max(1, pageNum), pageData.pageCount); if (pageNum !== pageData.currentPage && me.fireEvent('beforechange', me, pageNum) !== false) { me.store.loadPage(pageNum); } } } else if (k == e.HOME || k == e.END) { e.stopEvent(); pageNum = k == e.HOME ? 1 : pageData.pageCount; field.setValue(pageNum); } else if (k == e.UP || k == e.PAGE_UP || k == e.DOWN || k == e.PAGE_DOWN) { e.stopEvent(); pageNum = me.readPageFromInput(pageData); if (pageNum) { if (k == e.DOWN || k == e.PAGE_DOWN) { increment *= -1; } pageNum += increment; if (pageNum >= 1 && pageNum <= pageData.pageCount) { field.setValue(pageNum); } } } }, beforeLoad : function() { this.setChildDisabled('#refresh', true); }, moveFirst : function(){ if (this.fireEvent('beforechange', this, 1) !== false){ this.store.loadPage(1); return true; } return false; }, movePrevious : function(){ var me = this, store = me.store, prev = store.currentPage - 1; if (prev > 0) { if (me.fireEvent('beforechange', me, prev) !== false) { store.previousPage(); return true; } } return false; }, moveNext : function(){ var me = this, store = me.store, total = me.getPageData().pageCount, next = store.currentPage + 1; if (next <= total) { if (me.fireEvent('beforechange', me, next) !== false) { store.nextPage(); return true; } } return false; }, moveLast : function(){ var me = this, last = me.getPageData().pageCount; if (me.fireEvent('beforechange', me, last) !== false) { me.store.loadPage(last); return true; } return false; }, doRefresh : function(){ var me = this, store = me.store, current = store.currentPage; if (me.fireEvent('beforechange', me, current) !== false) { store.loadPage(current); return true; } return false; }, getStoreListeners: function() { return { beforeload: this.beforeLoad, load: this.onLoad, exception: this.onLoadError }; }, unbind : function(store){ this.bindStore(null); }, bind : function(store){ this.bindStore(store); }, onDestroy : function(){ this.unbind(); this.callParent(); } }); Ext.define('Ext.view.BoundList', { extend: Ext.view.View , alias: 'widget.boundlist', alternateClassName: 'Ext.BoundList', mixins: { queryable: Ext.Queryable }, pageSize: 0, baseCls: Ext.baseCSSPrefix + 'boundlist', itemCls: Ext.baseCSSPrefix + 'boundlist-item', listItemCls: '', shadow: false, trackOver: true, refreshed: 0, deferInitialRefresh: false, componentLayout: 'boundlist', childEls: [ 'listEl' ], renderTpl: [ '', '{%', 'var me=values.$comp, pagingToolbar=me.pagingToolbar;', 'if (pagingToolbar) {', 'pagingToolbar.ownerLayout = me.componentLayout;', 'Ext.DomHelper.generateMarkup(pagingToolbar.getRenderTree(), out);', '}', '%}', { disableFormats: true } ], initComponent: function() { var me = this, baseCls = me.baseCls, itemCls = me.itemCls; me.selectedItemCls = baseCls + '-selected'; if (me.trackOver) { me.overItemCls = baseCls + '-item-over'; } me.itemSelector = "." + itemCls; if (me.floating) { me.addCls(baseCls + '-floating'); } if (!me.tpl) { me.tpl = new Ext.XTemplate( '
    ', '
  • ' + me.getInnerTpl(me.displayField) + '
  • ', '
' ); } else if (!me.tpl.isTemplate) { me.tpl = new Ext.XTemplate(me.tpl); } if (me.pageSize) { me.pagingToolbar = me.createPagingToolbar(); } me.callParent(); }, beforeRender: function() { var me = this; me.callParent(arguments); if (me.up('menu')) { me.addCls(Ext.baseCSSPrefix + 'menu'); } }, getRefOwner: function() { return this.pickerField || this.callParent(); }, getRefItems: function() { return this.pagingToolbar ? [ this.pagingToolbar ] : []; }, createPagingToolbar: function() { return Ext.widget('pagingtoolbar', { id: this.id + '-paging-toolbar', pageSize: this.pageSize, store: this.dataSource, border: false, ownerCt: this, ownerLayout: this.getComponentLayout() }); }, finishRenderChildren: function () { var toolbar = this.pagingToolbar; this.callParent(arguments); if (toolbar) { toolbar.finishRender(); } }, refresh: function(){ var me = this, tpl = me.tpl, toolbar = me.pagingToolbar, rendered = me.rendered; tpl.field = me.pickerField; tpl.store = me.store; me.callParent(); tpl.field = tpl.store = null; if (rendered && toolbar && toolbar.rendered && !me.preserveScrollOnRefresh) { me.el.appendChild(toolbar.el); } if (rendered && Ext.isIE6 && Ext.isStrict) { me.listEl.repaint(); } }, bindStore : function(store, initial) { var toolbar = this.pagingToolbar; this.callParent(arguments); if (toolbar) { toolbar.bindStore(store, initial); } }, getTargetEl: function() { return this.listEl || this.el; }, getInnerTpl: function(displayField) { return '{' + displayField + '}'; }, onDestroy: function() { Ext.destroyMembers(this, 'pagingToolbar', 'listEl'); this.callParent(); } }); Ext.define('Ext.view.BoundListKeyNav', { extend: Ext.util.KeyNav , constructor: function(el, config) { var me = this; me.boundList = config.boundList; me.callParent([el, Ext.apply({}, config, me.defaultHandlers)]); }, defaultHandlers: { up: function() { var me = this, boundList = me.boundList, allItems = boundList.all, oldItem = boundList.highlightedItem, oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1, newItemIdx = oldItemIdx > 0 ? oldItemIdx - 1 : allItems.getCount() - 1; me.highlightAt(newItemIdx); }, down: function() { var me = this, boundList = me.boundList, allItems = boundList.all, oldItem = boundList.highlightedItem, oldItemIdx = oldItem ? boundList.indexOf(oldItem) : -1, newItemIdx = oldItemIdx < allItems.getCount() - 1 ? oldItemIdx + 1 : 0; me.highlightAt(newItemIdx); }, pageup: function() { }, pagedown: function() { }, home: function() { this.highlightAt(0); }, end: function() { var me = this; me.highlightAt(me.boundList.all.getCount() - 1); }, enter: function(e) { this.selectHighlighted(e); } }, highlightAt: function(index) { var boundList = this.boundList, item = boundList.all.item(index); if (item) { item = item.dom; boundList.highlightItem(item); boundList.getTargetEl().scrollChildIntoView(item, false); } }, selectHighlighted: function(e) { var boundList = this.boundList, selModel = boundList.getSelectionModel(), highlighted, highlightedRec; highlighted = boundList.highlightedItem; if (highlighted) { highlightedRec = boundList.getRecord(highlighted); if (e.getKey() === e.ENTER || !selModel.isSelected(highlightedRec)) { selModel.selectWithEvent(highlightedRec, e); } } } }); Ext.define('Ext.layout.component.field.ComboBox', { extend: Ext.layout.component.field.Trigger , alias: 'layout.combobox', type: 'combobox', startingWidth: null, getTextWidth: function () { var me = this, owner = me.owner, store = owner.store, field = owner.displayField, storeLn = store.data.length, value = '', i = 0, n = 0, ln, item, width; for (; i < storeLn; i++) { item = store.getAt(i).data[field]; ln = item.length; if (ln > n) { n = ln; value = item; } } width = Math.max(me.callParent(arguments), owner.inputEl.getTextWidth(value + owner.growAppend)); if (!me.startingWidth || owner.removingRecords) { me.startingWidth = width; if (width < owner.growMin) { owner.defaultListConfig.minWidth = owner.growMin; } owner.removingRecords = false; } return (width < me.startingWidth) ? me.startingWidth : width; } }); Ext.define('Ext.form.field.ComboBox', { extend: Ext.form.field.Picker , alternateClassName: 'Ext.form.ComboBox', alias: ['widget.combobox', 'widget.combo'], mixins: { bindable: Ext.util.Bindable }, componentLayout: 'combobox', triggerCls: Ext.baseCSSPrefix + 'form-arrow-trigger', hiddenName: '', hiddenDataCls: Ext.baseCSSPrefix + 'hide-display ' + Ext.baseCSSPrefix + 'form-data-hidden', ariaRole: 'combobox', fieldSubTpl: [ '', ' value="{[Ext.util.Format.htmlEncode(values.value)]}"', ' name="{name}"', ' placeholder="{placeholder}"', ' size="{size}"', ' maxlength="{maxLength}"', ' readonly="readonly"', ' disabled="disabled"', ' tabIndex="{tabIdx}"', ' style="{fieldStyle}"', '/>', { compiled: true, disableFormats: true } ], getSubTplData: function(){ var me = this; Ext.applyIf(me.subTplData, { hiddenDataCls: me.hiddenDataCls }); return me.callParent(arguments); }, afterRender: function(){ var me = this; me.callParent(arguments); me.setHiddenValue(me.value); }, multiSelect: false, delimiter: ', ', displayField: 'text', triggerAction: 'all', allQuery: '', queryParam: 'query', queryMode: 'remote', queryCaching: true, pageSize: 0, anyMatch: false, caseSensitive: false, autoSelect: true, typeAhead: false, typeAheadDelay: 250, selectOnTab: true, forceSelection: false, growToLongestValue: true, clearFilterOnBlur: true, defaultListConfig: { loadingHeight: 70, minWidth: 70, maxHeight: 300, shadow: 'sides' }, transformInPlace: true, ignoreSelection: 0, removingRecords: null, resizeComboToGrow: function () { var me = this; return me.grow && me.growToLongestValue; }, initComponent: function() { var me = this, isDefined = Ext.isDefined, store = me.store, transform = me.transform, displayTpl = me.displayTpl, transformSelect, isLocalMode; Ext.applyIf(me.renderSelectors, { hiddenDataEl: '.' + me.hiddenDataCls.split(' ').join('.') }); me.addEvents( 'beforequery', 'select', 'beforeselect', 'beforedeselect' ); if (transform) { transformSelect = Ext.getDom(transform); if (transformSelect) { if (!me.store) { store = Ext.Array.map(Ext.Array.from(transformSelect.options), function(option){ return [option.value, option.text]; }); } if (!me.name) { me.name = transformSelect.name; } if (!('value' in me)) { me.value = transformSelect.value; } } } me.bindStore(store || 'ext-empty-store', true); store = me.store; if (store.autoCreated) { me.queryMode = 'local'; me.valueField = me.displayField = 'field1'; if (!store.expanded) { me.displayField = 'field2'; } } if (!isDefined(me.valueField)) { me.valueField = me.displayField; } isLocalMode = me.queryMode === 'local'; if (!isDefined(me.queryDelay)) { me.queryDelay = isLocalMode ? 10 : 500; } if (!isDefined(me.minChars)) { me.minChars = isLocalMode ? 0 : 4; } if (!displayTpl) { me.displayTpl = new Ext.XTemplate( '' + '{[typeof values === "string" ? values : values["' + me.displayField + '"]]}' + '' + me.delimiter + '' + '' ); } else if (!displayTpl.isTemplate) { me.displayTpl = new Ext.XTemplate(displayTpl); } me.callParent(); me.doQueryTask = new Ext.util.DelayedTask(me.doRawQuery, me); if (me.store.getCount() > 0) { me.setValue(me.value); } if (transformSelect) { if (me.transformInPlace) { me.render(transformSelect.parentNode, transformSelect); delete me.renderTo; } Ext.removeNode(transformSelect); } }, getStore : function(){ return this.store; }, beforeBlur: function() { var me = this, filter = me.queryFilter; me.doQueryTask.cancel(); me.assertValue(); if (filter && !filter.disabled && me.queryMode === 'local' && me.clearFilterOnBlur) { filter.disabled = true; me.store.filter(); } }, onFocus: function() { var me = this, filter = me.queryFilter; me.callParent(arguments); if (!me.duringTriggerClick && me.triggerAction !== 'all' && filter && filter.disabled && me.queryMode === 'local' && me.clearFilterOnBlur) { delete me.lastQuery; me.doRawQuery(); } }, assertValue: function() { var me = this, value = me.getRawValue(), rec, currentValue; if (me.forceSelection) { if (me.multiSelect) { if (value !== me.getDisplayValue()) { me.setValue(me.lastSelection); } } else { rec = me.findRecordByDisplay(value); if (rec) { currentValue = me.value; if (!me.findRecordByValue(currentValue)) { me.select(rec, true); } } else { me.setValue(me.lastSelection); } } } me.collapse(); }, onTypeAhead: function() { var me = this, displayField = me.displayField, record = me.store.findRecord(displayField, me.getRawValue()), boundList = me.getPicker(), newValue, len, selStart; if (record) { newValue = record.get(displayField); len = newValue.length; selStart = me.getRawValue().length; boundList.highlightItem(boundList.getNode(record)); if (selStart !== 0 && selStart !== len) { me.setRawValue(newValue); me.selectText(selStart, newValue.length); } } }, resetToDefault: Ext.emptyFn, beforeReset: function() { var filter = this.queryFilter; this.callParent(); if (filter && !filter.disabled) { filter.disabled = true; this.store.filter(); } }, onUnbindStore: function(store) { var me = this, picker = me.picker, filter = me.queryFilter; if (filter) { me.store.removeFilter(filter); } if (!store && picker) { picker.bindStore(null); } }, onBindStore: function(store, initial) { var picker = this.picker; if (!initial) { this.resetToDefault(); } if (picker) { picker.bindStore(store); } }, getStoreListeners: function() { var me = this; return { beforeload: me.onBeforeLoad, clear: me.onClear, datachanged: me.onDataChanged, load: me.onLoad, exception: me.onException, remove: me.onRemove }; }, onBeforeLoad: function(){ ++this.ignoreSelection; }, onDataChanged: function() { var me = this; if (me.resizeComboToGrow()) { me.updateLayout(); } }, onClear: function() { var me = this; if (me.resizeComboToGrow()) { me.removingRecords = true; me.onDataChanged(); } }, onRemove: function() { var me = this; if (me.resizeComboToGrow()) { me.removingRecords = true; } }, onException: function(){ if (this.ignoreSelection > 0) { --this.ignoreSelection; } this.collapse(); }, onLoad: function(store, records, success) { var me = this; if (me.ignoreSelection > 0) { --me.ignoreSelection; } if (success && !store.lastOptions.rawQuery) { if (me.value == null) { if (me.store.getCount()) { me.doAutoSelect(); } else { me.setValue(me.value); } } else { me.setValue(me.value); } } }, doRawQuery: function() { this.doQuery(this.getRawValue(), false, true); }, doQuery: function(queryString, forceAll, rawQuery) { var me = this, queryPlan = me.beforeQuery({ query: queryString || '', rawQuery: rawQuery, forceAll: forceAll, combo: me, cancel: false }); if (queryPlan === false || queryPlan.cancel) { return false; } if (me.queryCaching && queryPlan.query === me.lastQuery) { me.expand(); if (me.queryMode === 'local') { me.doAutoSelect(); } } else { me.lastQuery = queryPlan.query; if (me.queryMode === 'local') { me.doLocalQuery(queryPlan); } else { me.doRemoteQuery(queryPlan); } } return true; }, beforeQuery: function(queryPlan) { var me = this; if (me.fireEvent('beforequery', queryPlan) === false) { queryPlan.cancel = true; } else if (!queryPlan.cancel) { if (queryPlan.query.length < me.minChars && !queryPlan.forceAll) { queryPlan.cancel = true; } } return queryPlan; }, doLocalQuery: function(queryPlan) { var me = this, queryString = queryPlan.query; if (!me.queryFilter) { me.queryFilter = new Ext.util.Filter({ id: me.id + '-query-filter', anyMatch: me.anyMatch, caseSensitive: me.caseSensitive, root: 'data', property: me.displayField }); me.store.addFilter(me.queryFilter, false); } if (queryString || !queryPlan.forceAll) { me.queryFilter.disabled = false; me.queryFilter.setValue(me.enableRegEx ? new RegExp(queryString) : queryString); } else { me.queryFilter.disabled = true; } me.store.filter(); if (me.store.getCount()) { me.expand(); } else { me.collapse(); } me.afterQuery(queryPlan); }, doRemoteQuery: function(queryPlan) { var me = this, loadCallback = function() { me.afterQuery(queryPlan); }; me.expand(); if (me.pageSize) { me.loadPage(1, { rawQuery: queryPlan.rawQuery, callback: loadCallback }); } else { me.store.load({ params: me.getParams(queryPlan.query), rawQuery: queryPlan.rawQuery, callback: loadCallback }); } }, afterQuery: function(queryPlan) { var me = this; if (me.store.getCount()) { if (me.typeAhead) { me.doTypeAhead(); } if (me.getRawValue() !== me.getDisplayValue()) { me.ignoreSelection++; me.picker.getSelectionModel().deselectAll(); me.ignoreSelection--; } if (queryPlan.rawQuery) { me.syncSelection(); if (me.picker && !me.picker.getSelectionModel().hasSelection()) { me.doAutoSelect(); } } else { me.doAutoSelect(); } } }, loadPage: function(pageNum, options) { this.store.loadPage(pageNum, Ext.apply({ params: this.getParams(this.lastQuery) }, options)); }, onPageChange: function(toolbar, newPage){ this.loadPage(newPage); return false; }, getParams: function(queryString) { var params = {}, param = this.queryParam; if (param) { params[param] = queryString; } return params; }, doAutoSelect: function() { var me = this, picker = me.picker, lastSelected, itemNode; if (picker && me.autoSelect && me.store.getCount() > 0) { lastSelected = picker.getSelectionModel().lastSelected; itemNode = picker.getNode(lastSelected || 0); if (itemNode) { picker.highlightItem(itemNode); picker.listEl.scrollChildIntoView(itemNode, false); } } }, doTypeAhead: function() { var me = this; if (!me.typeAheadTask) { me.typeAheadTask = new Ext.util.DelayedTask(me.onTypeAhead, me); } if (me.lastKey != Ext.EventObject.BACKSPACE && me.lastKey != Ext.EventObject.DELETE) { me.typeAheadTask.delay(me.typeAheadDelay); } }, onTriggerClick: function() { var me = this; me.duringTriggerClick = true; if (!me.readOnly && !me.disabled) { if (me.isExpanded) { me.collapse(); } else { me.onFocus({}); if (me.triggerAction === 'all') { me.doQuery(me.allQuery, true); } else if (me.triggerAction === 'last') { me.doQuery(me.lastQuery, true); } else { me.doQuery(me.getRawValue(), false, true); } } me.inputEl.focus(); } delete me.duringTriggerClick; }, onPaste: function(){ var me = this; if (!me.readOnly && !me.disabled && me.editable) { me.doQueryTask.delay(me.queryDelay); } }, onKeyUp: function(e, t) { var me = this, key = e.getKey(); if (!me.readOnly && !me.disabled && me.editable) { me.lastKey = key; if (!e.isSpecialKey() || key == e.BACKSPACE || key == e.DELETE) { me.doQueryTask.delay(me.queryDelay); } } if (me.enableKeyEvents) { me.callParent(arguments); } }, initEvents: function() { var me = this; me.callParent(); if (!me.enableKeyEvents) { me.mon(me.inputEl, 'keyup', me.onKeyUp, me); } me.mon(me.inputEl, 'paste', me.onPaste, me); }, onDestroy: function() { var me = this if (me.typeAheadTask) { me.typeAheadTask.cancel(); me.typeAheadTask = null; } Ext.destroy(me.listKeyNav); me.bindStore(null); me.callParent(); }, onAdded: function() { var me = this; me.callParent(arguments); if (me.picker) { me.picker.ownerCt = me.up('[floating]'); me.picker.registerWithOwnerCt(); } }, createPicker: function() { var me = this, picker, pickerCfg = Ext.apply({ xtype: 'boundlist', pickerField: me, selModel: { mode: me.multiSelect ? 'SIMPLE' : 'SINGLE' }, floating: true, hidden: true, store: me.store, displayField: me.displayField, focusOnToFront: false, pageSize: me.pageSize, tpl: me.tpl }, me.listConfig, me.defaultListConfig); picker = me.picker = Ext.widget(pickerCfg); if (me.pageSize) { picker.pagingToolbar.on('beforechange', me.onPageChange, me); } me.mon(picker, { itemclick: me.onItemClick, refresh: me.onListRefresh, scope: me }); me.mon(picker.getSelectionModel(), { beforeselect: me.onBeforeSelect, beforedeselect: me.onBeforeDeselect, selectionchange: me.onListSelectionChange, scope: me }); return picker; }, alignPicker: function(){ var me = this, picker = me.getPicker(), heightAbove = me.getPosition()[1] - Ext.getBody().getScroll().top, heightBelow = Ext.Element.getViewHeight() - heightAbove - me.getHeight(), space = Math.max(heightAbove, heightBelow); if (picker.height) { delete picker.height; picker.updateLayout(); } if (picker.getHeight() > space - 5) { picker.setHeight(space - 5); } me.callParent(); }, onListRefresh: function() { if (!this.expanding) { this.alignPicker(); } this.syncSelection(); }, onItemClick: function(picker, record){ var me = this, selection = me.picker.getSelectionModel().getSelection(), valueField = me.valueField; if (!me.multiSelect && selection.length) { if (record.get(valueField) === selection[0].get(valueField)) { me.displayTplData = [record.data]; me.setRawValue(me.getDisplayValue()); me.collapse(); } } }, onBeforeSelect: function(list, record) { return this.fireEvent('beforeselect', this, record, record.index); }, onBeforeDeselect: function(list, record) { return this.fireEvent('beforedeselect', this, record, record.index); }, onListSelectionChange: function(list, selectedRecords) { var me = this, isMulti = me.multiSelect, hasRecords = selectedRecords.length > 0; if (!me.ignoreSelection && me.isExpanded) { if (!isMulti) { Ext.defer(me.collapse, 1, me); } if (isMulti || hasRecords) { me.setValue(selectedRecords, false); } if (hasRecords) { me.fireEvent('select', me, selectedRecords); } me.inputEl.focus(); } }, onExpand: function() { var me = this, keyNav = me.listKeyNav, selectOnTab = me.selectOnTab, picker = me.getPicker(); if (keyNav) { keyNav.enable(); } else { keyNav = me.listKeyNav = new Ext.view.BoundListKeyNav(me.inputEl, { boundList: picker, forceKeyDown: true, tab: function(e) { if (selectOnTab) { this.selectHighlighted(e); me.triggerBlur(); } return true; }, enter: function(e){ var selModel = picker.getSelectionModel(), count = selModel.getCount(); this.selectHighlighted(e); if (!me.multiSelect && count === selModel.getCount()) { me.collapse(); } } }); } if (selectOnTab) { me.ignoreMonitorTab = true; } Ext.defer(keyNav.enable, 1, keyNav); me.inputEl.focus(); }, onCollapse: function() { var me = this, keyNav = me.listKeyNav; if (keyNav) { keyNav.disable(); me.ignoreMonitorTab = false; } }, select: function(r, assert) { var me = this, picker = me.picker, fireSelect; if (r && r.isModel && assert === true && picker) { fireSelect = !picker.getSelectionModel().isSelected(r); } me.setValue(r, true); if (fireSelect) { me.fireEvent('select', me, r); } }, findRecord: function(field, value) { var ds = this.store, idx = ds.findExact(field, value); return idx !== -1 ? ds.getAt(idx) : false; }, findRecordByValue: function(value) { return this.findRecord(this.valueField, value); }, findRecordByDisplay: function(value) { return this.findRecord(this.displayField, value); }, setValue: function(value, doSelect) { var me = this, valueNotFoundText = me.valueNotFoundText, inputEl = me.inputEl, i, len, record, dataObj, matchedRecords = [], displayTplData = [], processedValue = []; if (me.store.loading) { me.value = value; me.setHiddenValue(me.value); return me; } value = Ext.Array.from(value); for (i = 0, len = value.length; i < len; i++) { record = value[i]; if (!record || !record.isModel) { record = me.findRecordByValue(record); } if (record) { matchedRecords.push(record); displayTplData.push(record.data); processedValue.push(record.get(me.valueField)); } else { if (!me.forceSelection) { processedValue.push(value[i]); dataObj = {}; dataObj[me.displayField] = value[i]; displayTplData.push(dataObj); } else if (Ext.isDefined(valueNotFoundText)) { displayTplData.push(valueNotFoundText); } } } me.setHiddenValue(processedValue); me.value = me.multiSelect ? processedValue : processedValue[0]; if (!Ext.isDefined(me.value)) { me.value = null; } me.displayTplData = displayTplData; me.lastSelection = me.valueModels = matchedRecords; if (inputEl && me.emptyText && !Ext.isEmpty(value)) { inputEl.removeCls(me.emptyCls); } me.setRawValue(me.getDisplayValue()); me.checkChange(); if (doSelect !== false) { me.syncSelection(); } me.applyEmptyText(); return me; }, setHiddenValue: function(values){ var me = this, name = me.hiddenName, i, dom, childNodes, input, valueCount, childrenCount; if (!me.hiddenDataEl || !name) { return; } values = Ext.Array.from(values); dom = me.hiddenDataEl.dom; childNodes = dom.childNodes; input = childNodes[0]; valueCount = values.length; childrenCount = childNodes.length; if (!input && valueCount > 0) { me.hiddenDataEl.update(Ext.DomHelper.markup({ tag: 'input', type: 'hidden', name: name })); childrenCount = 1; input = dom.firstChild; } while (childrenCount > valueCount) { dom.removeChild(childNodes[0]); -- childrenCount; } while (childrenCount < valueCount) { dom.appendChild(input.cloneNode(true)); ++ childrenCount; } for (i = 0; i < valueCount; i++) { childNodes[i].value = values[i]; } }, getDisplayValue: function() { return this.displayTpl.apply(this.displayTplData); }, getValue: function() { var me = this, picker = me.picker, rawValue = me.getRawValue(), value = me.value; if (me.getDisplayValue() !== rawValue) { value = rawValue; me.value = me.displayTplData = me.valueModels = null; if (picker) { me.ignoreSelection++; picker.getSelectionModel().deselectAll(); me.ignoreSelection--; } } return value; }, getSubmitValue: function() { var value = this.getValue(); if (Ext.isEmpty(value)) { value = ''; } return value; }, isEqual: function(v1, v2) { var fromArray = Ext.Array.from, i, len; v1 = fromArray(v1); v2 = fromArray(v2); len = v1.length; if (len !== v2.length) { return false; } for(i = 0; i < len; i++) { if (v2[i] !== v1[i]) { return false; } } return true; }, clearValue: function() { this.setValue([]); }, syncSelection: function() { var me = this, picker = me.picker, selection, selModel, values = me.valueModels || [], vLen = values.length, v, value; if (picker) { selection = []; for (v = 0; v < vLen; v++) { value = values[v]; if (value && value.isModel && me.store.indexOf(value) >= 0) { selection.push(value); } } me.ignoreSelection++; selModel = picker.getSelectionModel(); selModel.deselectAll(); if (selection.length) { selModel.select(selection, undefined, true); } me.ignoreSelection--; } }, onEditorTab: function(e){ var keyNav = this.listKeyNav; if (this.selectOnTab && keyNav) { keyNav.selectHighlighted(e); } } }); Ext.define('Ext.picker.Month', { extend: Ext.Component , alias: 'widget.monthpicker', alternateClassName: 'Ext.MonthPicker', childEls: [ 'bodyEl', 'prevEl', 'nextEl', 'buttonsEl', 'monthEl', 'yearEl' ], renderTpl: [ '
', '
', '', '
', '{.}', '
', '
', '
', '
', '
', '
', '', '
', '
', '', '
', '
', '', '
', '{.}', '
', '
', '
', '
', '', '
{%', 'var me=values.$comp, okBtn=me.okBtn, cancelBtn=me.cancelBtn;', 'okBtn.ownerLayout = cancelBtn.ownerLayout = me.componentLayout;', 'okBtn.ownerCt = cancelBtn.ownerCt = me;', 'Ext.DomHelper.generateMarkup(okBtn.getRenderTree(), out);', 'Ext.DomHelper.generateMarkup(cancelBtn.getRenderTree(), out);', '%}
', '
', '
' ], okText: 'OK', cancelText: 'Cancel', baseCls: Ext.baseCSSPrefix + 'monthpicker', showButtons: true, measureWidth: 35, measureMaxHeight: 20, smallCls: Ext.baseCSSPrefix + 'monthpicker-small', totalYears: 10, yearOffset: 5, monthOffset: 6, initComponent: function(){ var me = this; me.selectedCls = me.baseCls + '-selected'; me.addEvents( 'cancelclick', 'monthclick', 'monthdblclick', 'okclick', 'select', 'yearclick', 'yeardblclick' ); if (me.small) { me.addCls(me.smallCls); } me.setValue(me.value); me.activeYear = me.getYear(new Date().getFullYear() - 4, -4); if (me.showButtons) { me.okBtn = new Ext.button.Button({ text: me.okText, handler: me.onOkClick, scope: me }); me.cancelBtn = new Ext.button.Button({ text: me.cancelText, handler: me.onCancelClick, scope: me }); } this.callParent(); }, beforeRender: function(){ var me = this, i = 0, months = [], shortName = Ext.Date.getShortMonthName, monthLen = me.monthOffset, margin = me.monthMargin, style = ''; if (me.padding && !me.width) { me.cacheWidth(); } me.callParent(); for (; i < monthLen; ++i) { months.push(shortName(i), shortName(i + monthLen)); } if (Ext.isDefined(margin)) { style = 'margin: 0 ' + margin + 'px;'; } Ext.apply(me.renderData, { months: months, years: me.getYears(), showButtons: me.showButtons, monthStyle: style }); }, cacheWidth: function() { var me = this, padding = me.parseBox(me.padding), widthEl = Ext.getBody().createChild({ cls: me.baseCls + ' ' + me.borderBoxCls, style: 'position:absolute;top:-1000px;left:-1000px;', html: ' ' }); me.self.prototype.width = widthEl.getWidth() + padding.left + padding.right; widthEl.remove(); }, afterRender: function(){ var me = this, body = me.bodyEl, buttonsEl = me.buttonsEl; me.callParent(); me.mon(body, 'click', me.onBodyClick, me); me.mon(body, 'dblclick', me.onBodyClick, me); me.years = body.select('.' + me.baseCls + '-year a'); me.months = body.select('.' + me.baseCls + '-month a'); me.backRepeater = new Ext.util.ClickRepeater(me.prevEl, { handler: Ext.Function.bind(me.adjustYear, me, [-me.totalYears]) }); me.prevEl.addClsOnOver(me.baseCls + '-yearnav-prev-over'); me.nextRepeater = new Ext.util.ClickRepeater(me.nextEl, { handler: Ext.Function.bind(me.adjustYear, me, [me.totalYears]) }); me.nextEl.addClsOnOver(me.baseCls + '-yearnav-next-over'); me.updateBody(); if (!Ext.isDefined(me.monthMargin)) { Ext.picker.Month.prototype.monthMargin = me.calculateMonthMargin(); } }, calculateMonthMargin: function(){ var me = this, monthEl = me.monthEl, months = me.months, first = months.first(), itemMargin = first.getMargin('l'); while (itemMargin && me.getLargest() > me.measureMaxHeight) { --itemMargin; months.setStyle('margin', '0 ' + itemMargin + 'px'); } return itemMargin; }, getLargest: function(months){ var largest = 0; this.months.each(function(item){ var h = item.getHeight(); if (h > largest) { largest = h; } }); return largest; }, setValue: function(value){ var me = this, active = me.activeYear, offset = me.monthOffset, year, index; if (!value) { me.value = [null, null]; } else if (Ext.isDate(value)) { me.value = [value.getMonth(), value.getFullYear()]; } else { me.value = [value[0], value[1]]; } if (me.rendered) { year = me.value[1]; if (year !== null) { if ((year < active || year > active + me.yearOffset)) { me.activeYear = year - me.yearOffset + 1; } } me.updateBody(); } return me; }, getValue: function(){ return this.value; }, hasSelection: function(){ var value = this.value; return value[0] !== null && value[1] !== null; }, getYears: function(){ var me = this, offset = me.yearOffset, start = me.activeYear, end = start + offset, i = start, years = []; for (; i < end; ++i) { years.push(i, i + offset); } return years; }, updateBody: function(){ var me = this, years = me.years, months = me.months, yearNumbers = me.getYears(), cls = me.selectedCls, value = me.getYear(null), month = me.value[0], monthOffset = me.monthOffset, year, yearItems, y, yLen, el; if (me.rendered) { years.removeCls(cls); months.removeCls(cls); yearItems = years.elements; yLen = yearItems.length; for (y = 0; y < yLen; y++) { el = Ext.fly(yearItems[y]); year = yearNumbers[y]; el.dom.innerHTML = year; if (year == value) { el.addCls(cls); } } if (month !== null) { if (month < monthOffset) { month = month * 2; } else { month = (month - monthOffset) * 2 + 1; } months.item(month).addCls(cls); } } }, getYear: function(defaultValue, offset) { var year = this.value[1]; offset = offset || 0; return year === null ? defaultValue : year + offset; }, onBodyClick: function(e, t) { var me = this, isDouble = e.type == 'dblclick'; if (e.getTarget('.' + me.baseCls + '-month')) { e.stopEvent(); me.onMonthClick(t, isDouble); } else if (e.getTarget('.' + me.baseCls + '-year')) { e.stopEvent(); me.onYearClick(t, isDouble); } }, adjustYear: function(offset){ if (typeof offset != 'number') { offset = this.totalYears; } this.activeYear += offset; this.updateBody(); }, onOkClick: function(){ this.fireEvent('okclick', this, this.value); }, onCancelClick: function(){ this.fireEvent('cancelclick', this); }, onMonthClick: function(target, isDouble){ var me = this; me.value[0] = me.resolveOffset(me.months.indexOf(target), me.monthOffset); me.updateBody(); me.fireEvent('month' + (isDouble ? 'dbl' : '') + 'click', me, me.value); me.fireEvent('select', me, me.value); }, onYearClick: function(target, isDouble){ var me = this; me.value[1] = me.activeYear + me.resolveOffset(me.years.indexOf(target), me.yearOffset); me.updateBody(); me.fireEvent('year' + (isDouble ? 'dbl' : '') + 'click', me, me.value); me.fireEvent('select', me, me.value); }, resolveOffset: function(index, offset){ if (index % 2 === 0) { return (index / 2); } else { return offset + Math.floor(index / 2); } }, beforeDestroy: function(){ var me = this; me.years = me.months = null; Ext.destroyMembers(me, 'backRepeater', 'nextRepeater', 'okBtn', 'cancelBtn'); me.callParent(); }, finishRenderChildren: function () { var me = this; this.callParent(arguments); if (this.showButtons) { me.okBtn.finishRender(); me.cancelBtn.finishRender(); } }, onDestroy: function() { Ext.destroyMembers(this, 'okBtn', 'cancelBtn'); this.callParent(); } }); Ext.define('Ext.picker.Date', { extend: Ext.Component , alias: 'widget.datepicker', alternateClassName: 'Ext.DatePicker', childEls: [ 'innerEl', 'eventEl', 'prevEl', 'nextEl', 'middleBtnEl', 'footerEl' ], border: true, renderTpl: [ '
', '', '', '', '', '', '', '', '', '', '{#:this.isEndOfWeek}', '', '', '', '
', '
{.:this.firstInitial}
', '
', '', '
', '', '', '', '
', { firstInitial: function(value) { return Ext.picker.Date.prototype.getDayInitial(value); }, isEndOfWeek: function(value) { value--; var end = value % 7 === 0 && value !== 0; return end ? '' : ''; }, renderTodayBtn: function(values, out) { Ext.DomHelper.generateMarkup(values.$comp.todayBtn.getRenderTree(), out); }, renderMonthBtn: function(values, out) { Ext.DomHelper.generateMarkup(values.$comp.monthBtn.getRenderTree(), out); } } ], todayText : 'Today', ariaTitle: 'Date Picker: {0}', ariaTitleDateFormat: 'F d, Y', todayTip : '{0} (Spacebar)', minText : 'This date is before the minimum date', maxText : 'This date is after the maximum date', disabledDaysText : 'Disabled', disabledDatesText : 'Disabled', nextText : 'Next Month (Control+Right)', prevText : 'Previous Month (Control+Left)', monthYearText : 'Choose a month (Control+Up/Down to move years)', monthYearFormat: 'F Y', startDay : 0, showToday : true, disableAnim: false, baseCls: Ext.baseCSSPrefix + 'datepicker', longDayFormat: 'F d, Y', focusOnShow: false, focusOnSelect: true, initHour: 12, numDays: 42, initComponent : function() { var me = this, clearTime = Ext.Date.clearTime; me.selectedCls = me.baseCls + '-selected'; me.disabledCellCls = me.baseCls + '-disabled'; me.prevCls = me.baseCls + '-prevday'; me.activeCls = me.baseCls + '-active'; me.cellCls = me.baseCls + '-cell'; me.nextCls = me.baseCls + '-prevday'; me.todayCls = me.baseCls + '-today'; if (!me.format) { me.format = Ext.Date.defaultFormat; } if (!me.dayNames) { me.dayNames = Ext.Date.dayNames; } me.dayNames = me.dayNames.slice(me.startDay).concat(me.dayNames.slice(0, me.startDay)); me.callParent(); me.value = me.value ? clearTime(me.value, true) : clearTime(new Date()); me.addEvents( 'select' ); me.initDisabledDays(); }, beforeRender: function () { var me = this, days = new Array(me.numDays), today = Ext.Date.format(new Date(), me.format); if (me.up('menu')) { me.addCls(Ext.baseCSSPrefix + 'menu'); } if (me.padding && !me.width) { me.cacheWidth(); } me.monthBtn = new Ext.button.Split({ ownerCt: me, ownerLayout: me.getComponentLayout(), text: '', tooltip: me.monthYearText, listeners: { click: me.doShowMonthPicker, arrowclick: me.doShowMonthPicker, scope: me } }); if (me.showToday) { me.todayBtn = new Ext.button.Button({ ownerCt: me, ownerLayout: me.getComponentLayout(), text: Ext.String.format(me.todayText, today), tooltip: Ext.String.format(me.todayTip, today), tooltipType: 'title', handler: me.selectToday, scope: me }); } me.callParent(); Ext.applyIf(me, { renderData: {} }); Ext.apply(me.renderData, { dayNames: me.dayNames, showToday: me.showToday, prevText: me.prevText, nextText: me.nextText, days: days }); me.protoEl.unselectable(); }, cacheWidth: function() { var me = this, padding = me.parseBox(me.padding), widthEl = Ext.getBody().createChild({ cls: me.baseCls + ' ' + me.borderBoxCls, style: 'position:absolute;top:-1000px;left:-1000px;' }); me.self.prototype.width = widthEl.getWidth() + padding.left + padding.right; widthEl.remove(); }, finishRenderChildren: function () { var me = this; me.callParent(); me.monthBtn.finishRender(); if (me.showToday) { me.todayBtn.finishRender(); } }, onRender : function(container, position){ var me = this; me.callParent(arguments); me.cells = me.eventEl.select('tbody td'); me.textNodes = me.eventEl.query('tbody td a'); me.mon(me.eventEl, { scope: me, mousewheel: me.handleMouseWheel, click: { fn: me.handleDateClick, delegate: 'a.' + me.baseCls + '-date' } }); }, initEvents: function(){ var me = this, eDate = Ext.Date, day = eDate.DAY; me.callParent(); me.prevRepeater = new Ext.util.ClickRepeater(me.prevEl, { handler: me.showPrevMonth, scope: me, preventDefault: true, stopDefault: true }); me.nextRepeater = new Ext.util.ClickRepeater(me.nextEl, { handler: me.showNextMonth, scope: me, preventDefault:true, stopDefault:true }); me.keyNav = new Ext.util.KeyNav(me.eventEl, Ext.apply({ scope: me, left : function(e){ if(e.ctrlKey){ me.showPrevMonth(); }else{ me.update(eDate.add(me.activeDate, day, -1)); } }, right : function(e){ if(e.ctrlKey){ me.showNextMonth(); }else{ me.update(eDate.add(me.activeDate, day, 1)); } }, up : function(e){ if(e.ctrlKey){ me.showNextYear(); }else{ me.update(eDate.add(me.activeDate, day, -7)); } }, down : function(e){ if(e.ctrlKey){ me.showPrevYear(); }else{ me.update(eDate.add(me.activeDate, day, 7)); } }, pageUp:function (e) { if (e.altKey) { me.showPrevYear(); } else { me.showPrevMonth(); } }, pageDown:function (e) { if (e.altKey) { me.showNextYear(); } else { me.showNextMonth(); } }, tab:function (e) { me.doCancelFieldFocus = true; me.handleTabClick(e); delete me.doCancelFieldFocus; return true; }, enter : function(e){ e.stopPropagation(); return true; }, home:function (e) { me.update(eDate.getFirstDateOfMonth(me.activeDate)); }, end:function (e) { me.update(eDate.getLastDateOfMonth(me.activeDate)); } }, me.keyNavConfig)); if (me.showToday) { me.todayKeyListener = me.eventEl.addKeyListener(Ext.EventObject.SPACE, me.selectToday, me); } me.update(me.value); }, handleTabClick:function (e) { var me = this, t = me.getSelectedDate(me.activeDate), handler = me.handler; if (!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)) { me.doCancelFocus = me.focusOnSelect === false; me.setValue(new Date(t.dateValue)); delete me.doCancelFocus; me.fireEvent('select', me, me.value); if (handler) { handler.call(me.scope || me, me, me.value); } me.onSelect(); } }, getSelectedDate:function (date) { var me = this, t = date.getTime(), cells = me.cells, cls = me.selectedCls, cellItems = cells.elements, c, cLen = cellItems.length, cell; cells.removeCls(cls); for (c = 0; c < cLen; c++) { cell = Ext.fly(cellItems[c]); if (cell.dom.firstChild.dateValue == t) { return cell.dom.firstChild; } } return null; }, initDisabledDays : function(){ var me = this, dd = me.disabledDates, re = '(?:', len, d, dLen, dI; if(!me.disabledDatesRE && dd){ len = dd.length - 1; dLen = dd.length; for (d = 0; d < dLen; d++) { dI = dd[d]; re += Ext.isDate(dI) ? '^' + Ext.String.escapeRegex(Ext.Date.dateFormat(dI, me.format)) + '$' : dI; if (d != len) { re += '|'; } } me.disabledDatesRE = new RegExp(re + ')'); } }, setDisabledDates : function(dd){ var me = this; if(Ext.isArray(dd)){ me.disabledDates = dd; me.disabledDatesRE = null; }else{ me.disabledDatesRE = dd; } me.initDisabledDays(); me.update(me.value, true); return me; }, setDisabledDays : function(dd){ this.disabledDays = dd; return this.update(this.value, true); }, setMinDate : function(dt){ this.minDate = dt; return this.update(this.value, true); }, setMaxDate : function(dt){ this.maxDate = dt; return this.update(this.value, true); }, setValue : function(value){ this.value = Ext.Date.clearTime(value, true); return this.update(this.value); }, getValue : function(){ return this.value; }, getDayInitial: function(value){ return value.substr(0,1); }, focus : function(){ this.update(this.activeDate); }, onEnable: function(){ this.callParent(); this.setDisabledStatus(false); this.update(this.activeDate); }, onDisable : function(){ this.callParent(); this.setDisabledStatus(true); }, setDisabledStatus : function(disabled){ var me = this; me.keyNav.setDisabled(disabled); me.prevRepeater.setDisabled(disabled); me.nextRepeater.setDisabled(disabled); if (me.showToday) { me.todayKeyListener.setDisabled(disabled); me.todayBtn.setDisabled(disabled); } }, getActive: function(){ return this.activeDate || this.value; }, runAnimation: function(isHide){ var picker = this.monthPicker, options = { duration: 200, callback: function(){ if (isHide) { picker.hide(); } else { picker.show(); } } }; if (isHide) { picker.el.slideOut('t', options); } else { picker.el.slideIn('t', options); } }, hideMonthPicker : function(animate){ var me = this, picker = me.monthPicker; if (picker) { if (me.shouldAnimate(animate)) { me.runAnimation(true); } else { picker.hide(); } } return me; }, doShowMonthPicker: function(){ this.showMonthPicker(); }, showMonthPicker : function(animate){ var me = this, el = me.el, picker; if (me.rendered && !me.disabled) { picker = me.createMonthPicker(); picker.setValue(me.getActive()); picker.setSize(el.getSize()); picker.setPosition(-el.getBorderWidth('l'), -el.getBorderWidth('t')); if (me.shouldAnimate(animate)) { me.runAnimation(false); } else { picker.show(); } } return me; }, shouldAnimate: function(animate){ return Ext.isDefined(animate) ? animate : !this.disableAnim; }, createMonthPicker: function(){ var me = this, picker = me.monthPicker; if (!picker) { me.monthPicker = picker = new Ext.picker.Month({ renderTo: me.el, floating: true, padding: me.padding, shadow: false, small: me.showToday === false, listeners: { scope: me, cancelclick: me.onCancelClick, okclick: me.onOkClick, yeardblclick: me.onOkClick, monthdblclick: me.onOkClick } }); if (!me.disableAnim) { picker.el.setStyle('display', 'none'); } me.on('beforehide', Ext.Function.bind(me.hideMonthPicker, me, [false])); } return picker; }, onOkClick: function(picker, value){ var me = this, month = value[0], year = value[1], date = new Date(year, month, me.getActive().getDate()); if (date.getMonth() !== month) { date = Ext.Date.getLastDateOfMonth(new Date(year, month, 1)); } me.setValue(date); me.hideMonthPicker(); }, onCancelClick: function(){ this.selectedUpdate(this.activeDate); this.hideMonthPicker(); }, showPrevMonth : function(e){ return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.MONTH, -1)); }, showNextMonth : function(e){ return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.MONTH, 1)); }, showPrevYear : function(){ return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.YEAR, -1)); }, showNextYear : function(){ return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.YEAR, 1)); }, handleMouseWheel : function(e){ e.stopEvent(); if(!this.disabled){ var delta = e.getWheelDelta(); if(delta > 0){ this.showPrevMonth(); } else if(delta < 0){ this.showNextMonth(); } } }, handleDateClick : function(e, t){ var me = this, handler = me.handler; e.stopEvent(); if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)){ me.doCancelFocus = me.focusOnSelect === false; me.setValue(new Date(t.dateValue)); delete me.doCancelFocus; me.fireEvent('select', me, me.value); if (handler) { handler.call(me.scope || me, me, me.value); } me.onSelect(); } }, onSelect: function() { if (this.hideOnSelect) { this.hide(); } }, selectToday : function(){ var me = this, btn = me.todayBtn, handler = me.handler; if(btn && !btn.disabled){ me.setValue(Ext.Date.clearTime(new Date())); me.fireEvent('select', me, me.value); if (handler) { handler.call(me.scope || me, me, me.value); } me.onSelect(); } return me; }, selectedUpdate: function(date){ var me = this, t = date.getTime(), cells = me.cells, cls = me.selectedCls, cellItems = cells.elements, c, cLen = cellItems.length, cell; cells.removeCls(cls); for (c = 0; c < cLen; c++) { cell = Ext.fly(cellItems[c]); if (cell.dom.firstChild.dateValue == t) { me.fireEvent('highlightitem', me, cell); cell.addCls(cls); if(me.isVisible() && !me.doCancelFocus){ Ext.fly(cell.dom.firstChild).focus(50); } break; } } }, fullUpdate: function(date){ var me = this, cells = me.cells.elements, textNodes = me.textNodes, disabledCls = me.disabledCellCls, eDate = Ext.Date, i = 0, extraDays = 0, visible = me.isVisible(), newDate = +eDate.clearTime(date, true), today = +eDate.clearTime(new Date()), min = me.minDate ? eDate.clearTime(me.minDate, true) : Number.NEGATIVE_INFINITY, max = me.maxDate ? eDate.clearTime(me.maxDate, true) : Number.POSITIVE_INFINITY, ddMatch = me.disabledDatesRE, ddText = me.disabledDatesText, ddays = me.disabledDays ? me.disabledDays.join('') : false, ddaysText = me.disabledDaysText, format = me.format, days = eDate.getDaysInMonth(date), firstOfMonth = eDate.getFirstDateOfMonth(date), startingPos = firstOfMonth.getDay() - me.startDay, previousMonth = eDate.add(date, eDate.MONTH, -1), longDayFormat = me.longDayFormat, prevStart, current, disableToday, tempDate, setCellClass, html, cls, formatValue, value; if (startingPos < 0) { startingPos += 7; } days += startingPos; prevStart = eDate.getDaysInMonth(previousMonth) - startingPos; current = new Date(previousMonth.getFullYear(), previousMonth.getMonth(), prevStart, me.initHour); if (me.showToday) { tempDate = eDate.clearTime(new Date()); disableToday = (tempDate < min || tempDate > max || (ddMatch && format && ddMatch.test(eDate.dateFormat(tempDate, format))) || (ddays && ddays.indexOf(tempDate.getDay()) != -1)); if (!me.disabled) { me.todayBtn.setDisabled(disableToday); me.todayKeyListener.setDisabled(disableToday); } } setCellClass = function(cell, cls){ value = +eDate.clearTime(current, true); cell.title = eDate.format(current, longDayFormat); cell.firstChild.dateValue = value; if(value == today){ cls += ' ' + me.todayCls; cell.title = me.todayText; me.todayElSpan = Ext.DomHelper.append(cell.firstChild, { tag:'span', cls: Ext.baseCSSPrefix + 'hide-clip', html:me.todayText }, true); } if(value == newDate) { cls += ' ' + me.selectedCls; me.fireEvent('highlightitem', me, cell); if (visible && me.floating) { Ext.fly(cell.firstChild).focus(50); } } if (value < min) { cls += ' ' + disabledCls; cell.title = me.minText; } else if (value > max) { cls += ' ' + disabledCls; cell.title = me.maxText; } else if (ddays && ddays.indexOf(current.getDay()) !== -1){ cell.title = ddaysText; cls += ' ' + disabledCls; } else if (ddMatch && format){ formatValue = eDate.dateFormat(current, format); if(ddMatch.test(formatValue)){ cell.title = ddText.replace('%0', formatValue); cls += ' ' + disabledCls; } } cell.className = cls + ' ' + me.cellCls; }; for(; i < me.numDays; ++i) { if (i < startingPos) { html = (++prevStart); cls = me.prevCls; } else if (i >= days) { html = (++extraDays); cls = me.nextCls; } else { html = i - startingPos + 1; cls = me.activeCls; } textNodes[i].innerHTML = html; current.setDate(current.getDate() + 1); setCellClass(cells[i], cls); } me.monthBtn.setText(Ext.Date.format(date, me.monthYearFormat)); }, update : function(date, forceRefresh){ var me = this, active = me.activeDate; if (me.rendered) { me.activeDate = date; if(!forceRefresh && active && me.el && active.getMonth() == date.getMonth() && active.getFullYear() == date.getFullYear()){ me.selectedUpdate(date, active); } else { me.fullUpdate(date, active); } } return me; }, beforeDestroy : function() { var me = this; if (me.rendered) { Ext.destroy( me.todayKeyListener, me.keyNav, me.monthPicker, me.monthBtn, me.nextRepeater, me.prevRepeater, me.todayBtn ); delete me.textNodes; delete me.cells.elements; } me.callParent(); }, onShow: function() { this.callParent(arguments); if (this.focusOnShow) { this.focus(); } } }); Ext.define('Ext.form.field.Date', { extend: Ext.form.field.Picker , alias: 'widget.datefield', alternateClassName: ['Ext.form.DateField', 'Ext.form.Date'], format : "m/d/Y", altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j", disabledDaysText : "Disabled", disabledDatesText : "Disabled", minText : "The date in this field must be equal to or after {0}", maxText : "The date in this field must be equal to or before {0}", invalidText : "{0} is not a valid date - it must be in the format {1}", triggerCls : Ext.baseCSSPrefix + 'form-date-trigger', showToday : true, useStrict: undefined, initTime: '12', initTimeFormat: 'H', matchFieldWidth: false, startDay: 0, initComponent : function(){ var me = this, isString = Ext.isString, min, max; min = me.minValue; max = me.maxValue; if(isString(min)){ me.minValue = me.parseDate(min); } if(isString(max)){ me.maxValue = me.parseDate(max); } me.disabledDatesRE = null; me.initDisabledDays(); me.callParent(); }, initValue: function() { var me = this, value = me.value; if (Ext.isString(value)) { me.value = me.rawToValue(value); } me.callParent(); }, initDisabledDays : function(){ if(this.disabledDates){ var dd = this.disabledDates, len = dd.length - 1, re = "(?:", d, dLen = dd.length, date; for (d = 0; d < dLen; d++) { date = dd[d]; re += Ext.isDate(date) ? '^' + Ext.String.escapeRegex(date.dateFormat(this.format)) + '$' : date; if (d !== len) { re += '|'; } } this.disabledDatesRE = new RegExp(re + ')'); } }, setDisabledDates : function(dd){ var me = this, picker = me.picker; me.disabledDates = dd; me.initDisabledDays(); if (picker) { picker.setDisabledDates(me.disabledDatesRE); } }, setDisabledDays : function(dd){ var picker = this.picker; this.disabledDays = dd; if (picker) { picker.setDisabledDays(dd); } }, setMinValue : function(dt){ var me = this, picker = me.picker, minValue = (Ext.isString(dt) ? me.parseDate(dt) : dt); me.minValue = minValue; if (picker) { picker.minText = Ext.String.format(me.minText, me.formatDate(me.minValue)); picker.setMinDate(minValue); } }, setMaxValue : function(dt){ var me = this, picker = me.picker, maxValue = (Ext.isString(dt) ? me.parseDate(dt) : dt); me.maxValue = maxValue; if (picker) { picker.maxText = Ext.String.format(me.maxText, me.formatDate(me.maxValue)); picker.setMaxDate(maxValue); } }, getErrors: function(value) { var me = this, format = Ext.String.format, clearTime = Ext.Date.clearTime, errors = me.callParent(arguments), disabledDays = me.disabledDays, disabledDatesRE = me.disabledDatesRE, minValue = me.minValue, maxValue = me.maxValue, len = disabledDays ? disabledDays.length : 0, i = 0, svalue, fvalue, day, time; value = me.formatDate(value || me.processRawValue(me.getRawValue())); if (value === null || value.length < 1) { return errors; } svalue = value; value = me.parseDate(value); if (!value) { errors.push(format(me.invalidText, svalue, Ext.Date.unescapeFormat(me.format))); return errors; } time = value.getTime(); if (minValue && time < clearTime(minValue).getTime()) { errors.push(format(me.minText, me.formatDate(minValue))); } if (maxValue && time > clearTime(maxValue).getTime()) { errors.push(format(me.maxText, me.formatDate(maxValue))); } if (disabledDays) { day = value.getDay(); for(; i < len; i++) { if (day === disabledDays[i]) { errors.push(me.disabledDaysText); break; } } } fvalue = me.formatDate(value); if (disabledDatesRE && disabledDatesRE.test(fvalue)) { errors.push(format(me.disabledDatesText, fvalue)); } return errors; }, rawToValue: function(rawValue) { return this.parseDate(rawValue) || rawValue || null; }, valueToRaw: function(value) { return this.formatDate(this.parseDate(value)); }, safeParse : function(value, format) { var me = this, utilDate = Ext.Date, result = null, strict = me.useStrict, parsedDate; if (utilDate.formatContainsHourInfo(format)) { result = utilDate.parse(value, format, strict); } else { parsedDate = utilDate.parse(value + ' ' + me.initTime, format + ' ' + me.initTimeFormat, strict); if (parsedDate) { result = utilDate.clearTime(parsedDate); } } return result; }, getSubmitValue: function() { var format = this.submitFormat || this.format, value = this.getValue(); return value ? Ext.Date.format(value, format) : ''; }, parseDate : function(value) { if(!value || Ext.isDate(value)){ return value; } var me = this, val = me.safeParse(value, me.format), altFormats = me.altFormats, altFormatsArray = me.altFormatsArray, i = 0, len; if (!val && altFormats) { altFormatsArray = altFormatsArray || altFormats.split('|'); len = altFormatsArray.length; for (; i < len && !val; ++i) { val = me.safeParse(value, altFormatsArray[i]); } } return val; }, formatDate : function(date){ return Ext.isDate(date) ? Ext.Date.dateFormat(date, this.format) : date; }, createPicker: function() { var me = this, format = Ext.String.format; return new Ext.picker.Date({ pickerField: me, ownerCt: me.ownerCt, renderTo: document.body, floating: true, hidden: true, focusOnShow: true, minDate: me.minValue, maxDate: me.maxValue, disabledDatesRE: me.disabledDatesRE, disabledDatesText: me.disabledDatesText, disabledDays: me.disabledDays, disabledDaysText: me.disabledDaysText, format: me.format, showToday: me.showToday, startDay: me.startDay, minText: format(me.minText, me.formatDate(me.minValue)), maxText: format(me.maxText, me.formatDate(me.maxValue)), listeners: { scope: me, select: me.onSelect }, keyNavConfig: { esc: function() { me.collapse(); } } }); }, onDownArrow: function(e) { this.callParent(arguments); if (this.isExpanded) { this.getPicker().focus(); } }, onSelect: function(m, d) { var me = this; me.setValue(d); me.fireEvent('select', me, d); me.collapse(); }, onExpand: function() { var value = this.getValue(); this.picker.setValue(Ext.isDate(value) ? value : new Date()); }, onCollapse: function() { this.focus(false, 60); }, beforeBlur : function(){ var me = this, v = me.parseDate(me.getRawValue()), focusTask = me.focusTask; if (focusTask) { focusTask.cancel(); } if (v) { me.setValue(v); } } }); Ext.define('Ext.form.field.FileButton', { extend: Ext.button.Button , alias: 'widget.filebutton', childEls: [ 'btnEl', 'btnWrap', 'btnInnerEl', 'btnIconEl', 'fileInputEl' ], inputCls: Ext.baseCSSPrefix + 'form-file-input', cls: Ext.baseCSSPrefix + 'form-file-btn', preventDefault: false, renderTpl: [ ' {splitCls}', '{childElCls}" unselectable="on">', '', '', '{text}', '', 'background-image:url({iconUrl});', 'font-family:{glyphFontFamily};">', '&#{glyph}; ', '', '', '', '' ], getTemplateArgs: function(){ var args = this.callParent(); args.inputCls = this.inputCls; args.inputName = this.inputName; return args; }, afterRender: function(){ var me = this; me.callParent(arguments); me.fileInputEl.on('change', me.fireChange, me); }, fireChange: function(e){ this.fireEvent('change', this, e, this.fileInputEl.dom.value); }, createFileInput : function(isTemporary) { var me = this; me.fileInputEl = me.el.createChild({ name: me.inputName, id: !isTemporary ? me.id + '-fileInputEl' : undefined, cls: me.inputCls, tag: 'input', type: 'file', size: 1 }); me.fileInputEl.on('change', me.fireChange, me); }, reset: function(remove){ if (remove) { this.fileInputEl.remove(); } this.createFileInput(!remove); }, restoreInput: function(el){ this.fileInputEl.remove(); el = Ext.get(el); this.el.appendChild(el); this.fileInputEl = el; }, onDisable: function(){ this.callParent(); this.fileInputEl.dom.disabled = true; }, onEnable : function() { this.callParent(); this.fileInputEl.dom.disabled = false; } }); Ext.define('Ext.form.field.File', { extend: Ext.form.field.Trigger , alias: ['widget.filefield', 'widget.fileuploadfield'], alternateClassName: ['Ext.form.FileUploadField', 'Ext.ux.form.FileUploadField', 'Ext.form.File'], buttonText: 'Browse...', buttonOnly: false, buttonMargin: 3, clearOnSubmit: true, extraFieldBodyCls: Ext.baseCSSPrefix + 'form-file-wrap', readOnly: true, submitValue: false, triggerNoEditCls: '', componentLayout: 'triggerfield', childEls: ['browseButtonWrap'], onRender: function() { var me = this, id = me.id, inputEl; me.callParent(arguments); inputEl = me.inputEl; inputEl.dom.name = ''; me.button = new Ext.form.field.FileButton(Ext.apply({ renderTo: id + '-browseButtonWrap', ownerCt: me, ownerLayout: me.componentLayout, id: id + '-button', ui: me.ui, disabled: me.disabled, text: me.buttonText, style: me.buttonOnly ? '' : me.getButtonMarginProp() + me.buttonMargin + 'px', inputName: me.getName(), listeners: { scope: me, change: me.onFileChange } }, me.buttonConfig)); me.fileInputEl = me.button.fileInputEl; if (me.buttonOnly) { me.inputCell.setDisplayed(false); } me.browseButtonWrap.dom.style.width = (me.browseButtonWrap.dom.lastChild.offsetWidth + me.button.getEl().getMargin('lr')) + 'px'; if (Ext.isIE) { me.button.getEl().repaint(); } }, getTriggerMarkup: function() { return ''; }, onFileChange: function(button, e, value) { this.duringFileSelect = true; Ext.form.field.File.superclass.setValue.call(this, value); delete this.duringFileSelect; }, didValueChange: function(){ return !!this.duringFileSelect; }, setValue: Ext.emptyFn, reset : function(){ var me = this, clear = me.clearOnSubmit; if (me.rendered) { me.button.reset(clear); me.fileInputEl = me.button.fileInputEl; if (clear) { me.inputEl.dom.value = ''; Ext.form.field.File.superclass.setValue.call(this, null); } } me.callParent(); }, onShow: function(){ this.callParent(); this.button.updateLayout(); }, onDisable: function(){ this.callParent(); this.button.disable(); }, onEnable: function(){ this.callParent(); this.button.enable(); }, isFileUpload: function() { return true; }, extractFileInput: function() { var me = this, fileInput; if (me.rendered) { fileInput = me.button.fileInputEl.dom; me.reset(); } else { fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.className = Ext.baseCSSPrefix + 'hide-display'; fileInput.name = me.getName(); } return fileInput; }, restoreInput: function(el) { if (this.rendered) { var button = this.button; button.restoreInput(el); this.fileInputEl = button.fileInputEl; } }, onDestroy: function(){ Ext.destroyMembers(this, 'button'); delete this.fileInputEl; this.callParent(); }, getButtonMarginProp: function() { return 'margin-left:'; } }); Ext.define('Ext.form.field.Hidden', { extend: Ext.form.field.Base , alias: ['widget.hiddenfield', 'widget.hidden'], alternateClassName: 'Ext.form.Hidden', inputType : 'hidden', hideLabel: true, hidden: true, ariaRole: 'presentation', initComponent: function() { this.formItemCls += '-hidden'; this.callParent(); }, isEqual: function(value1, value2) { return this.isEqualAsString(value1, value2); }, initEvents: Ext.emptyFn, setSize : Ext.emptyFn, setWidth : Ext.emptyFn, setHeight : Ext.emptyFn, setPosition : Ext.emptyFn, setPagePosition : Ext.emptyFn, markInvalid : Ext.emptyFn, clearInvalid : Ext.emptyFn }); Ext.define('Ext.picker.Color', { extend: Ext.Component , alias: 'widget.colorpicker', alternateClassName: 'Ext.ColorPalette', componentCls : Ext.baseCSSPrefix + 'color-picker', selectedCls: Ext.baseCSSPrefix + 'color-picker-selected', itemCls: Ext.baseCSSPrefix + 'color-picker-item', value : null, clickEvent :'click', allowReselect : false, colors : [ '000000', '993300', '333300', '003300', '003366', '000080', '333399', '333333', '800000', 'FF6600', '808000', '008000', '008080', '0000FF', '666699', '808080', 'FF0000', 'FF9900', '99CC00', '339966', '33CCCC', '3366FF', '800080', '969696', 'FF00FF', 'FFCC00', 'FFFF00', '00FF00', '00FFFF', '00CCFF', '993366', 'C0C0C0', 'FF99CC', 'FFCC99', 'FFFF99', 'CCFFCC', 'CCFFFF', '99CCFF', 'CC99FF', 'FFFFFF' ], colorRe: /(?:^|\s)color-(.{6})(?:\s|$)/, renderTpl: [ '', '', ' ', '', '' ], initComponent : function(){ var me = this; me.callParent(arguments); me.addEvents( 'select' ); if (me.handler) { me.on('select', me.handler, me.scope, true); } }, initRenderData : function(){ var me = this; return Ext.apply(me.callParent(), { itemCls: me.itemCls, colors: me.colors }); }, onRender : function(){ var me = this, clickEvent = me.clickEvent; me.callParent(arguments); me.mon(me.el, clickEvent, me.handleClick, me, {delegate: 'a'}); if(clickEvent != 'click'){ me.mon(me.el, 'click', Ext.emptyFn, me, {delegate: 'a', stopEvent: true}); } }, afterRender : function(){ var me = this, value; me.callParent(arguments); if (me.value) { value = me.value; me.value = null; me.select(value, true); } }, handleClick : function(event, target){ var me = this, color; event.stopEvent(); if (!me.disabled) { color = target.className.match(me.colorRe)[1]; me.select(color.toUpperCase()); } }, select : function(color, suppressEvent){ var me = this, selectedCls = me.selectedCls, value = me.value, el; color = color.replace('#', ''); if (!me.rendered) { me.value = color; return; } if (color != value || me.allowReselect) { el = me.el; if (me.value) { el.down('a.color-' + value).removeCls(selectedCls); } el.down('a.color-' + color).addCls(selectedCls); me.value = color; if (suppressEvent !== true) { me.fireEvent('select', me, color); } } }, clear: function(){ var me = this, value = me.value, el; if (value && me.rendered) { el = me.el.down('a.color-' + value); el.removeCls(me.selectedCls); } me.value = null; }, getValue: function(){ return this.value || null; } }); Ext.define('Ext.layout.component.field.HtmlEditor', { extend: Ext.layout.component.field.FieldContainer , alias: ['layout.htmleditor'], type: 'htmleditor', naturalHeight: 150, naturalWidth: 300, beginLayout: function(ownerContext) { var owner = this.owner, dom; if (Ext.isGecko) { dom = owner.textareaEl.dom; this.lastValue = dom.value; dom.value = ''; } this.callParent(arguments); ownerContext.toolbarContext = ownerContext.context.getCmp(owner.toolbar); ownerContext.inputCmpContext = ownerContext.context.getCmp(owner.inputCmp); ownerContext.textAreaContext = ownerContext.getEl('textareaEl'); ownerContext.iframeContext = ownerContext.getEl('iframeEl'); }, beginLayoutCycle: function(ownerContext) { var me = this, widthModel = ownerContext.widthModel, heightModel = ownerContext.heightModel, owner = me.owner, iframeEl = owner.iframeEl, textareaEl = owner.textareaEl; me.callParent(arguments); if (widthModel.shrinkWrap) { iframeEl.setStyle('width', ''); textareaEl.setStyle('width', ''); } else if (widthModel.natural) { ownerContext.bodyCellContext.setWidth(me.naturalWidth); } if (heightModel.natural || heightModel.shrinkWrap) { iframeEl.setHeight(me.naturalHeight); textareaEl.setHeight(me.naturalHeight); } }, finishedLayout: function(){ var owner = this.owner; this.callParent(arguments); if (Ext.isIE9m && Ext.isIEQuirks) { owner.el.repaint(); } if (Ext.isGecko) { owner.textareaEl.dom.value = this.lastValue; } }, publishOwnerWidth: function(ownerContext, width){ this.callParent(arguments); width -= ownerContext.inputCmpContext.getBorderInfo().width; ownerContext.textAreaContext.setWidth(width); ownerContext.iframeContext.setWidth(width); }, publishInnerWidth: function(ownerContext, width){ var border = ownerContext.inputCmpContext.getBorderInfo().width, ieBug = Ext.isStrict && Ext.isIE8m, natural = ownerContext.widthModel.natural; this.callParent(arguments); width = ownerContext.bodyCellContext.props.width - border; if (natural) { if (ieBug) { width -= 2; } ownerContext.textAreaContext.setWidth(width); ownerContext.iframeContext.setWidth(width); } else if (ieBug) { ownerContext.textAreaContext.setWidth(width); } }, publishInnerHeight: function (ownerContext, height) { var toolbarHeight = ownerContext.toolbarContext.getProp('height'), sourceEdit = this.owner.sourceEditMode; this.callParent(arguments); height = ownerContext.bodyCellContext.props.height; if (toolbarHeight !== undefined) { height -= toolbarHeight + ownerContext.inputCmpContext.getFrameInfo().height; if (Ext.isIE8 && Ext.isStrict) { height -= 2; } else if (Ext.isIEQuirks && (Ext.isIE8 || Ext.isIE9)) { height -= 4; } ownerContext.iframeContext.setHeight(height); ownerContext.textAreaContext.setHeight(height); } else { this.done = false; } } }); Ext.define('Ext.form.field.HtmlEditor', { extend: Ext.form.FieldContainer , mixins: { field: Ext.form.field.Field }, alias: 'widget.htmleditor', alternateClassName: 'Ext.form.HtmlEditor', componentLayout: 'htmleditor', componentTpl: [ '{beforeTextAreaTpl}', '', '{afterTextAreaTpl}', '{beforeIFrameTpl}', '', '{afterIFrameTpl}', { disableFormats: true } ], stretchInputElFixed: true, subTplInsertions: [ 'beforeTextAreaTpl', 'afterTextAreaTpl', 'beforeIFrameTpl', 'afterIFrameTpl', 'iframeAttrTpl', 'inputAttrTpl' ], enableFormat: true, enableFontSize: true, enableColors: true, enableAlignments: true, enableLists: true, enableSourceEdit: true, enableLinks: true, enableFont: true, createLinkText: 'Please enter the URL for the link:', defaultLinkValue: 'http:/'+'/', fontFamilies: [ 'Arial', 'Courier New', 'Tahoma', 'Times New Roman', 'Verdana' ], defaultValue: (Ext.isOpera || Ext.isIE6) ? ' ' : '​', extraFieldBodyCls: Ext.baseCSSPrefix + 'html-editor-wrap', initialized: false, activated: false, sourceEditMode: false, iframePad:3, hideMode:'offsets', maskOnDisable: true, containerElCls: Ext.baseCSSPrefix + 'html-editor-container', reStripQuotes: /^['"]*|['"]*$/g, // @private initComponent: function(){ var me = this; me.addEvents( /** * @event initialize * Fires when the editor is fully initialized (including the iframe) * @param {Ext.form.field.HtmlEditor} this */ 'initialize', /** * @event activate * Fires when the editor is first receives the focus. Any insertion must wait until after this event. * @param {Ext.form.field.HtmlEditor} this */ 'activate', /** * @event beforesync * Fires before the textarea is updated with content from the editor iframe. Return false to cancel the * sync. * @param {Ext.form.field.HtmlEditor} this * @param {String} html */ 'beforesync', /** * @event beforepush * Fires before the iframe editor is updated with content from the textarea. Return false to cancel the * push. * @param {Ext.form.field.HtmlEditor} this * @param {String} html */ 'beforepush', /** * @event sync * Fires when the textarea is updated with content from the editor iframe. * @param {Ext.form.field.HtmlEditor} this * @param {String} html */ 'sync', /** * @event push * Fires when the iframe editor is updated with content from the textarea. * @param {Ext.form.field.HtmlEditor} this * @param {String} html */ 'push', /** * @event editmodechange * Fires when the editor switches edit modes * @param {Ext.form.field.HtmlEditor} this * @param {Boolean} sourceEdit True if source edit, false if standard editing. */ 'editmodechange' ); me.items = [me.createToolbar(), me.createInputCmp()]; me.layout = { type: 'vbox', align: 'stretch' }; me.callParent(arguments); me.initField(); }, createInputCmp: function(){ this.inputCmp = Ext.widget(this.getInputCmpCfg()); return this.inputCmp; }, getInputCmpCfg: function(){ var me = this, id = me.id + '-inputCmp', data = { id : id, name : me.name, textareaCls : Ext.baseCSSPrefix + 'hidden', value : me.value, iframeName : Ext.id(), iframeSrc : Ext.SSL_SECURE_URL, iframeCls : Ext.baseCSSPrefix + 'htmleditor-iframe' }; me.getInsertionRenderData(data, me.subTplInsertions); return { flex: 1, xtype: 'component', tpl: me.getTpl('componentTpl'), childEls: ['iframeEl', 'textareaEl'], id: id, cls: Ext.baseCSSPrefix + 'html-editor-input', data: data }; }, /* * Called when the editor creates its toolbar. Override this method if you need to * add custom toolbar buttons. * @param {Ext.form.field.HtmlEditor} editor * @protected */ createToolbar: function(){ this.toolbar = Ext.widget(this.getToolbarCfg()); return this.toolbar; }, getToolbarCfg: function(){ var me = this, items = [], i, tipsEnabled = Ext.quickTipsActive && Ext.tip.QuickTipManager.isEnabled(), baseCSSPrefix = Ext.baseCSSPrefix, fontSelectItem, undef; function btn(id, toggle, handler){ return { itemId: id, cls: baseCSSPrefix + 'btn-icon', iconCls: baseCSSPrefix + 'edit-'+id, enableToggle:toggle !== false, scope: me, handler:handler||me.relayBtnCmd, clickEvent: 'mousedown', tooltip: tipsEnabled ? me.buttonTips[id] || undef : undef, overflowText: me.buttonTips[id].title || undef, tabIndex: -1 }; } if (me.enableFont && !Ext.isSafari2) { fontSelectItem = Ext.widget('component', { itemId: 'fontSelect', renderTpl: [ '' ], childEls: ['selectEl'], afterRender: function() { me.fontSelect = this.selectEl; Ext.Component.prototype.afterRender.apply(this, arguments); }, onDisable: function() { var selectEl = this.selectEl; if (selectEl) { selectEl.dom.disabled = true; } Ext.Component.prototype.onDisable.apply(this, arguments); }, onEnable: function() { var selectEl = this.selectEl; if (selectEl) { selectEl.dom.disabled = false; } Ext.Component.prototype.onEnable.apply(this, arguments); }, listeners: { change: function() { me.win.focus(); me.relayCmd('fontName', me.fontSelect.dom.value); me.deferFocus(); }, element: 'selectEl' } }); items.push( fontSelectItem, '-' ); } if (me.enableFormat) { items.push( btn('bold'), btn('italic'), btn('underline') ); } if (me.enableFontSize) { items.push( '-', btn('increasefontsize', false, me.adjustFont), btn('decreasefontsize', false, me.adjustFont) ); } if (me.enableColors) { items.push( '-', { itemId: 'forecolor', cls: baseCSSPrefix + 'btn-icon', iconCls: baseCSSPrefix + 'edit-forecolor', overflowText: me.buttonTips.forecolor.title, tooltip: tipsEnabled ? me.buttonTips.forecolor || undef : undef, tabIndex:-1, menu: Ext.widget('menu', { plain: true, items: [{ xtype: 'colorpicker', allowReselect: true, focus: Ext.emptyFn, value: '000000', plain: true, clickEvent: 'mousedown', handler: function(cp, color) { me.relayCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color); this.up('menu').hide(); } }] }) }, { itemId: 'backcolor', cls: baseCSSPrefix + 'btn-icon', iconCls: baseCSSPrefix + 'edit-backcolor', overflowText: me.buttonTips.backcolor.title, tooltip: tipsEnabled ? me.buttonTips.backcolor || undef : undef, tabIndex:-1, menu: Ext.widget('menu', { plain: true, items: [{ xtype: 'colorpicker', focus: Ext.emptyFn, value: 'FFFFFF', plain: true, allowReselect: true, clickEvent: 'mousedown', handler: function(cp, color) { if (Ext.isGecko) { me.execCmd('useCSS', false); me.execCmd('hilitecolor', '#'+color); me.execCmd('useCSS', true); me.deferFocus(); } else { me.relayCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE || Ext.isOpera ? '#'+color : color); } this.up('menu').hide(); } }] }) } ); } if (me.enableAlignments) { items.push( '-', btn('justifyleft'), btn('justifycenter'), btn('justifyright') ); } if (!Ext.isSafari2) { if (me.enableLinks) { items.push( '-', btn('createlink', false, me.createLink) ); } if (me.enableLists) { items.push( '-', btn('insertorderedlist'), btn('insertunorderedlist') ); } if (me.enableSourceEdit) { items.push( '-', btn('sourceedit', true, function(btn){ me.toggleSourceEdit(!me.sourceEditMode); }) ); } } // Everything starts disabled. for (i = 0; i < items.length; i++) { if (items[i].itemId !== 'sourceedit') { items[i].disabled = true; } } // build the toolbar // Automatically rendered in AbstractComponent.afterRender's renderChildren call return { xtype: 'toolbar', defaultButtonUI: me.defaultButtonUI, cls: Ext.baseCSSPrefix + 'html-editor-tb', enableOverflow: true, items: items, // stop form submits listeners: { click: function(e){ e.preventDefault(); }, element: 'el' } }; }, getMaskTarget: function(){ // Can't be the body td directly because of issues with absolute positioning // inside td's in FF return Ext.isGecko ? this.inputCmp.el : this.bodyEl; }, /** * Sets the read only state of this field. * @param {Boolean} readOnly Whether the field should be read only. */ setReadOnly: function(readOnly) { var me = this, textareaEl = me.textareaEl, iframeEl = me.iframeEl, body; me.readOnly = readOnly; if (textareaEl) { textareaEl.dom.readOnly = readOnly; } if (me.initialized) { body = me.getEditorBody(); if (Ext.isIE) { // Hide the iframe while setting contentEditable so it doesn't grab focus iframeEl.setDisplayed(false); body.contentEditable = !readOnly; iframeEl.setDisplayed(true); } else { me.setDesignMode(!readOnly); } if (body) { body.style.cursor = readOnly ? 'default' : 'text'; } me.disableItems(readOnly); } }, /** * Called when the editor initializes the iframe with HTML contents. Override this method if you * want to change the initialization markup of the iframe (e.g. to add stylesheets). * * **Note:** IE8-Standards has unwanted scroller behavior, so the default meta tag forces IE7 compatibility. * Also note that forcing IE7 mode works when the page is loaded normally, but if you are using IE's Web * Developer Tools to manually set the document mode, that will take precedence and override what this * code sets by default. This can be confusing when developing, but is not a user-facing issue. * @protected */ getDocMarkup: function() { var me = this, h = me.iframeEl.getHeight() - me.iframePad * 2, oldIE = Ext.isIE8m; // - IE9+ require a strict doctype otherwise text outside visible area can't be selected. // - Opera inserts

tags on Return key, so P margins must be removed to avoid double line-height. // - On browsers other than IE, the font is not inherited by the IFRAME so it must be specified. return Ext.String.format( (oldIE ? '' : '') + '' , me.iframePad, h, me.defaultFont); }, // @private getEditorBody: function() { var doc = this.getDoc(); return doc.body || doc.documentElement; }, // @private getDoc: function() { return this.iframeEl.dom.contentDocument || this.getWin().document; }, // @private getWin: function() { // using window.frames[id] to access the the iframe's window object in FF creates // a global variable with name == id in the global scope that references the iframe // window. This is undesirable for unit testing because that global variable // is readonly and cannot be deleted. To avoid this, we use contentWindow if it // is available (and it is in all supported browsers at the time of this writing) // and fall back to window.frames if contentWindow is not available. return this.iframeEl.dom.contentWindow || window.frames[this.iframeEl.dom.name]; }, initDefaultFont: function(){ // It's not ideal to do this here since it's a write phase, but we need to know // what the font used in the textarea is so that we can setup the appropriate font // options in the select box. The select box will reflow once we populate it, so we want // to do so before we layout the first time. var me = this, selIdx = 0, fonts, font, select, option, i, len, lower; if (!me.defaultFont) { font = me.textareaEl.getStyle('font-family'); font = Ext.String.capitalize(font.split(',')[0]); fonts = Ext.Array.clone(me.fontFamilies); Ext.Array.include(fonts, font); fonts.sort(); me.defaultFont = font; select = me.down('#fontSelect').selectEl.dom; for (i = 0, len = fonts.length; i < len; ++i) { font = fonts[i]; lower = font.toLowerCase(); option = new Option(font, lower); if (font == me.defaultFont) { selIdx = i; } option.style.fontFamily = lower; if (Ext.isIE) { select.add(option); } else { select.options.add(option); } } // Old IE versions have a problem if we set the selected property // in the loop, so set it after. select.options[selIdx].selected = true; } }, isEqual: function(value1, value2){ return this.isEqualAsString(value1, value2); }, // @private afterRender: function() { var me = this, inputCmp = me.inputCmp; me.callParent(arguments); me.iframeEl = inputCmp.iframeEl; me.textareaEl = inputCmp.textareaEl; // The input element is interrogated by the layout to extract height when labelAlign is 'top' // It must be set, and then switched between the iframe and the textarea me.inputEl = me.iframeEl; if (me.enableFont) { me.initDefaultFont(); } // Start polling for when the iframe document is ready to be manipulated me.monitorTask = Ext.TaskManager.start({ run: me.checkDesignMode, scope: me, interval: 100 }); }, initFrameDoc: function() { var me = this, doc, task; Ext.TaskManager.stop(me.monitorTask); doc = me.getDoc(); me.win = me.getWin(); doc.open(); doc.write(me.getDocMarkup()); doc.close(); task = { // must defer to wait for browser to be ready run: function() { var doc = me.getDoc(); if (doc.body || doc.readyState === 'complete') { Ext.TaskManager.stop(task); me.setDesignMode(true); Ext.defer(me.initEditor, 10, me); } }, interval: 10, duration:10000, scope: me }; Ext.TaskManager.start(task); }, checkDesignMode: function() { var me = this, doc = me.getDoc(); if (doc && (!doc.editorInitialized || me.getDesignMode() !== 'on')) { me.initFrameDoc(); } }, /** * @private * Sets current design mode. To enable, mode can be true or 'on', off otherwise */ setDesignMode: function(mode) { var me = this, doc = me.getDoc(); if (doc) { if (me.readOnly) { mode = false; } doc.designMode = (/on|true/i).test(String(mode).toLowerCase()) ?'on':'off'; } }, // @private getDesignMode: function() { var doc = this.getDoc(); return !doc ? '' : String(doc.designMode).toLowerCase(); }, disableItems: function(disabled) { var items = this.getToolbar().items.items, i, iLen = items.length, item; for (i = 0; i < iLen; i++) { item = items[i]; if (item.getItemId() !== 'sourceedit') { item.setDisabled(disabled); } } }, /** * Toggles the editor between standard and source edit mode. * @param {Boolean} [sourceEditMode] True for source edit, false for standard */ toggleSourceEdit: function(sourceEditMode) { var me = this, iframe = me.iframeEl, textarea = me.textareaEl, hiddenCls = Ext.baseCSSPrefix + 'hidden', btn = me.getToolbar().getComponent('sourceedit'); if (!Ext.isBoolean(sourceEditMode)) { sourceEditMode = !me.sourceEditMode; } me.sourceEditMode = sourceEditMode; if (btn.pressed !== sourceEditMode) { btn.toggle(sourceEditMode); } if (sourceEditMode) { me.disableItems(true); me.syncValue(); iframe.addCls(hiddenCls); textarea.removeCls(hiddenCls); textarea.dom.removeAttribute('tabIndex'); textarea.focus(); me.inputEl = textarea; } else { if (me.initialized) { me.disableItems(me.readOnly); } me.pushValue(); iframe.removeCls(hiddenCls); textarea.addCls(hiddenCls); textarea.dom.setAttribute('tabIndex', -1); me.deferFocus(); me.inputEl = iframe; } me.fireEvent('editmodechange', me, sourceEditMode); me.updateLayout(); }, // @private used internally createLink: function() { var url = prompt(this.createLinkText, this.defaultLinkValue); if (url && url !== 'http:/'+'/') { this.relayCmd('createlink', url); } }, clearInvalid: Ext.emptyFn, setValue: function(value) { var me = this, textarea = me.textareaEl, inputCmp = me.inputCmp; if (value === null || value === undefined) { value = ''; } if (textarea) { textarea.dom.value = value; } me.pushValue(); if (!me.rendered && me.inputCmp) { me.inputCmp.data.value = value; } me.mixins.field.setValue.call(me, value); return me; }, /** * If you need/want custom HTML cleanup, this is the method you should override. * @param {String} html The HTML to be cleaned * @return {String} The cleaned HTML * @protected */ cleanHtml: function(html) { html = String(html); if (Ext.isWebKit) { // strip safari nonsense html = html.replace(/\sclass="(?:Apple-style-span|Apple-tab-span|khtml-block-placeholder)"/gi, ''); } /* * Neat little hack. Strips out all the non-digit characters from the default * value and compares it to the character code of the first character in the string * because it can cause encoding issues when posted to the server. We need the * parseInt here because charCodeAt will return a number. */ if (html.charCodeAt(0) === parseInt(this.defaultValue.replace(/\D/g, ''), 10)) { html = html.substring(1); } return html; }, /** * Syncs the contents of the editor iframe with the textarea. * @protected */ syncValue: function(){ var me = this, body, changed, html, bodyStyle, match, textElDom; if (me.initialized) { body = me.getEditorBody(); html = body.innerHTML; textElDom = me.textareaEl.dom; if (Ext.isWebKit) { bodyStyle = body.getAttribute('style'); // Safari puts text-align styles on the body element! match = bodyStyle.match(/text-align:(.*?);/i); if (match && match[1]) { html = '

' + html + '
'; } } html = me.cleanHtml(html); if (me.fireEvent('beforesync', me, html) !== false) { // Gecko inserts single
tag when input is empty // and user toggles source mode. See https://sencha.jira.com/browse/EXTJSIV-8542 if (Ext.isGecko && textElDom.value === '' && html === '
') { html = ''; } if (textElDom.value !== html) { textElDom.value = html; changed = true; } me.fireEvent('sync', me, html); if (changed) { // we have to guard this to avoid infinite recursion because getValue // calls this method... me.checkChange(); } } } }, getValue: function() { var me = this, value; if (!me.sourceEditMode) { me.syncValue(); } value = me.rendered ? me.textareaEl.dom.value : me.value; me.value = value; return value; }, /** * Pushes the value of the textarea into the iframe editor. * @protected */ pushValue: function() { var me = this, v; if(me.initialized){ v = me.textareaEl.dom.value || ''; if (!me.activated && v.length < 1) { v = me.defaultValue; } if (me.fireEvent('beforepush', me, v) !== false) { me.getEditorBody().innerHTML = v; if (Ext.isGecko) { // Gecko hack, see: https://bugzilla.mozilla.org/show_bug.cgi?id=232791#c8 me.setDesignMode(false); //toggle off first me.setDesignMode(true); } me.fireEvent('push', me, v); } } }, // @private deferFocus: function(){ this.focus(false, true); }, getFocusEl: function() { var me = this, win = me.win; return win && !me.sourceEditMode ? win : me.textareaEl; }, focus: function(selectText, delay) { var me = this, value, focusEl; if (delay) { if (!me.focusTask) { me.focusTask = new Ext.util.DelayedTask(me.focus); } me.focusTask.delay(Ext.isNumber(delay) ? delay : 10, null, me, [selectText, false]); } else { if (selectText) { if (me.textareaEl && me.textareaEl.dom) { value = me.textareaEl.dom.value; } if (value && value.length) { // Make sure there is content before calling SelectAll, otherwise the caret disappears. me.execCmd('selectall', true); } } focusEl = me.getFocusEl(); if (focusEl && focusEl.focus) { focusEl.focus(); } } return me; }, // @private initEditor: function(){ //Destroying the component during/before initEditor can cause issues. try { var me = this, dbody = me.getEditorBody(), ss = me.textareaEl.getStyles('font-size', 'font-family', 'background-image', 'background-repeat', 'background-color', 'color'), doc, fn; ss['background-attachment'] = 'fixed'; // w3c dbody.bgProperties = 'fixed'; // ie Ext.DomHelper.applyStyles(dbody, ss); doc = me.getDoc(); if (doc) { try { Ext.EventManager.removeAll(doc); } catch(e) {} } /* * We need to use createDelegate here, because when using buffer, the delayed task is added * as a property to the function. When the listener is removed, the task is deleted from the function. * Since onEditorEvent is shared on the prototype, if we have multiple html editors, the first time one of the editors * is destroyed, it causes the fn to be deleted from the prototype, which causes errors. Essentially, we're just anonymizing the function. */ fn = Ext.Function.bind(me.onEditorEvent, me); Ext.EventManager.on(doc, { mousedown: fn, dblclick: fn, click: fn, keyup: fn, buffer:100 }); // These events need to be relayed from the inner document (where they stop // bubbling) up to the outer document. This has to be done at the DOM level so // the event reaches listeners on elements like the document body. The effected // mechanisms that depend on this bubbling behavior are listed to the right // of the event. fn = me.onRelayedEvent; Ext.EventManager.on(doc, { mousedown: fn, // menu dismisal (MenuManager) and Window onMouseDown (toFront) mousemove: fn, // window resize drag detection mouseup: fn, // window resize termination click: fn, // not sure, but just to be safe dblclick: fn, // not sure again scope: me }); if (Ext.isGecko) { Ext.EventManager.on(doc, 'keypress', me.applyCommand, me); } if (me.fixKeys) { Ext.EventManager.on(doc, 'keydown', me.fixKeys, me); } if (me.fixKeysAfter) { Ext.EventManager.on(doc, 'keyup', me.fixKeysAfter, me); } if (Ext.isIE9 && Ext.isStrict) { Ext.EventManager.on(doc.documentElement, 'focus', me.focus, me); } // In old IEs, clicking on a toolbar button shifts focus from iframe // and it loses selection. To avoid this, we save current selection // and restore it. if (Ext.isIE8m || (Ext.isIE9 && !Ext.isStrict)) { Ext.EventManager.on(doc, 'focusout', function() { me.savedSelection = doc.selection.type !== 'None' ? doc.selection.createRange() : null; }, me); Ext.EventManager.on(doc, 'focusin', function() { if (me.savedSelection) { me.savedSelection.select(); } }, me); } // We need to be sure we remove all our events from the iframe on unload or we're going to LEAK! Ext.EventManager.onWindowUnload(me.beforeDestroy, me); doc.editorInitialized = true; me.initialized = true; me.pushValue(); me.setReadOnly(me.readOnly); me.fireEvent('initialize', me); } catch(ex) { // ignore (why?) } }, // @private beforeDestroy: function(){ var me = this, monitorTask = me.monitorTask, doc, prop; if (monitorTask) { Ext.TaskManager.stop(monitorTask); } if (me.rendered) { Ext.EventManager.removeUnloadListener(me.beforeDestroy, me); try { doc = me.getDoc(); if (doc) { // removeAll() doesn't currently know how to handle iframe document, // so for now we have to wrap it in an Ext.Element using Ext.fly, // or else IE6/7 will leak big time when the page is refreshed. // TODO: this may not be needed once we find a more permanent fix. // see EXTJSIV-5891. Ext.EventManager.removeAll(Ext.fly(doc)); for (prop in doc) { if (doc.hasOwnProperty && doc.hasOwnProperty(prop)) { delete doc[prop]; } } } } catch(e) { // ignore (why?) } me.iframeEl.remove(); delete me.iframeEl; delete me.textareaEl; delete me.toolbar; delete me.inputCmp; } me.callParent(); }, // @private onRelayedEvent: function (event) { // relay event from the iframe's document to the document that owns the iframe... var iframeEl = this.iframeEl, // Get the left-based iframe position iframeXY = Ext.Element.getTrueXY(iframeEl), originalEventXY = event.getXY(), // Get the left-based XY position. // This is because the consumer of the injected event (Ext.EventManager) will // perform its own RTL normalization. eventXY = Ext.EventManager.getPageXY(event.browserEvent); // the event from the inner document has XY relative to that document's origin, // so adjust it to use the origin of the iframe in the outer document: event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]]; event.injectEvent(iframeEl); // blame the iframe for the event... event.xy = originalEventXY; // restore the original XY (just for safety) }, // @private onFirstFocus: function(){ var me = this, selection, range; me.activated = true; me.disableItems(me.readOnly); if (Ext.isGecko) { // prevent silly gecko errors me.win.focus(); selection = me.win.getSelection(); // If the editor contains a
tag, clicking on the editor after the text where // the
broke the line will produce nodeType === 1 (the body tag). // It's better to check the length of the selection.focusNode's content. // // If htmleditor.value = ' ' (note the space) // 1. nodeType === 1 // 2. nodeName === 'BODY' // 3. selection.focusNode.textContent.length === 1 // // If htmleditor.value = '' (no chars) nodeType === 3 && nodeName === '#text' // 1. nodeType === 3 // 2. nodeName === '#text' // 3. selection.focusNode.textContent.length === 1 (yes, that's right, 1) // // The editor inserts Unicode code point 8203, a zero-width space when // htmleditor.value === '' (call selection.focusNode.textContent.charCodeAt(0)) // http://www.fileformat.info/info/unicode/char/200b/index.htm // So, test with framework method to normalize. if (selection.focusNode && !me.getValue().length) { range = selection.getRangeAt(0); range.selectNodeContents(me.getEditorBody()); range.collapse(true); me.deferFocus(); } try { me.execCmd('useCSS', true); me.execCmd('styleWithCSS', false); } catch(e) { // ignore (why?) } } me.fireEvent('activate', me); }, // @private adjustFont: function(btn) { var adjust = btn.getItemId() === 'increasefontsize' ? 1 : -1, size = this.getDoc().queryCommandValue('FontSize') || '2', isPxSize = Ext.isString(size) && size.indexOf('px') !== -1, isSafari; size = parseInt(size, 10); if (isPxSize) { // Safari 3 values // 1 = 10px, 2 = 13px, 3 = 16px, 4 = 18px, 5 = 24px, 6 = 32px if (size <= 10) { size = 1 + adjust; } else if (size <= 13) { size = 2 + adjust; } else if (size <= 16) { size = 3 + adjust; } else if (size <= 18) { size = 4 + adjust; } else if (size <= 24) { size = 5 + adjust; } else { size = 6 + adjust; } size = Ext.Number.constrain(size, 1, 6); } else { isSafari = Ext.isSafari; if (isSafari) { // safari adjust *= 2; } size = Math.max(1, size + adjust) + (isSafari ? 'px' : 0); } this.relayCmd('FontSize', size); }, // @private onEditorEvent: function(e) { this.updateToolbar(); }, /** * Triggers a toolbar update by reading the markup state of the current selection in the editor. * @protected */ updateToolbar: function() { var me = this, i, l, btns, doc, name, queriedName, fontSelect, toolbarSubmenus; if (me.readOnly) { return; } if (!me.activated) { me.onFirstFocus(); return; } btns = me.getToolbar().items.map; doc = me.getDoc(); if (me.enableFont && !Ext.isSafari2) { // When querying the fontName, Chrome may return an Array of font names // with those containing spaces being placed between single-quotes. queriedName = doc.queryCommandValue('fontName'); name = (queriedName ? queriedName.split(",")[0].replace(me.reStripQuotes, '') : me.defaultFont).toLowerCase(); fontSelect = me.fontSelect.dom; if (name !== fontSelect.value || name != queriedName) { fontSelect.value = name; } } function updateButtons() { var state; for (i = 0, l = arguments.length, name; i < l; i++) { name = arguments[i]; // Firefox 18+ sometimes throws NS_ERROR_INVALID_POINTER exception // See https://sencha.jira.com/browse/EXTJSIV-9766 try { state = doc.queryCommandState(name); } catch (e) { state = false; } btns[name].toggle(state); } } if(me.enableFormat){ updateButtons('bold', 'italic', 'underline'); } if(me.enableAlignments){ updateButtons('justifyleft', 'justifycenter', 'justifyright'); } if(!Ext.isSafari2 && me.enableLists){ updateButtons('insertorderedlist', 'insertunorderedlist'); } // Ensure any of our toolbar's owned menus are hidden. // The overflow menu must control itself. toolbarSubmenus = me.toolbar.query('menu'); for (i = 0; i < toolbarSubmenus.length; i++) { toolbarSubmenus[i].hide(); } me.syncValue(); }, // @private relayBtnCmd: function(btn) { this.relayCmd(btn.getItemId()); }, /** * Executes a Midas editor command on the editor document and performs necessary focus and toolbar updates. * **This should only be called after the editor is initialized.** * @param {String} cmd The Midas command * @param {String/Boolean} [value=null] The value to pass to the command */ relayCmd: function(cmd, value) { Ext.defer(function() { var me = this; if (!this.isDestroyed) { me.win.focus(); me.execCmd(cmd, value); me.updateToolbar(); } }, 10, this); }, /** * Executes a Midas editor command directly on the editor document. For visual commands, you should use * {@link #relayCmd} instead. **This should only be called after the editor is initialized.** * @param {String} cmd The Midas command * @param {String/Boolean} [value=null] The value to pass to the command */ execCmd: function(cmd, value){ var me = this, doc = me.getDoc(); doc.execCommand(cmd, false, (value == undefined ? null : value)); me.syncValue(); }, // @private applyCommand: function(e){ if (e.ctrlKey) { var me = this, c = e.getCharCode(), cmd; if (c > 0) { c = String.fromCharCode(c); switch (c) { case 'b': cmd = 'bold'; break; case 'i': cmd = 'italic'; break; case 'u': cmd = 'underline'; break; } if (cmd) { me.win.focus(); me.execCmd(cmd); me.deferFocus(); e.preventDefault(); } } } }, /** * Inserts the passed text at the current cursor position. * __Note:__ the editor must be initialized and activated to insert text. * @param {String} text */ insertAtCursor: function(text){ var me = this, range; if (me.activated) { me.win.focus(); if (Ext.isIE) { range = me.getDoc().selection.createRange(); if (range) { range.pasteHTML(text); me.syncValue(); me.deferFocus(); } }else{ me.execCmd('InsertHTML', text); me.deferFocus(); } } }, // @private fixKeys: (function() { // load time branching for fastest keydown performance if (Ext.isIE) { return function(e){ var me = this, k = e.getKey(), doc = me.getDoc(), readOnly = me.readOnly, range, target; if (k === e.TAB) { e.stopEvent(); if (!readOnly) { range = doc.selection.createRange(); if (range){ if (range.collapse) { range.collapse(true); range.pasteHTML('    '); } me.deferFocus(); } } } else if (k === e.ENTER) { if (!readOnly) { range = doc.selection.createRange(); if (range) { target = range.parentElement(); if(!target || target.tagName.toLowerCase() !== 'li'){ e.stopEvent(); range.pasteHTML('
'); range.collapse(false); range.select(); } } } } }; } if (Ext.isOpera) { return function(e){ var me = this, k = e.getKey(), readOnly = me.readOnly; if (k === e.TAB) { e.stopEvent(); if (!readOnly) { me.win.focus(); me.execCmd('InsertHTML','    '); me.deferFocus(); } } }; } return null; // not needed, so null }()), // @private fixKeysAfter: (function() { if (Ext.isIE) { return function(e) { var me = this, k = e.getKey(), doc = me.getDoc(), readOnly = me.readOnly, innerHTML; if (!readOnly && (k === e.BACKSPACE || k === e.DELETE)) { innerHTML = doc.body.innerHTML; // If HtmlEditor had some input and user cleared it, IE inserts

 

// which makes an impression that there is still some text, and creeps // into source mode when toggled. We don't want this. // // See https://sencha.jira.com/browse/EXTJSIV-8542 // // N.B. There is **small** chance that user could go to source mode, // type '

 

', switch back to visual mode, type something else // and then clear it -- the code below would clear the

tag as well, // which could be considered a bug. However I see no way to distinguish // between offending markup being entered manually and generated by IE, // so this can be considered a nasty corner case. // if (innerHTML === '

 

' || innerHTML === '

 

') { doc.body.innerHTML = ''; } } } } return null; }()), /** * Returns the editor's toolbar. **This is only available after the editor has been rendered.** * @return {Ext.toolbar.Toolbar} */ getToolbar: function(){ return this.toolbar; }, // /** * @property {Object} buttonTips * Object collection of toolbar tooltips for the buttons in the editor. The key is the command id associated with * that button and the value is a valid QuickTips object. For example: * * { * bold: { * title: 'Bold (Ctrl+B)', * text: 'Make the selected text bold.', * cls: 'x-html-editor-tip' * }, * italic: { * title: 'Italic (Ctrl+I)', * text: 'Make the selected text italic.', * cls: 'x-html-editor-tip' * } * // ... * } */ buttonTips: { bold: { title: 'Bold (Ctrl+B)', text: 'Make the selected text bold.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, italic: { title: 'Italic (Ctrl+I)', text: 'Make the selected text italic.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, underline: { title: 'Underline (Ctrl+U)', text: 'Underline the selected text.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, increasefontsize: { title: 'Grow Text', text: 'Increase the font size.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, decreasefontsize: { title: 'Shrink Text', text: 'Decrease the font size.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, backcolor: { title: 'Text Highlight Color', text: 'Change the background color of the selected text.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, forecolor: { title: 'Font Color', text: 'Change the color of the selected text.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, justifyleft: { title: 'Align Text Left', text: 'Align text to the left.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, justifycenter: { title: 'Center Text', text: 'Center text in the editor.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, justifyright: { title: 'Align Text Right', text: 'Align text to the right.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, insertunorderedlist: { title: 'Bullet List', text: 'Start a bulleted list.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, insertorderedlist: { title: 'Numbered List', text: 'Start a numbered list.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, createlink: { title: 'Hyperlink', text: 'Make the selected text a hyperlink.', cls: Ext.baseCSSPrefix + 'html-editor-tip' }, sourceedit: { title: 'Source Edit', text: 'Switch to source editing mode.', cls: Ext.baseCSSPrefix + 'html-editor-tip' } } // // hide stuff that is not compatible /** * @event blur * @private */ /** * @event focus * @private */ /** * @event specialkey * @private */ /** * @cfg {String} fieldCls * @private */ /** * @cfg {String} focusCls * @private */ /** * @cfg {String} autoCreate * @private */ /** * @cfg {String} inputType * @private */ /** * @cfg {String} invalidCls * @private */ /** * @cfg {String} invalidText * @private */ /** * @cfg {String} msgFx * @private */ /** * @cfg {Boolean} allowDomMove * @private */ /** * @cfg {String} applyTo * @private */ /** * @cfg {String} readOnly * @private */ /** * @cfg {String} tabIndex * @private */ /** * @method validate * @private */ }); /** * A time picker which provides a list of times from which to choose. This is used by the Ext.form.field.Time * class to allow browsing and selection of valid times, but could also be used with other components. * * By default, all times starting at midnight and incrementing every 15 minutes will be presented. This list of * available times can be controlled using the {@link #minValue}, {@link #maxValue}, and {@link #increment} * configuration properties. The format of the times presented in the list can be customized with the {@link #format} * config. * * To handle when the user selects a time from the list, you can subscribe to the {@link #selectionchange} event. * * @example * Ext.create('Ext.picker.Time', { * width: 60, * minValue: Ext.Date.parse('04:30:00 AM', 'h:i:s A'), * maxValue: Ext.Date.parse('08:00:00 AM', 'h:i:s A'), * renderTo: Ext.getBody() * }); */ Ext.define('Ext.picker.Time', { extend: Ext.view.BoundList , alias: 'widget.timepicker', /** * @cfg {Date} minValue * The minimum time to be shown in the list of times. This must be a Date object (only the time fields will be * used); no parsing of String values will be done. */ /** * @cfg {Date} maxValue * The maximum time to be shown in the list of times. This must be a Date object (only the time fields will be * used); no parsing of String values will be done. */ /** * @cfg {Number} increment * The number of minutes between each time value in the list. */ increment: 15, // /** * @cfg {String} [format=undefined] * The default time format string which can be overriden for localization support. The format must be valid * according to {@link Ext.Date#parse}. * * Defaults to `'g:i A'`, e.g., `'3:15 PM'`. For 24-hour time format try `'H:i'` instead. */ format : "g:i A", // /** * @private * The field in the implicitly-generated Model objects that gets displayed in the list. This is * an internal field name only and is not useful to change via config. */ displayField: 'disp', /** * @private * Year, month, and day that all times will be normalized into internally. */ initDate: [2008,0,1], componentCls: Ext.baseCSSPrefix + 'timepicker', /** * @cfg * @private */ loadMask: false, initComponent: function() { var me = this, dateUtil = Ext.Date, clearTime = dateUtil.clearTime, initDate = me.initDate; // Set up absolute min and max for the entire day me.absMin = clearTime(new Date(initDate[0], initDate[1], initDate[2])); me.absMax = dateUtil.add(clearTime(new Date(initDate[0], initDate[1], initDate[2])), 'mi', (24 * 60) - 1); me.store = me.createStore(); // Add our min/max range filter, but do not apply it. // The owning TimeField will filter it. me.store.addFilter(me.rangeFilter = new Ext.util.Filter({ id: 'time-picker-filter' }), false); // Updates the range filter's filterFn according to our configured min and max me.updateList(); me.callParent(); }, /** * Set the {@link #minValue} and update the list of available times. This must be a Date object (only the time * fields will be used); no parsing of String values will be done. * @param {Date} value */ setMinValue: function(value) { this.minValue = value; this.updateList(); }, /** * Set the {@link #maxValue} and update the list of available times. This must be a Date object (only the time * fields will be used); no parsing of String values will be done. * @param {Date} value */ setMaxValue: function(value) { this.maxValue = value; this.updateList(); }, /** * @private * Sets the year/month/day of the given Date object to the {@link #initDate}, so that only * the time fields are significant. This makes values suitable for time comparison. * @param {Date} date */ normalizeDate: function(date) { var initDate = this.initDate; date.setFullYear(initDate[0], initDate[1], initDate[2]); return date; }, /** * Update the list of available times in the list to be constrained within the {@link #minValue} * and {@link #maxValue}. */ updateList: function() { var me = this, min = me.normalizeDate(me.minValue || me.absMin), max = me.normalizeDate(me.maxValue || me.absMax); me.rangeFilter.setFilterFn(function(record) { var date = record.get('date'); return date >= min && date <= max; }); me.store.filter(); }, /** * @private * Creates the internal {@link Ext.data.Store} that contains the available times. The store * is loaded with all possible times, and it is later filtered to hide those times outside * the minValue/maxValue. */ createStore: function() { var me = this, utilDate = Ext.Date, times = [], min = me.absMin, max = me.absMax; while(min <= max){ times.push({ disp: utilDate.dateFormat(min, me.format), date: min }); min = utilDate.add(min, 'mi', me.increment); } return new Ext.data.Store({ fields: ['disp', 'date'], data: times }); }, focusNode: function (rec) { // We don't want the view being focused when interacting with the inputEl (see Ext.form.field.ComboBox:onKeyUp) // so this is here to prevent focus of the boundlist view. See EXTJSIV-7319. return false; } }); /** * Provides a time input field with a time dropdown and automatic time validation. * * This field recognizes and uses JavaScript Date objects as its main {@link #value} type (only the time portion of the * date is used; the month/day/year are ignored). In addition, it recognizes string values which are parsed according to * the {@link #format} and/or {@link #altFormats} configs. These may be reconfigured to use time formats appropriate for * the user's locale. * * The field may be limited to a certain range of times by using the {@link #minValue} and {@link #maxValue} configs, * and the interval between time options in the dropdown can be changed with the {@link #increment} config. * * Example usage: * * @example * Ext.create('Ext.form.Panel', { * title: 'Time Card', * width: 300, * bodyPadding: 10, * renderTo: Ext.getBody(), * items: [{ * xtype: 'timefield', * name: 'in', * fieldLabel: 'Time In', * minValue: '6:00 AM', * maxValue: '8:00 PM', * increment: 30, * anchor: '100%' * }, { * xtype: 'timefield', * name: 'out', * fieldLabel: 'Time Out', * minValue: '6:00 AM', * maxValue: '8:00 PM', * increment: 30, * anchor: '100%' * }] * }); */ Ext.define('Ext.form.field.Time', { extend: Ext.form.field.ComboBox , alias: 'widget.timefield', alternateClassName: ['Ext.form.TimeField', 'Ext.form.Time'], /** * @cfg {String} [triggerCls='x-form-time-trigger'] * An additional CSS class used to style the trigger button. The trigger will always get the {@link #triggerBaseCls} * by default and triggerCls will be **appended** if specified. */ triggerCls: Ext.baseCSSPrefix + 'form-time-trigger', /** * @cfg {Date/String} minValue * The minimum allowed time. Can be either a Javascript date object with a valid time value or a string time in a * valid format -- see {@link #format} and {@link #altFormats}. */ /** * @cfg {Date/String} maxValue * The maximum allowed time. Can be either a Javascript date object with a valid time value or a string time in a * valid format -- see {@link #format} and {@link #altFormats}. */ // /** * @cfg {String} minText * The error text to display when the entered time is before {@link #minValue}. */ minText : "The time in this field must be equal to or after {0}", // // /** * @cfg {String} maxText * The error text to display when the entered time is after {@link #maxValue}. */ maxText : "The time in this field must be equal to or before {0}", // // /** * @cfg {String} invalidText * The error text to display when the time in the field is invalid. */ invalidText : "{0} is not a valid time", // // /** * @cfg {String} [format=undefined] * The default time format string which can be overriden for localization support. The format must be valid * according to {@link Ext.Date#parse}. * * Defaults to `'g:i A'`, e.g., `'3:15 PM'`. For 24-hour time format try `'H:i'` instead. */ format : "g:i A", // // /** * @cfg {String} [submitFormat=undefined] * The date format string which will be submitted to the server. The format must be valid according to * {@link Ext.Date#parse}. * * Defaults to {@link #format}. */ // // /** * @cfg {String} altFormats * Multiple date formats separated by "|" to try when parsing a user input value and it doesn't match the defined * format. */ altFormats : "g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A", // /** * @cfg {Number} increment * The number of minutes between each time value in the list. */ increment: 15, /** * @cfg {Number} pickerMaxHeight * The maximum height of the {@link Ext.picker.Time} dropdown. */ pickerMaxHeight: 300, /** * @cfg {Boolean} selectOnTab * Whether the Tab key should select the currently highlighted item. */ selectOnTab: true, /** * @cfg {Boolean} [snapToIncrement=false] * Specify as `true` to enforce that only values on the {@link #increment} boundary are accepted. */ snapToIncrement: false, /** * @private * This is the date to use when generating time values in the absence of either minValue * or maxValue. Using the current date causes DST issues on DST boundary dates, so this is an * arbitrary "safe" date that can be any date aside from DST boundary dates. */ initDate: '1/1/2008', initDateParts: [2008, 0, 1], initDateFormat: 'j/n/Y', ignoreSelection: 0, queryMode: 'local', displayField: 'disp', valueField: 'date', initComponent: function() { var me = this, min = me.minValue, max = me.maxValue; if (min) { me.setMinValue(min); } if (max) { me.setMaxValue(max); } me.displayTpl = new Ext.XTemplate( '' + '{[typeof values === "string" ? values : this.formatDate(values["' + me.displayField + '"])]}' + '' + me.delimiter + '' + '', { formatDate: Ext.Function.bind(me.formatDate, me) }); this.callParent(); }, /** * @private */ transformOriginalValue: function (value) { if (Ext.isDefined(value)) { return this.rawToValue(value) || value || null; } return value; }, /** * @private */ isEqual: function (v1, v2) { var fromArray = Ext.Array.from, isEqual = Ext.Date.isEqual, i, len; v1 = fromArray(v1); v2 = fromArray(v2); len = v1.length; if (len !== v2.length) { return false; } for (i = 0; i < len; i++) { if (!isEqual(v2[i], v1[i])) { return false; } } return true; }, /** * Replaces any existing {@link #minValue} with the new time and refreshes the picker's range. * @param {Date/String} value The minimum time that can be selected */ setMinValue: function(value) { var me = this, picker = me.picker; me.setLimit(value, true); if (picker) { picker.setMinValue(me.minValue); } }, /** * Replaces any existing {@link #maxValue} with the new time and refreshes the picker's range. * @param {Date/String} value The maximum time that can be selected */ setMaxValue: function(value) { var me = this, picker = me.picker; me.setLimit(value, false); if (picker) { picker.setMaxValue(me.maxValue); } }, /** * @private * Updates either the min or max value. Converts the user's value into a Date object whose * year/month/day is set to the {@link #initDate} so that only the time fields are significant. */ setLimit: function(value, isMin) { var me = this, d, val; if (Ext.isString(value)) { d = me.parseDate(value); } else if (Ext.isDate(value)) { d = value; } if (d) { val = me.getInitDate(); val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds()); } // Invalid min/maxValue config should result in a null so that defaulting takes over else { val = null; } me[isMin ? 'minValue' : 'maxValue'] = val; }, getInitDate: function(hours, minutes) { var parts = this.initDateParts; return new Date(parts[0], parts[1], parts[2], hours || 0, minutes || 0, 0, 0); }, valueToRaw: function(value) { return this.formatDate(this.parseDate(value)); }, /** * Runs all of Time's validations and returns an array of any errors. Note that this first runs Text's validations, * so the returned array is an amalgamation of all field errors. The additional validation checks are testing that * the time format is valid, that the chosen time is within the {@link #minValue} and {@link #maxValue} constraints * set. * @param {Object} [value] The value to get errors for (defaults to the current field value) * @return {String[]} All validation errors for this field */ getErrors: function(value) { var me = this, format = Ext.String.format, errors = me.callParent(arguments), minValue = me.minValue, maxValue = me.maxValue, data = me.displayTplData, raw = me.getRawValue(), i, len, date, item; if (data && data.length > 0) { for (i = 0, len = data.length; i < len; i++ ){ item = data[i]; item = item.date || item.disp; date = me.parseDate(item); if (!date) { errors.push(format(me.invalidText, item, Ext.Date.unescapeFormat(me.format))); continue; } if (minValue && date < minValue) { errors.push(format(me.minText, me.formatDate(minValue))); } if (maxValue && date > maxValue) { errors.push(format(me.maxText, me.formatDate(maxValue))); } } } else if (raw.length && !me.parseDate(raw)) { // If we don't have any data & a rawValue, it means an invalid time was entered. errors.push(format(me.invalidText, raw, Ext.Date.unescapeFormat(me.format))); } return errors; }, formatDate: function(items) { var formatted = [], i, len; items = Ext.Array.from(items); for (i = 0, len = items.length; i < len; i++) { formatted.push(Ext.form.field.Date.prototype.formatDate.call(this, items[i])); } return formatted.join(this.delimiter); }, /** * @private * Parses an input value into a valid Date object. * @param {String/Date} value */ parseDate: function(value) { var me = this, val = value, altFormats = me.altFormats, altFormatsArray = me.altFormatsArray, i = 0, len; if (value && !Ext.isDate(value)) { val = me.safeParse(value, me.format); if (!val && altFormats) { altFormatsArray = altFormatsArray || altFormats.split('|'); len = altFormatsArray.length; for (; i < len && !val; ++i) { val = me.safeParse(value, altFormatsArray[i]); } } } // If configured to snap, snap resulting parsed Date to the closest increment. if (val && me.snapToIncrement) { val = new Date(Ext.Number.snap(val.getTime(), me.increment * 60 * 1000)); } return val; }, safeParse: function(value, format){ var me = this, utilDate = Ext.Date, parsedDate, result = null; if (utilDate.formatContainsDateInfo(format)) { // assume we've been given a full date result = utilDate.parse(value, format); } else { // Use our initial safe date parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format); if (parsedDate) { result = parsedDate; } } return result; }, // @private getSubmitValue: function() { var me = this, format = me.submitFormat || me.format, value = me.getValue(); return value ? Ext.Date.format(value, format) : null; }, /** * @private * Creates the {@link Ext.picker.Time} */ createPicker: function() { var me = this, picker; me.listConfig = Ext.apply({ xtype: 'timepicker', selModel: { mode: me.multiSelect ? 'SIMPLE' : 'SINGLE' }, cls: undefined, minValue: me.minValue, maxValue: me.maxValue, increment: me.increment, format: me.format, maxHeight: me.pickerMaxHeight }, me.listConfig); picker = me.callParent(); me.bindStore(picker.store); return picker; }, onItemClick: function(picker, record){ // The selection change events won't fire when clicking on the selected element. Detect it here. var me = this, selected = picker.getSelectionModel().getSelection(); if (!me.multiSelect && selected.length) { if (selected.length > 0) { selected = selected[0]; if (selected && Ext.Date.isEqual(record.get('date'), selected.get('date'))) { me.collapse(); } } } }, /** * @private * Synchronizes the selection in the picker to match the current value */ syncSelection: function() { var me = this, picker = me.picker, isEqual = Ext.Date.isEqual, toSelect = [], selModel, value, values, i, len, item, data, d, dLen, rec; if (picker) { picker.clearHighlight(); value = me.getValue(); selModel = picker.getSelectionModel(); // Update the selection to match me.ignoreSelection++; if (value === null) { selModel.deselectAll(); } else { values = Ext.Array.from(value); data = picker.store.data.items; dLen = data.length; for (i = 0, len = values.length; i < len; i++) { item = values[i]; if (Ext.isDate(item)) { // find value, select it for (d = 0; d < dLen; d++) { rec = data[d]; if (isEqual(rec.get('date'), item)) { toSelect.push(rec); if (!me.multiSelect) { break; } } } selModel.select(toSelect); } } } me.ignoreSelection--; } }, postBlur: function() { var me = this, val = me.getValue(); me.callParent(arguments); // Only set the raw value if the current value is valid and is not falsy if (me.validateValue(val)) { me.setValue(val); } }, /** * Finds the record by searching values in the {@link #valueField}. * @param {Object/String} value The value to match the field against. * @return {Ext.data.Model} The matched record or false. */ findRecordByValue: function (value) { if (typeof value === 'string') { value = this.parseDate(value); } return this.callParent([value]); }, rawToValue: function (item) { var me = this, items, values, i, len; if (me.multiSelect) { values = []; items = Ext.Array.from(item); for (i = 0, len = items.length; i < len; i++) { values.push(me.parseDate(items[i])); } return values; } return me.parseDate(item); }, setValue: function(v) { // Store MUST be created for parent setValue to function this.getPicker(); if (Ext.isDate(v)) { v = this.getInitDate(v.getHours(), v.getMinutes()); } return this.callParent([v]); }, getValue: function () { return this.rawToValue(this.callParent(arguments)); } }); /** * Internal utility class that provides a unique cell context. * @private */ Ext.define('Ext.grid.CellContext', { /** * @property {Boolean} isCellContext * @readonly * `true` in this class to identify an object as an instantiated CellContext, or subclass thereof. */ isCellContext: true, constructor: function(view) { this.view = view; }, isEqual: function(other) { if (other) { return this.record === other.record && this.columnHeader === other.columnHeader; } return false; }, // Selection row/record & column/columnHeader setPosition: function(row, col) { var me = this; // We were passed {row: 1, column: 2, view: myView} if (arguments.length === 1) { if (row.view) { me.view = row.view; } col = row.column; row = row.row; } me.setRow(row); me.setColumn(col); return me; }, setRow: function(row) { var me = this; if (row !== undefined) { // Row index passed if (typeof row === 'number') { me.row = Math.max(Math.min(row, me.view.dataSource.getCount() - 1), 0); me.record = me.view.dataSource.getAt(row); } // row is a Record else if (row.isModel) { me.record = row; me.row = me.view.indexOf(row); } // row is a grid row else if (row.tagName) { me.record = me.view.getRecord(row); me.row = me.view.indexOf(me.record); } } }, setColumn: function(col) { var me = this, mgr = me.view.ownerCt.getColumnManager(); if (col !== undefined) { if (typeof col === 'number') { me.column = col; me.columnHeader = mgr.getHeaderAtIndex(col); } else if (col.isHeader) { me.columnHeader = col; me.column = mgr.getHeaderIndex(col); } } } }); /** * Internal utility class that provides default configuration for cell editing. * @private */ Ext.define('Ext.grid.CellEditor', { extend: Ext.Editor , constructor: function(config) { config = Ext.apply({}, config); if (config.field) { config.field.monitorTab = false; } this.callParent([config]); }, /** * @private * Hides the grid cell inner element when a cell editor is shown. */ onShow: function() { var me = this, innerCell = me.boundEl.first(); if (innerCell) { if (me.isForTree) { innerCell = innerCell.child(me.treeNodeSelector); } innerCell.hide(); } me.callParent(arguments); }, /** * @private * Shows the grid cell inner element when a cell editor is hidden */ onHide: function() { var me = this, innerCell = me.boundEl.first(); if (innerCell) { if (me.isForTree) { innerCell = innerCell.child(me.treeNodeSelector); } innerCell.show(); } me.callParent(arguments); }, /** * @private * Fix checkbox blur when it is clicked. */ afterRender: function() { var me = this, field = me.field; me.callParent(arguments); if (field.isCheckbox) { field.mon(field.inputEl, { mousedown: me.onCheckBoxMouseDown, click: me.onCheckBoxClick, scope: me }); } }, /** * @private * Because when checkbox is clicked it loses focus completeEdit is bypassed. */ onCheckBoxMouseDown: function() { this.completeEdit = Ext.emptyFn; }, /** * @private * Restore checkbox focus and completeEdit method. */ onCheckBoxClick: function() { delete this.completeEdit; this.field.focus(false, 10); }, /** * @private * Realigns the Editor to the grid cell, or to the text node in the grid inner cell * if the inner cell contains multiple child nodes. */ realign: function(autoSize) { var me = this, boundEl = me.boundEl, innerCell = boundEl.first(), innerCellTextNode = innerCell.dom.firstChild, width = boundEl.getWidth(), offsets = Ext.Array.clone(me.offsets), grid = me.grid, xOffset, v = '', // innerCell is empty if there are no children, or there is one text node, and it contains whitespace isEmpty = !innerCellTextNode || (innerCellTextNode.nodeType === 3 && !(Ext.String.trim(v = innerCellTextNode.data).length)); if (me.isForTree) { // When editing a tree, adjust the width and offsets of the editor to line // up with the tree cell's text element xOffset = me.getTreeNodeOffset(innerCell); width -= Math.abs(xOffset); offsets[0] += xOffset; } if (grid.columnLines) { // Subtract the column border width so that the editor displays inside the // borders. The column border could be either on the left or the right depending // on whether the grid is RTL - using the sum of both borders works in both modes. width -= boundEl.getBorderWidth('rl'); } if (autoSize === true) { me.field.setWidth(width); } // https://sencha.jira.com/browse/EXTJSIV-10871 Ensure the data bearing element has a height from text. if (isEmpty) { innerCell.dom.innerHTML = 'X'; } me.alignTo(innerCell, me.alignment, offsets); if (isEmpty) { innerCell.dom.firstChild.data = v; } }, // private getTreeNodeOffset: function(innerCell) { return innerCell.child(this.treeNodeSelector).getOffsetsTo(innerCell)[0]; }, onEditorTab: function(e){ var field = this.field; if (field.onEditorTab) { field.onEditorTab(e); } }, onFieldBlur : function() { this.callParent(arguments); // Reset the flag that may have been set by CellEditing#startEdit to prevent // Ext.Editor#onFieldBlur from canceling editing. this.selectSameEditor = false; }, alignment: "l-l", hideEl : false, cls: Ext.baseCSSPrefix + 'small-editor ' + Ext.baseCSSPrefix + 'grid-editor ' + Ext.baseCSSPrefix + 'grid-cell-editor', treeNodeSelector: '.' + Ext.baseCSSPrefix + 'tree-node-text', shim: false, shadow: false }); /** * Component layout for grid column headers which have a title element at the top followed by content. * @private */ Ext.define('Ext.grid.ColumnComponentLayout', { extend: Ext.layout.component.Auto , alias: 'layout.columncomponent', type: 'columncomponent', setWidthInDom: true, beginLayout: function(ownerContext) { this.callParent(arguments); ownerContext.titleContext = ownerContext.getEl('titleEl'); ownerContext.triggerContext = ownerContext.getEl('triggerEl'); }, beginLayoutCycle: function(ownerContext) { var owner = this.owner; this.callParent(arguments); // If shrinkwrapping, allow content width to stretch the element if (ownerContext.widthModel.shrinkWrap) { owner.el.setWidth(''); } owner.titleEl.setStyle({ paddingTop: '', // reset back to default padding of the style paddingBottom: '' }); }, // If not shrink wrapping, push height info down into child items publishInnerHeight: function(ownerContext, outerHeight) { // TreePanels (and grids with hideHeaders: true) set their column container height to zero ti hide them. // This is because they need to lay out in order to calculate widths for the columns (eg flexes). // If there is no height to lay out, bail out early. if (!outerHeight) { return; } var me = this, owner = me.owner, innerHeight = outerHeight - ownerContext.getBorderInfo().height, availableHeight = innerHeight, textHeight, titleHeight, pt, pb; // We do not have enough information to get the height of the titleEl if (!owner.noWrap && !ownerContext.hasDomProp('width')) { me.done = false; return; } // If we are not a container, but just have HTML content... if (ownerContext.hasRawContent) { titleHeight = availableHeight; // Vertically center the header text and ensure titleContext occupies availableHeight textHeight = owner.textEl.getHeight(); if (textHeight) { availableHeight -= textHeight; if (availableHeight > 0) { pt = Math.floor(availableHeight / 2); pb = availableHeight - pt; ownerContext.titleContext.setProp('padding-top', pt); ownerContext.titleContext.setProp('padding-bottom', pb); } } } // There are child items else { titleHeight = owner.titleEl.getHeight(); ownerContext.setProp('innerHeight', innerHeight - titleHeight, false); } // Only IE6 and IEQuirks needs this. // This is why we maintain titleHeight when setting it. if ((Ext.isIE6 || Ext.isIEQuirks) && ownerContext.triggerContext) { ownerContext.triggerContext.setHeight(titleHeight); } }, // We do not need the Direct2D sub pixel measurement here. Just the offsetHeight will do. // TODO: When https://sencha.jira.com/browse/EXTJSIV-7734 is fixed to not do subpixel adjustment on height, // remove this override. measureContentHeight: function(ownerContext) { return ownerContext.el.dom.offsetHeight; }, publishOwnerHeight: function(ownerContext, contentHeight) { this.callParent(arguments); // Only IE6 and IEQuirks needs this. // This is why we maintain titleHeight when setting it. if ((Ext.isIE6 || Ext.isIEQuirks) && ownerContext.triggerContext) { ownerContext.triggerContext.setHeight(contentHeight); } }, // If not shrink wrapping, push width info down into child items publishInnerWidth: function(ownerContext, outerWidth) { // If we are acting as a container, publish the innerWidth for the ColumnLayout to use if (!ownerContext.hasRawContent) { ownerContext.setProp('innerWidth', outerWidth - ownerContext.getBorderInfo().width, false); } }, // Push content height outwards when we are shrinkwrapping calculateOwnerHeightFromContentHeight: function (ownerContext, contentHeight) { var result = this.callParent(arguments); // If we are NOT a group header, we just use the auto component's measurement if (!ownerContext.hasRawContent) { if (this.owner.noWrap || ownerContext.hasDomProp('width')) { return contentHeight + this.owner.titleEl.getHeight() + ownerContext.getBorderInfo().height; } // We do not have the information to return the height yet because we cannot know // the final height of the text el return null; } return result; }, // Push content width outwards when we are shrinkwrapping calculateOwnerWidthFromContentWidth: function (ownerContext, contentWidth) { var owner = this.owner, padWidth = ownerContext.getPaddingInfo().width, triggerOffset = this.getTriggerOffset(owner, ownerContext), inner; // Only measure the content if we're not grouped, otherwise // the size should be governed by the children if (owner.isGroupHeader) { inner = contentWidth; } else { inner = Math.max(contentWidth, owner.textEl.getWidth() + ownerContext.titleContext.getPaddingInfo().width); } return inner + padWidth + triggerOffset; }, getTriggerOffset: function(owner, ownerContext) { var width = 0; if (ownerContext.widthModel.shrinkWrap && !owner.menuDisabled) { // If we have any children underneath, then we already have space reserved if (owner.query('>:not([hidden])').length === 0) { width = owner.self.triggerElWidth; } } return width; } }); /** * @private * * This class is used only by the grid's HeaderContainer docked child. * * It adds the ability to shrink the vertical size of the inner container element back if a grouped * column header has all its child columns dragged out, and the whole HeaderContainer needs to shrink back down. * * Also, after every layout, after all headers have attained their 'stretchmax' height, it goes through and calls * `setPadding` on the columns so that they lay out correctly. */ Ext.define('Ext.grid.ColumnLayout', { extend: Ext.layout.container.HBox , alias: 'layout.gridcolumn', type : 'gridcolumn', reserveOffset: false, firstHeaderCls: Ext.baseCSSPrefix + 'column-header-first', lastHeaderCls: Ext.baseCSSPrefix + 'column-header-last', initLayout: function() { var me = this; if (me.scrollbarWidth === undefined) { me.self.prototype.scrollbarWidth = Ext.getScrollbarSize().width; } me.grid = this.owner.up('[scrollerOwner]'); me.callParent(); }, // Collect the height of the table of data upon layout begin beginLayout: function (ownerContext) { var me = this, owner = me.owner, grid = me.grid, view = grid.view, items = me.getVisibleItems(), len = items.length, firstCls = me.firstHeaderCls, lastCls = me.lastHeaderCls, removeCls = [firstCls, lastCls], i, item; // If we are one side of a locking grid, then if we are on the "normal" side, we have to grab the normal view // for use in determining whether to subtract scrollbar width from available width. // The locked side does not have scrollbars, so it should not look at the view. if (grid.lockable) { if (owner.up('tablepanel') === view.normalGrid) { view = view.normalGrid.getView(); } else { view = null; } } for (i = 0; i < len; i++) { item = items[i]; item.removeCls(removeCls); if (i === 0) { item.addCls(firstCls); } if (i === len - 1) { item.addCls(lastCls); } } me.callParent(arguments); // If the owner is the grid's HeaderContainer, and the UI displays old fashioned scrollbars and there is a rendered View with data in it, // collect the View context to interrogate it for overflow, and possibly invalidate it if there is overflow if (!owner.isColumn && me.scrollbarWidth && !grid.collapsed && view && view.rendered && (ownerContext.viewTable = view.body.dom)) { ownerContext.viewContext = ownerContext.context.getCmp(view); } }, roundFlex: function(width) { return Math.floor(width); }, calculate: function(ownerContext) { this.callParent(arguments); if (ownerContext.state.parallelDone) { // TODO: auto width columns aren't necessarily done here. // see view.TableLayout, there is a work around for that there ownerContext.setProp('columnWidthsDone', true); } // Collect the height of the data table if we need it to determine overflow if (ownerContext.viewContext) { ownerContext.state.tableHeight = ownerContext.viewTable.offsetHeight; } }, completeLayout: function(ownerContext) { var me = this, owner = me.owner, state = ownerContext.state; me.callParent(arguments); // If we have not been through this already, and the owning Container is configured // forceFit, is not a group column and and there is a valid width, then convert // widths to flexes, and loop back. if (!ownerContext.flexedItems.length && !state.flexesCalculated && owner.forceFit && // Recalculate based upon all columns now being flexed instead of sized. // Set flag, so that we do not do this infinitely me.convertWidthsToFlexes(ownerContext)) { me.cacheFlexes(ownerContext); ownerContext.invalidate({ state: { flexesCalculated: true } }); } else { ownerContext.setProp('columnWidthsDone', true); } }, convertWidthsToFlexes: function(ownerContext) { var me = this, totalWidth = 0, calculated = me.sizeModels.calculated, childItems, len, i, childContext, item; childItems = ownerContext.childItems; len = childItems.length; for (i = 0; i < len; i++) { childContext = childItems[i]; item = childContext.target; totalWidth += childContext.props.width; // Only allow to be flexed if it's a resizable column if (!(item.fixed || item.resizable === false)) { // For forceFit, just use allocated width as the flex value, and the proportions // will end up the same whatever HeaderContainer width they are being forced into. item.flex = ownerContext.childItems[i].flex = childContext.props.width; item.width = null; childContext.widthModel = calculated; } } // Only need to loop back if the total column width is not already an exact fit return totalWidth !== ownerContext.props.width; }, /** * @private * Local getContainerSize implementation accounts for vertical scrollbar in the view. */ getContainerSize: function(ownerContext) { var me = this, result, viewContext = ownerContext.viewContext, viewHeight; // Column, NOT the main grid's HeaderContainer if (me.owner.isColumn) { result = me.getColumnContainerSize(ownerContext); } // This is the maingrid's HeaderContainer else { result = me.callParent(arguments); // If we've collected a viewContext and we're not shrinkwrapping the height // then we see if we have to narrow the width slightly to account for scrollbar if (viewContext && !viewContext.heightModel.shrinkWrap && viewContext.target.componentLayout.ownerContext) { // if (its layout is running) viewHeight = viewContext.getProp('height'); if (isNaN(viewHeight)) { me.done = false; } else if (ownerContext.state.tableHeight > viewHeight) { result.width -= me.scrollbarWidth; ownerContext.state.parallelDone = false; viewContext.invalidate(); } } } // TODO - flip the initial assumption to "we have a vscroll" to avoid the invalidate in most // cases (and the expensive ones to boot) return result; }, getColumnContainerSize : function(ownerContext) { var padding = ownerContext.paddingContext.getPaddingInfo(), got = 0, needed = 0, gotWidth, gotHeight, width, height; // In an shrinkWrap width/height case, we must not ask for any of these dimensions // because they will be determined by contentWidth/Height which is calculated by // this layout... // Fit/Card layouts are able to set just the width of children, allowing child's // resulting height to autosize the Container. // See examples/tabs/tabs.html for an example of this. if (!ownerContext.widthModel.shrinkWrap) { ++needed; width = ownerContext.getProp('innerWidth'); gotWidth = (typeof width == 'number'); if (gotWidth) { ++got; width -= padding.width; if (width < 0) { width = 0; } } } if (!ownerContext.heightModel.shrinkWrap) { ++needed; height = ownerContext.getProp('innerHeight'); gotHeight = (typeof height == 'number'); if (gotHeight) { ++got; height -= padding.height; if (height < 0) { height = 0; } } } return { width: width, height: height, needed: needed, got: got, gotAll: got == needed, gotWidth: gotWidth, gotHeight: gotHeight }; }, // FIX: when flexing we actually don't have enough space as we would // typically because of the scrollOffset on the GridView, must reserve this publishInnerCtSize: function(ownerContext) { var me = this, size = ownerContext.state.boxPlan.targetSize, cw = ownerContext.peek('contentWidth'), view; // Allow the other co-operating objects to know whether the columns overflow the available width. me.owner.tooNarrow = ownerContext.state.boxPlan.tooNarrow; // InnerCt MUST stretch to accommodate all columns so that left/right scrolling is enabled in the header container. if ((cw != null) && !me.owner.isColumn) { size.width = cw; // innerCt must also encompass any vertical scrollbar width if there may be one view = me.owner.ownerCt.view; if (view.scrollFlags.y) { size.width += me.scrollbarWidth; } } return me.callParent(arguments); } }); /** * @private * * Manages and provides information about a TablePanel's *visible leaf* columns. */ Ext.define('Ext.grid.ColumnManager', { alternateClassName: ['Ext.grid.ColumnModel'], columns: null, constructor: function(visibleOnly, headerCt, secondHeaderCt) { this.headerCt = headerCt; // We are managing columns for a lockable grid... if (secondHeaderCt) { this.secondHeaderCt = secondHeaderCt; } this.visibleOnly = !!visibleOnly; }, getColumns: function() { if (!this.columns) { this.cacheColumns(); } return this.columns; }, /** * If called from a root header, returns the index of a leaf level header regardless of what the nesting * structure is. * * If called from a group header, returns the index of a leaf level header relative to the group header. * * If a group header is passed, the index of the first leaf level header within it is returned. * * @param {Ext.grid.column.Column} header The header to find the index of * @return {Number} The index of the specified column header */ getHeaderIndex: function (header) { if (header.isGroupHeader) { // Get the first header for the particular group header. The .getHeaderColumns API // will sort out if it's to be just visible columns or all columns. header = this.getHeaderColumns(header)[0]; } return Ext.Array.indexOf(this.getColumns(), header); }, /** * If called from a root header, gets a leaf level header by index regardless of what the nesting * structure is. * * If called from a group header, returns the index of a leaf level header relative to the group header. * * @param {Number} index The column index for which to retrieve the column. * @return {Ext.grid.column.Column} The header. `null` if it doesn't exist. */ getHeaderAtIndex: function(index) { var columns = this.getColumns(), col = columns[index]; return col || null; }, getPreviousSibling: function(header){ var index = this.getHeaderIndex(header), col = null; if (index > 0) { col = this.getColumns()[index - 1]; } return col; }, getNextSibling: function(header){ var index = this.getHeaderIndex(header), col; if (index !== -1) { col = this.getColumns()[index + 1]; } return col || null; }, /** * Get the first column. * @return {Ext.grid.column.Column} The header. `null` if it doesn't exist */ getFirst: function(){ var columns = this.getColumns(); return columns.length > 0 ? columns[0] : null; }, /** * Get the last column. * @return {Ext.grid.column.Column} The header. `null` if it doesn't exist */ getLast: function(){ var columns = this.getColumns(), len = columns.length; return len > 0 ? columns[len - 1] : null; }, /** * Get a leaf level header by index regardless of what the nesting * structure is. * @param {String} id The id * @return {Ext.grid.column.Column} The header. `null` if it doesn't exist. */ getHeaderById: function(id) { var columns = this.getColumns(), len = columns.length, i, header; for (i = 0; i < len; ++i) { header = columns[i]; if (header.getItemId() === id) { return header; } } return null; }, /** * When passed a column index, returns the closet *visible* column to that. If the column at the passed index is visible, * that is returned. If it is hidden, either the next visible, or the previous visible column is returned. * * If called from a group header, returns the visible index of a leaf level header relative to the group header with the * same stipulations as outlined above. * * @param {Number} index Position at which to find the closest visible column. */ getVisibleHeaderClosestToIndex: function(index) { var result = this.getHeaderAtIndex(index); if (result && result.hidden) { result = result.next(':not([hidden])') || result.prev(':not([hidden])'); } return result; }, cacheColumns: function() { var columns = this.getHeaderColumns(this.headerCt), second = this.secondHeaderCt; if (second) { columns = columns.concat(this.getHeaderColumns(second)); } this.columns = columns; }, getHeaderColumns: function(header) { var result = this.visibleOnly ? header.getVisibleGridColumns() : header.getGridColumns(); return Ext.Array.clone(result); }, invalidate: function() { var root = this.rootColumns; this.columns = null; // If we are part of a lockable assembly, invalidate the root column manager if (root) { root.invalidate(); } }, destroy: function(){ this.columns = this.rootColumns = null; } }, function() { this.createAlias('indexOf', 'getHeaderIndex'); }); /** * This is a base class for layouts that contain a single item that automatically expands to fill the layout's * container. This class is intended to be extended or created via the layout:'fit' * {@link Ext.container.Container#layout} config, and should generally not need to be created directly via the new keyword. * * Fit layout does not have any direct config options (other than inherited ones). To fit a panel to a container using * Fit layout, simply set `layout: 'fit'` on the container and add a single panel to it. * * @example * Ext.create('Ext.panel.Panel', { * title: 'Fit Layout', * width: 300, * height: 150, * layout:'fit', * items: { * title: 'Inner Panel', * html: 'This is the inner panel content', * bodyPadding: 20, * border: false * }, * renderTo: Ext.getBody() * }); * * If the container has multiple items, all of the items will all be equally sized. This is usually not * desired, so to avoid this, place only a **single** item in the container. This sizing of all items * can be used to provide a background {@link Ext.Img image} that is "behind" another item * such as a {@link Ext.view.View dataview} if you also absolutely position the items. */ Ext.define('Ext.layout.container.Fit', { /* Begin Definitions */ extend: Ext.layout.container.Container , alternateClassName: 'Ext.layout.FitLayout', alias: 'layout.fit', /* End Definitions */ itemCls: Ext.baseCSSPrefix + 'fit-item', targetCls: Ext.baseCSSPrefix + 'layout-fit', type: 'fit', /** * @cfg {Object} defaultMargins * If the individual contained items do not have a margins property specified or margin specified via CSS, the * default margins from this property will be applied to each item. * * This property may be specified as an object containing margins to apply in the format: * * { * top: (top margin), * right: (right margin), * bottom: (bottom margin), * left: (left margin) * } * * This property may also be specified as a string containing space-separated, numeric margin values. The order of * the sides associated with each value matches the way CSS processes margin values: * * - If there is only one value, it applies to all sides. * - If there are two values, the top and bottom borders are set to the first value and the right and left are * set to the second. * - If there are three values, the top is set to the first value, the left and right are set to the second, * and the bottom is set to the third. * - If there are four values, they apply to the top, right, bottom, and left, respectively. * */ defaultMargins: { top: 0, right: 0, bottom: 0, left: 0 }, manageMargins: true, sizePolicies: { 0: { readsWidth: 1, readsHeight: 1, setsWidth: 0, setsHeight: 0 }, 1: { readsWidth: 0, readsHeight: 1, setsWidth: 1, setsHeight: 0 }, 2: { readsWidth: 1, readsHeight: 0, setsWidth: 0, setsHeight: 1 }, 3: { readsWidth: 0, readsHeight: 0, setsWidth: 1, setsHeight: 1 } }, getItemSizePolicy: function (item, ownerSizeModel) { // this layout's sizePolicy is derived from its owner's sizeModel: var sizeModel = ownerSizeModel || this.owner.getSizeModel(), mode = (sizeModel.width.shrinkWrap ? 0 : 1) | (sizeModel.height.shrinkWrap ? 0 : 2); return this.sizePolicies[mode]; }, beginLayoutCycle: function (ownerContext, firstCycle) { var me = this, // determine these before the lastSizeModels get updated: resetHeight = me.lastHeightModel && me.lastHeightModel.calculated, resetWidth = me.lastWidthModel && me.lastWidthModel.calculated, resetSizes = resetWidth || resetHeight, maxChildMinHeight = 0, maxChildMinWidth = 0, c, childItems, i, item, length, margins, minHeight, minWidth, style, undef; me.callParent(arguments); // Clear any dimensions which we set before calculation, in case the current // settings affect the available size. This particularly effects self-sizing // containers such as fields, in which the target element is naturally sized, // and should not be stretched by a sized child item. if (resetSizes && ownerContext.targetContext.el.dom.tagName.toUpperCase() != 'TD') { resetSizes = resetWidth = resetHeight = false; } childItems = ownerContext.childItems; length = childItems.length; for (i = 0; i < length; ++i) { item = childItems[i]; // On the firstCycle, we determine the max of the minWidth/Height of the items // since these can cause the container to grow scrollbars despite our attempts // to fit the child to the container. if (firstCycle) { c = item.target; minHeight = c.minHeight; minWidth = c.minWidth; if (minWidth || minHeight) { margins = item.marginInfo || item.getMarginInfo(); // if the child item has undefined minWidth/Height, these will become // NaN by adding the margins... minHeight += margins.height; minWidth += margins.height; // if the child item has undefined minWidth/Height, these comparisons // will evaluate to false... that is, "0 < NaN" == false... if (maxChildMinHeight < minHeight) { maxChildMinHeight = minHeight; } if (maxChildMinWidth < minWidth) { maxChildMinWidth = minWidth; } } } if (resetSizes) { style = item.el.dom.style; if (resetHeight) { style.height = ''; } if (resetWidth) { style.width = ''; } } } if (firstCycle) { ownerContext.maxChildMinHeight = maxChildMinHeight; ownerContext.maxChildMinWidth = maxChildMinWidth; } // Cache the overflowX/Y flags, but make them false in shrinkWrap mode (since we // won't be triggering overflow in that case) and false if we have no minSize (so // no child to trigger an overflow). c = ownerContext.target; ownerContext.overflowX = (!ownerContext.widthModel.shrinkWrap && ownerContext.maxChildMinWidth && c.scrollFlags.x) || undef; ownerContext.overflowY = (!ownerContext.heightModel.shrinkWrap && ownerContext.maxChildMinHeight && c.scrollFlags.y) || undef; }, calculate : function (ownerContext) { var me = this, childItems = ownerContext.childItems, length = childItems.length, containerSize = me.getContainerSize(ownerContext), info = { length: length, ownerContext: ownerContext, targetSize: containerSize }, shrinkWrapWidth = ownerContext.widthModel.shrinkWrap, shrinkWrapHeight = ownerContext.heightModel.shrinkWrap, overflowX = ownerContext.overflowX, overflowY = ownerContext.overflowY, scrollbars, scrollbarSize, padding, i, contentWidth, contentHeight; if (overflowX || overflowY) { // If we have children that have minHeight/Width, we may be forced to overflow // and gain scrollbars. If so, we want to remove their space from the other // axis so that we fit things inside the scrollbars rather than under them. scrollbars = me.getScrollbarsNeeded( overflowX && containerSize.width, overflowY && containerSize.height, ownerContext.maxChildMinWidth, ownerContext.maxChildMinHeight); if (scrollbars) { scrollbarSize = Ext.getScrollbarSize(); if (scrollbars & 1) { // if we need the hscrollbar, remove its height containerSize.height -= scrollbarSize.height; } if (scrollbars & 2) { // if we need the vscrollbar, remove its width containerSize.width -= scrollbarSize.width; } } } // Size the child items to the container (if non-shrinkWrap): for (i = 0; i < length; ++i) { info.index = i; me.fitItem(childItems[i], info); } if (shrinkWrapHeight || shrinkWrapWidth) { padding = ownerContext.targetContext.getPaddingInfo(); if (shrinkWrapWidth) { if (overflowY && !containerSize.gotHeight) { // if we might overflow vertically and don't have the container height, // we don't know if we will need a vscrollbar or not, so we must wait // for that height so that we can determine the contentWidth... me.done = false; } else { contentWidth = info.contentWidth + padding.width; // the scrollbar flag (if set) will indicate that an overflow exists on // the horz(1) or vert(2) axis... if not set, then there could never be // an overflow... if (scrollbars & 2) { // if we need the vscrollbar, add its width contentWidth += scrollbarSize.width; } if (!ownerContext.setContentWidth(contentWidth)) { me.done = false; } } } if (shrinkWrapHeight) { if (overflowX && !containerSize.gotWidth) { // if we might overflow horizontally and don't have the container width, // we don't know if we will need a hscrollbar or not, so we must wait // for that width so that we can determine the contentHeight... me.done = false; } else { contentHeight = info.contentHeight + padding.height; // the scrollbar flag (if set) will indicate that an overflow exists on // the horz(1) or vert(2) axis... if not set, then there could never be // an overflow... if (scrollbars & 1) { // if we need the hscrollbar, add its height contentHeight += scrollbarSize.height; } if (!ownerContext.setContentHeight(contentHeight)) { me.done = false; } } } } }, fitItem: function (itemContext, info) { var me = this; if (itemContext.invalid) { me.done = false; return; } info.margins = itemContext.getMarginInfo(); info.needed = info.got = 0; me.fitItemWidth(itemContext, info); me.fitItemHeight(itemContext, info); // If not all required dimensions have been satisfied, we're not done. if (info.got != info.needed) { me.done = false; } }, fitItemWidth: function (itemContext, info) { var contentWidth, width; // Attempt to set only dimensions that are being controlled, not shrinkWrap dimensions if (info.ownerContext.widthModel.shrinkWrap) { // contentWidth must include the margins to be consistent with setItemWidth width = itemContext.getProp('width') + info.margins.width; // because we add margins, width will be NaN or a number (not undefined) contentWidth = info.contentWidth; if (contentWidth === undefined) { info.contentWidth = width; } else { info.contentWidth = Math.max(contentWidth, width); } } else if (itemContext.widthModel.calculated) { ++info.needed; if (info.targetSize.gotWidth) { ++info.got; this.setItemWidth(itemContext, info); } } this.positionItemX(itemContext, info); }, fitItemHeight: function (itemContext, info) { var contentHeight, height; if (info.ownerContext.heightModel.shrinkWrap) { // contentHeight must include the margins to be consistent with setItemHeight height = itemContext.getProp('height') + info.margins.height; // because we add margins, height will be NaN or a number (not undefined) contentHeight = info.contentHeight; if (contentHeight === undefined) { info.contentHeight = height; } else { info.contentHeight = Math.max(contentHeight, height); } } else if (itemContext.heightModel.calculated) { ++info.needed; if (info.targetSize.gotHeight) { ++info.got; this.setItemHeight(itemContext, info); } } this.positionItemY(itemContext, info); }, positionItemX: function (itemContext, info) { var margins = info.margins; // Adjust position to account for configured margins or if we have multiple items // (all items should overlap): if (info.index || margins.left) { itemContext.setProp('x', margins.left); } if (margins.width) { // Need the margins for shrink-wrapping but old IE sometimes collapses the left margin into the padding itemContext.setProp('margin-right', margins.width); } }, positionItemY: function (itemContext, info) { var margins = info.margins; if (info.index || margins.top) { itemContext.setProp('y', margins.top); } if (margins.height) { // Need the margins for shrink-wrapping but old IE sometimes collapses the top margin into the padding itemContext.setProp('margin-bottom', margins.height); } }, setItemHeight: function (itemContext, info) { itemContext.setHeight(info.targetSize.height - info.margins.height); }, setItemWidth: function (itemContext, info) { itemContext.setWidth(info.targetSize.width - info.margins.width); } }); /** * @author Nicolas Ferrero * * TablePanel is the basis of both {@link Ext.tree.Panel TreePanel} and {@link Ext.grid.Panel GridPanel}. * * TablePanel aggregates: * * - a Selection Model * - a View * - a Store * - Scrollers * - Ext.grid.header.Container * * @mixins Ext.grid.locking.Lockable */ Ext.define('Ext.panel.Table', { extend: Ext.panel.Panel , alias: 'widget.tablepanel', extraBaseCls: Ext.baseCSSPrefix + 'grid', extraBodyCls: Ext.baseCSSPrefix + 'grid-body', layout: 'fit', /** * @property {Boolean} hasView * True to indicate that a view has been injected into the panel. */ hasView: false, // each panel should dictate what viewType and selType to use /** * @cfg {String} viewType * An xtype of view to use. This is automatically set to 'gridview' by {@link Ext.grid.Panel Grid} * and to 'treeview' by {@link Ext.tree.Panel Tree}. * @protected */ viewType: null, /** * @cfg {Object} viewConfig * A config object that will be applied to the grid's UI view. Any of the config options available for * {@link Ext.view.Table} can be specified here. This option is ignored if {@link #view} is specified. */ /** * @cfg {Ext.view.Table} view * The {@link Ext.view.Table} used by the grid. Use {@link #viewConfig} to just supply some config options to * view (instead of creating an entire View instance). */ /** * @cfg {String} selType * An xtype of selection model to use. Defaults to 'rowmodel'. This is used to create selection model if just * a config object or nothing at all given in {@link #selModel} config. */ selType: 'rowmodel', /** * @cfg {Ext.selection.Model/Object} selModel * A {@link Ext.selection.Model selection model} instance or config object. In latter case the {@link #selType} * config option determines to which type of selection model this config is applied. */ /** * @cfg {Boolean} [multiSelect=false] * True to enable 'MULTI' selection mode on selection model. * @deprecated 4.1.1 Use {@link Ext.selection.Model#mode} 'MULTI' instead. */ /** * @cfg {Boolean} [simpleSelect=false] * True to enable 'SIMPLE' selection mode on selection model. * @deprecated 4.1.1 Use {@link Ext.selection.Model#mode} 'SIMPLE' instead. */ /** * @cfg {Ext.data.Store} store (required) * The {@link Ext.data.Store Store} the grid should use as its data source. */ /** * @cfg {String/Boolean} scroll * Scrollers configuration. Valid values are 'both', 'horizontal' or 'vertical'. * True implies 'both'. False implies 'none'. */ scroll: true, /** * @cfg {Ext.grid.column.Column[]/Object} columns * An array of {@link Ext.grid.column.Column column} definition objects which define all columns that appear in this * grid. Each column definition provides the header text for the column, and a definition of where the data for that * column comes from. * * This can also be a configuration object for a {Ext.grid.header.Container HeaderContainer} which may override * certain default configurations if necessary. For example, the special layout may be overridden to use a simpler * layout, or one can set default values shared by all columns: * * columns: { * items: [ * { * text: "Column A" * dataIndex: "field_A" * },{ * text: "Column B", * dataIndex: "field_B" * }, * ... * ], * defaults: { * flex: 1 * } * } */ /** * @cfg {Boolean} forceFit * True to force the columns to fit into the available width. Headers are first sized according to configuration, * whether that be a specific width, or flex. Then they are all proportionally changed in width so that the entire * content width is used. For more accurate control, it is more optimal to specify a flex setting on the columns * that are to be stretched & explicit widths on columns that are not. */ /** * @cfg {Ext.grid.feature.Feature[]/Object[]/Ext.enums.Feature[]} features * An array of grid Features to be added to this grid. Can also be just a single feature instead of array. * * Features config behaves much like {@link #plugins}. * A feature can be added by either directly referencing the instance: * * features: [Ext.create('Ext.grid.feature.GroupingSummary', {groupHeaderTpl: 'Subject: {name}'})], * * By using config object with ftype: * * features: [{ftype: 'groupingsummary', groupHeaderTpl: 'Subject: {name}'}], * * Or with just a ftype: * * features: ['grouping', 'groupingsummary'], * * See {@link Ext.enums.Feature} for list of all ftypes. */ /** * @cfg {Boolean} [hideHeaders=false] * True to hide column headers. */ /** * @cfg {Boolean} deferRowRender * Defaults to true to enable deferred row rendering. * * This allows the View to execute a refresh quickly, with the expensive update of the row structure deferred so * that layouts with GridPanels appear, and lay out more quickly. */ /** * @cfg {Object} verticalScroller * A config object to be used when configuring the {@link Ext.grid.plugin.BufferedRenderer scroll monitor} to control * refreshing of data in an "infinite grid". * * Configurations of this object allow fine tuning of data caching which can improve performance and usability * of the infinite grid. */ deferRowRender: true, /** * @cfg {Boolean} sortableColumns * False to disable column sorting via clicking the header and via the Sorting menu items. */ sortableColumns: true, /** * @cfg {Boolean} [enableLocking=false] * Configure as `true` to enable locking support for this grid. Alternatively, locking will also be automatically * enabled if any of the columns in the {@link #columns columns} configuration contain a {@link Ext.grid.column.Column#locked locked} config option. * * A locking grid is processed in a special way. The configuration options are cloned and *two* grids are created to be the locked (left) side * and the normal (right) side. This Panel becomes merely a {@link Ext.container.Container container} which arranges both in an {@link Ext.layout.container.HBox HBox} layout. * * {@link #plugins Plugins} may be targeted at either locked, or unlocked grid, or, both, in which case the plugin is cloned and used on both sides. * * Plugins may also be targeted at the containing locking Panel. * * This is configured by specifying a `lockableScope` property in your plugin which may have the following values: * * * `"both"` (the default) - The plugin is added to both grids * * `"top"` - The plugin is added to the containing Panel * * `"locked"` - The plugin is added to the locked (left) grid * * `"normal"` - The plugin is added to the normal (right) grid * * If `both` is specified, then each copy of the plugin gains a property `lockingPartner` which references its sibling on the other side so that they * can synchronize operations is necessary. * * {@link #features Features} may also be configured with `lockableScope` and may target the locked grid, the normal grid or both grids. Features * also get a `lockingPartner` reference injected. */ enableLocking: false, // private property used to determine where to go down to find views // this is here to support locking. scrollerOwner: true, /** * @cfg {Boolean} [enableColumnMove=true] * False to disable column dragging within this grid. */ enableColumnMove: true, /** * @cfg {Boolean} [sealedColumns=false] * True to constrain column dragging so that a column cannot be dragged in or out of it's * current group. Only relevant while {@link #enableColumnMove} is enabled. */ sealedColumns: false, /** * @cfg {Boolean} [enableColumnResize=true] * False to disable column resizing within this grid. */ enableColumnResize: true, /** * @cfg {Boolean} [enableColumnHide=true] * False to disable column hiding within this grid. */ /** * @cfg {Boolean} columnLines Adds column line styling */ /** * @cfg {Boolean} [rowLines=true] Adds row line styling */ rowLines: true, /** * @cfg {Boolean} [disableSelection=false] * True to disable selection model. */ /** * @cfg {String} emptyText Default text (html tags are accepted) to display in the Panel body when the Store * is empty. When specified, and the Store is empty, the text will be rendered inside a DIV with the CSS class "x-grid-empty". */ /** * @cfg {Boolean} [allowDeselect=false] * True to allow deselecting a record. This config is forwarded to {@link Ext.selection.Model#allowDeselect}. */ /** * @property {Boolean} optimizedColumnMove * If you are writing a grid plugin or a {Ext.grid.feature.Feature Feature} which creates a column-based structure which * needs a view refresh when columns are moved, then set this property in the grid. * * An example is the built in {@link Ext.grid.feature.AbstractSummary Summary} Feature. This creates summary rows, and the * summary columns must be in the same order as the data columns. This plugin sets the `optimizedColumnMove` to `false. */ colLinesCls: Ext.baseCSSPrefix + 'grid-with-col-lines', rowLinesCls: Ext.baseCSSPrefix + 'grid-with-row-lines', noRowLinesCls: Ext.baseCSSPrefix + 'grid-no-row-lines', hiddenHeaderCtCls: Ext.baseCSSPrefix + 'grid-header-ct-hidden', hiddenHeaderCls: Ext.baseCSSPrefix + 'grid-header-hidden', resizeMarkerCls: Ext.baseCSSPrefix + 'grid-resize-marker', emptyCls: Ext.baseCSSPrefix + 'grid-empty', initComponent: function() { var me = this, headerCtCfg = me.columns || me.colModel, view, i, len, // Look up the configured Store. If none configured, use the fieldless, empty Store defined in Ext.data.Store. store = me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store'), columns; // Add the row/column line classes to the body element so that the settings are not inherited by docked grids (https://sencha.jira.com/browse/EXTJSIV-9263). if (me.columnLines) { me.addBodyCls(me.colLinesCls); } me.addBodyCls(me.rowLines ? me.rowLinesCls : me.noRowLinesCls); me.addBodyCls(me.extraBodyCls); // The columns/colModel config may be either a fully instantiated HeaderContainer, or an array of Column definitions, or a config object of a HeaderContainer // Either way, we extract a columns property referencing an array of Column definitions. if (headerCtCfg.isRootHeader) { me.headerCt = headerCtCfg; me.headerCt.forceFit = !!me.forceFit; // If it's an instance then the column managers were already created and bound to the headerCt. me.columnManager = headerCtCfg.columnManager; me.visibleColumnManager = headerCtCfg.visibleColumnManager; } else { // If any of the Column objects contain a locked property, and are not processed, this is a lockable TablePanel, a // special view will be injected by the Ext.grid.locking.Lockable mixin, so no processing of . if (me.enableLocking || me.hasLockedColumns(headerCtCfg)) { me.self.mixin('lockable', Ext.grid.locking.Lockable); me.injectLockable(); } // Not lockable - create the HeaderContainer else { if (Ext.isArray(headerCtCfg)) { headerCtCfg = { items: headerCtCfg }; } Ext.apply(headerCtCfg, { grid: me, forceFit: me.forceFit, sortable: me.sortableColumns, enableColumnMove: me.enableColumnMove, enableColumnResize: me.enableColumnResize, sealed: me.sealedColumns }); if (Ext.isDefined(me.enableColumnHide)) { headerCtCfg.enableColumnHide = me.enableColumnHide; } // Create our HeaderCOntainer from the generated configuration if (!me.headerCt) { me.headerCt = new Ext.grid.header.Container(headerCtCfg); } } } // Maintain backward compatibiliy by providing the initial leaf column set as a property. me.columns = columns = me.headerCt.getGridColumns(); me.scrollTask = new Ext.util.DelayedTask(me.syncHorizontalScroll, me); me.addEvents( // documented on GridPanel 'reconfigure', /** * @event viewready * Fires when the grid view is available (use this for selecting a default row). * @param {Ext.panel.Table} this */ 'viewready' ); me.cls = me.cls || '' + (' ' + me.extraBaseCls); // autoScroll is not a valid configuration delete me.autoScroll; // If this TablePanel is lockable (Either configured lockable, or any of the defined columns has a 'locked' property) // then a special lockable view containing 2 side-by-side grids will have been injected so we do not need to set up any UI. if (!me.hasView) { // If the Store is paging blocks of the dataset in, then it can only be sorted remotely. if (store.buffered && !store.remoteSort) { for (i = 0, len = columns.length; i < len; i++) { columns[i].sortable = false; } } if (me.hideHeaders) { me.headerCt.height = 0; // don't se the hidden property, we still need these to layout me.headerCt.hiddenHeaders = true; me.headerCt.addCls(me.hiddenHeaderCtCls); me.addCls(me.hiddenHeaderCls); // IE Quirks Mode fix // If hidden configuration option was used, several layout calculations will be bypassed. if (Ext.isIEQuirks) { me.headerCt.style = { display: 'none' }; } } me.relayHeaderCtEvents(me.headerCt); me.features = me.features || []; if (!Ext.isArray(me.features)) { me.features = [me.features]; } me.dockedItems = [].concat(me.dockedItems || []); me.dockedItems.unshift(me.headerCt); me.viewConfig = me.viewConfig || {}; // AbstractDataView will look up a Store configured as an object // getView converts viewConfig into a View instance view = me.getView(); me.items = [view]; me.hasView = true; // Add a listener to synchronize the horizontal scroll position of the headers // with the table view's element... Unless we are not showing headers! if (!me.hideHeaders) { view.on({ scroll: { fn: me.onHorizontalScroll, element: 'el', scope: me } }); } // Attach this Panel to the Store me.bindStore(store, true); me.mon(view, { viewready: me.onViewReady, refresh: me.onRestoreHorzScroll, scope: me }); } // Relay events from the View whether it be a LockingView, or a regular GridView me.relayEvents(me.view, [ /** * @event beforeitemmousedown * @inheritdoc Ext.view.View#beforeitemmousedown */ 'beforeitemmousedown', /** * @event beforeitemmouseup * @inheritdoc Ext.view.View#beforeitemmouseup */ 'beforeitemmouseup', /** * @event beforeitemmouseenter * @inheritdoc Ext.view.View#beforeitemmouseenter */ 'beforeitemmouseenter', /** * @event beforeitemmouseleave * @inheritdoc Ext.view.View#beforeitemmouseleave */ 'beforeitemmouseleave', /** * @event beforeitemclick * @inheritdoc Ext.view.View#beforeitemclick */ 'beforeitemclick', /** * @event beforeitemdblclick * @inheritdoc Ext.view.View#beforeitemdblclick */ 'beforeitemdblclick', /** * @event beforeitemcontextmenu * @inheritdoc Ext.view.View#beforeitemcontextmenu */ 'beforeitemcontextmenu', /** * @event itemmousedown * @inheritdoc Ext.view.View#itemmousedown */ 'itemmousedown', /** * @event itemmouseup * @inheritdoc Ext.view.View#itemmouseup */ 'itemmouseup', /** * @event itemmouseenter * @inheritdoc Ext.view.View#itemmouseenter */ 'itemmouseenter', /** * @event itemmouseleave * @inheritdoc Ext.view.View#itemmouseleave */ 'itemmouseleave', /** * @event itemclick * @inheritdoc Ext.view.View#itemclick */ 'itemclick', /** * @event itemdblclick * @inheritdoc Ext.view.View#itemdblclick */ 'itemdblclick', /** * @event itemcontextmenu * @inheritdoc Ext.view.View#itemcontextmenu */ 'itemcontextmenu', /** * @event beforecellclick * @inheritdoc Ext.view.Table#beforecellclick */ 'beforecellclick', /** * @event cellclick * @inheritdoc Ext.view.Table#cellclick */ 'cellclick', /** * @event beforecelldblclick * @inheritdoc Ext.view.Table#beforecelldblclick */ 'beforecelldblclick', /** * @event celldblclick * @inheritdoc Ext.view.Table#celldblclick */ 'celldblclick', /** * @event beforecellcontextmenu * @inheritdoc Ext.view.Table#beforecellcontextmenu */ 'beforecellcontextmenu', /** * @event cellcontextmenu * @inheritdoc Ext.view.Table#cellcontextmenu */ 'cellcontextmenu', /** * @event beforecellmousedown * @inheritdoc Ext.view.Table#beforecellmousedown */ 'beforecellmousedown', /** * @event cellmousedown * @inheritdoc Ext.view.Table#cellmousedown */ 'cellmousedown', /** * @event beforecellmouseup * @inheritdoc Ext.view.Table#beforecellmouseup */ 'beforecellmouseup', /** * @event cellmouseup * @inheritdoc Ext.view.Table#cellmouseup */ 'cellmouseup', /** * @event beforecellkeydown * @inheritdoc Ext.view.Table#beforecellkeydown */ 'beforecellkeydown', /** * @event cellkeydown * @inheritdoc Ext.view.Table#cellkeydown */ 'cellkeydown', /** * @event beforeitemkeydown * @inheritdoc Ext.view.Table#beforeitemkeydown */ 'beforeitemkeydown', /** * @event itemkeydown * @inheritdoc Ext.view.Table#itemkeydown */ 'itemkeydown', /** * @event beforecontainermousedown * @inheritdoc Ext.view.View#beforecontainermousedown */ 'beforecontainermousedown', /** * @event beforecontainermouseup * @inheritdoc Ext.view.View#beforecontainermouseup */ 'beforecontainermouseup', /** * @event beforecontainermousedown * @inheritdoc Ext.view.View#beforecontainermousedown */ 'beforecontainermousedown', /** * @event beforecontainermouseover * @inheritdoc Ext.view.View#beforecontainermouseover */ 'beforecontainermouseover', /** * @event beforecontainermouseout * @inheritdoc Ext.view.View#beforecontainermouseout */ 'beforecontainermouseout', /** * @event beforecontainerclick * @inheritdoc Ext.view.View#beforecontainerclick */ 'beforecontainerclick', /** * @event beforecontainerdblclick * @inheritdoc Ext.view.View#beforecontainerdblclick */ 'beforecontainerdblclick', /** * @event beforecontainercontextmenu * @inheritdoc Ext.view.View#beforecontainercontextmenu */ 'beforecontainercontextmenu', /** * @event beforecontainerkeydown * @inheritdoc Ext.view.View#beforecontainerkeydown */ 'beforecontainerkeydown', /** * @event containermouseup * @inheritdoc Ext.view.View#containermouseup */ 'containermouseup', /** * @event containermousedown * @inheritdoc Ext.view.View#containermousedown */ 'containermousedown', /** * @event containermouseover * @inheritdoc Ext.view.View#containermouseover */ 'containermouseover', /** * @event containermouseout * @inheritdoc Ext.view.View#containermouseout */ 'containermouseout', /** * @event containerclick * @inheritdoc Ext.view.View#containerclick */ 'containerclick', /** * @event containerdblclick * @inheritdoc Ext.view.View#containerdblclick */ 'containerdblclick', /** * @event containercontextmenu * @inheritdoc Ext.view.View#containercontextmenu */ 'containercontextmenu', /** * @event containerkeydown * @inheritdoc Ext.view.View#containerkeydown */ 'containerkeydown', /** * @event selectionchange * @inheritdoc Ext.selection.Model#selectionchange */ 'selectionchange', /** * @event beforeselect * @inheritdoc Ext.selection.RowModel#beforeselect */ 'beforeselect', /** * @event select * @inheritdoc Ext.selection.RowModel#select */ 'select', /** * @event beforedeselect * @inheritdoc Ext.selection.RowModel#beforedeselect */ 'beforedeselect', /** * @event deselect * @inheritdoc Ext.selection.RowModel#deselect */ 'deselect' ]); me.callParent(arguments); me.addStateEvents(['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange', 'filterchange', 'groupchange']); // If lockable, the headerCt is just a collection of Columns, not a Container if (!me.lockable && me.headerCt) { me.headerCt.on('afterlayout', me.onRestoreHorzScroll, me); } }, // Private. Determine if there are any columns with a locked configuration option hasLockedColumns: function(columns) { var i, len, column; // In case they specified a config object with items... if (Ext.isObject(columns)) { columns = columns.items; } for (i = 0, len = columns.length; i < len; i++) { column = columns[i]; if (!column.processed && column.locked) { return true; } } }, relayHeaderCtEvents: function (headerCt) { this.relayEvents(headerCt, [ /** * @event columnresize * @inheritdoc Ext.grid.header.Container#columnresize */ 'columnresize', /** * @event columnmove * @inheritdoc Ext.grid.header.Container#columnmove */ 'columnmove', /** * @event columnhide * @inheritdoc Ext.grid.header.Container#columnhide */ 'columnhide', /** * @event columnshow * @inheritdoc Ext.grid.header.Container#columnshow */ 'columnshow', /** * @event columnschanged * @inheritdoc Ext.grid.header.Container#columnschanged */ 'columnschanged', /** * @event sortchange * @inheritdoc Ext.grid.header.Container#sortchange */ 'sortchange', /** * @event headerclick * @inheritdoc Ext.grid.header.Container#headerclick */ 'headerclick', /** * @event headercontextmenu * @inheritdoc Ext.grid.header.Container#headercontextmenu */ 'headercontextmenu', /** * @event headertriggerclick * @inheritdoc Ext.grid.header.Container#headertriggerclick */ 'headertriggerclick' ]); }, getState: function(){ var me = this, state = me.callParent(), storeState = me.store.getState(); state = me.addPropertyToState(state, 'columns', me.headerCt.getColumnsState()); if (storeState) { state.storeState = storeState; } return state; }, applyState: function(state) { var me = this, sorter = state.sort, storeState = state.storeState, store = me.store, columns = state.columns; delete state.columns; // Ensure superclass has applied *its* state. // AbstractComponent saves dimensions (and anchor/flex) plus collapsed state. me.callParent(arguments); if (columns) { me.headerCt.applyColumnsState(columns); } // Old stored sort state. Deprecated and will die out. if (sorter) { if (store.remoteSort) { // Pass false to prevent a sort from occurring store.sort({ property: sorter.property, direction: sorter.direction, root: sorter.root }, null, false); } else { store.sort(sorter.property, sorter.direction); } } // New storeState which encapsulates groupers, sorters and filters else if (storeState) { store.applyState(storeState); } }, /** * Returns the store associated with this Panel. * @return {Ext.data.Store} The store */ getStore: function(){ return this.store; }, /** * Gets the view for this panel. * @return {Ext.view.Table} */ getView: function() { var me = this, sm; if (!me.view) { sm = me.getSelectionModel(); // TableView injects the view reference into this grid so that we have a reference as early as possible Ext.widget(Ext.apply({ // Features need a reference to the grid, so configure a reference into the View grid: me, deferInitialRefresh: me.deferRowRender !== false, trackOver: me.trackMouseOver !== false, scroll: me.scroll, xtype: me.viewType, store: me.store, headerCt: me.headerCt, columnLines: me.columnLines, rowLines: me.rowLines, selModel: sm, features: me.features, panel: me, emptyText: me.emptyText || '' }, me.viewConfig)); // Normalize the application of the markup wrapping the emptyText config. // `emptyText` can now be defined on the grid as well as on its viewConfig, and this led to the emptyText not // having the wrapping markup when it was defined in the viewConfig. It should be backwards compatible. // Note that in the unlikely event that emptyText is defined on both the grid config and the viewConfig that the viewConfig wins. if (me.view.emptyText) { me.view.emptyText = '
' + me.view.emptyText + '
'; } // TableView's custom component layout, Ext.view.TableLayout requires a reference to the headerCt because it depends on the headerCt doing its work. me.view.getComponentLayout().headerCt = me.headerCt; me.mon(me.view, { uievent: me.processEvent, scope: me }); sm.view = me.view; me.headerCt.view = me.view; } return me.view; }, getColumnManager: function(){ return this.columnManager; }, getVisibleColumnManager: function(){ return this.visibleColumnManager; }, getTopLevelColumnManager: function(){ var ownerLock = this.ownerLockable; return ownerLock ? ownerLock.getColumnManager() : this.getColumnManager(); }, getTopLevelVisibleColumnManager: function(){ var ownerLock = this.ownerLockable; return ownerLock ? ownerLock.getVisibleColumnManager() : this.getVisibleColumnManager(); }, /** * @private * autoScroll is never valid for all classes which extend TablePanel. */ setAutoScroll: Ext.emptyFn, /** * @private * Processes UI events from the view. Propagates them to whatever internal Components need to process them. * @param {String} type Event type, eg 'click' * @param {Ext.view.Table} view TableView Component * @param {HTMLElement} cell Cell HtmlElement the event took place within * @param {Number} recordIndex Index of the associated Store Model (-1 if none) * @param {Number} cellIndex Cell index within the row * @param {Ext.EventObject} e Original event */ processEvent: function(type, view, cell, recordIndex, cellIndex, e, record, row) { var me = this, header; if (cellIndex !== -1) { header = me.getColumnManager().getHeaderAtIndex(cellIndex); return header.processEvent.apply(header, arguments); } }, /** * This method is obsolete in 4.1. The closest equivalent in * 4.1 is {@link #doLayout}, but it is also possible that no * layout is needed. * @deprecated 4.1 */ determineScrollbars: function () { }, /** * This method is obsolete in 4.1. The closest equivalent in 4.1 is * {@link Ext.AbstractComponent#updateLayout}, but it is also possible that no layout * is needed. * @deprecated 4.1 */ invalidateScroller: function () { }, scrollByDeltaY: function(yDelta, animate) { this.getView().scrollBy(0, yDelta, animate); }, scrollByDeltaX: function(xDelta, animate) { this.getView().scrollBy(xDelta, 0, animate); }, afterCollapse: function() { this.saveScrollPos(); this.callParent(arguments); }, afterExpand: function() { this.callParent(arguments); this.restoreScrollPos(); }, saveScrollPos: Ext.emptyFn, restoreScrollPos: Ext.emptyFn, onHeaderResize: function(){ this.delayScroll(); }, // Update the view when a header moves onHeaderMove: function(headerCt, header, colsToMove, fromIdx, toIdx) { var me = this; // If there are Features or Plugins which create DOM which must match column order, they set the optimizedColumnMove flag to false. // In this case we must refresh the view on column move. if (me.optimizedColumnMove === false) { me.view.refresh(); } // Simplest case for default DOM structure is just to swap the columns round in the view. else { me.view.moveColumn(fromIdx, toIdx, colsToMove); } me.delayScroll(); }, // Section onHeaderHide is invoked after view. onHeaderHide: function(headerCt, header) { this.view.refresh(); this.delayScroll(); }, onHeaderShow: function(headerCt, header) { this.view.refresh(); this.delayScroll(); }, // To be triggered on add/remove/move for a leaf header onHeadersChanged: function(headerCt, header) { var me = this; if (me.rendered && !me.reconfiguring) { me.view.refresh(); me.delayScroll(); } }, delayScroll: function(){ var target = this.getScrollTarget().el; if (target) { this.scrollTask.delay(10, null, null, [target.dom.scrollLeft]); } }, /** * @private * Fires the TablePanel's viewready event when the view declares that its internal DOM is ready */ onViewReady: function() { this.fireEvent('viewready', this); }, /** * @private * Tracks when things happen to the view and preserves the horizontal scroll position. */ onRestoreHorzScroll: function() { var left = this.scrollLeftPos; if (left) { // We need to restore the body scroll position here this.syncHorizontalScroll(left, true); } }, getScrollerOwner: function() { var rootCmp = this; if (!this.scrollerOwner) { rootCmp = this.up('[scrollerOwner]'); } return rootCmp; }, /** * Gets left hand side marker for header resizing. * @private */ getLhsMarker: function() { var me = this; return me.lhsMarker || (me.lhsMarker = Ext.DomHelper.append(me.el, { role: 'presentation', cls: me.resizeMarkerCls }, true)); }, /** * Gets right hand side marker for header resizing. * @private */ getRhsMarker: function() { var me = this; return me.rhsMarker || (me.rhsMarker = Ext.DomHelper.append(me.el, { role: 'presentation', cls: me.resizeMarkerCls }, true)); }, /** * Returns the selection model being used and creates it via the configuration if it has not been created already. * @return {Ext.selection.Model} selModel */ getSelectionModel: function(){ var me = this, selModel = me.selModel, applyMode, mode, type; if (!selModel) { selModel = {}; // no config, set our own mode applyMode = true; } if (!selModel.events) { // only config provided, set our mode if one doesn't exist on the config type = selModel.selType || me.selType; applyMode = !selModel.mode; selModel = me.selModel = Ext.create('selection.' + type, selModel); } if (me.simpleSelect) { mode = 'SIMPLE'; } else if (me.multiSelect) { mode = 'MULTI'; } Ext.applyIf(selModel, { allowDeselect: me.allowDeselect }); if (mode && applyMode) { selModel.setSelectionMode(mode); } if (!selModel.hasRelaySetup) { me.relayEvents(selModel, [ 'selectionchange', 'beforeselect', 'beforedeselect', 'select', 'deselect' ]); selModel.hasRelaySetup = true; } // lock the selection model if user // has disabled selection if (me.disableSelection) { selModel.locked = true; } return selModel; }, getScrollTarget: function(){ var owner = this.getScrollerOwner(), items = owner.query('tableview'); return items[1] || items[0]; }, onHorizontalScroll: function(event, target) { this.syncHorizontalScroll(target.scrollLeft); }, syncHorizontalScroll: function(left, setBody) { var me = this, scrollTarget; setBody = setBody === true; // Only set the horizontal scroll if we've changed position, // so that we don't set this on vertical scrolls if (me.rendered && (setBody || left !== me.scrollLeftPos)) { // Only set the body position if we're reacting to a refresh, otherwise // we just need to set the header. if (setBody) { scrollTarget = me.getScrollTarget(); scrollTarget.el.dom.scrollLeft = left; } me.headerCt.el.dom.scrollLeft = left; me.scrollLeftPos = left; } }, // template method meant to be overriden onStoreLoad: Ext.emptyFn, getEditorParent: function() { return this.body; }, bindStore: function(store, initial) { var me = this, view = me.getView(), bufferedStore = store && store.buffered, bufferedRenderer; // Bind to store immediately because subsequent processing looks for grid's store property me.store = store; // If the Store is buffered, create a BufferedRenderer to monitor the View's scroll progress // and scroll rows on/off when it detects we are nearing an edge. // MUST be done before store is bound to the view so that the BufferedRenderer may inject its getViewRange implementation // before the view tries to refresh. bufferedRenderer = me.findPlugin('bufferedrenderer'); if (bufferedRenderer) { me.verticalScroller = bufferedRenderer; // If we're in a reconfigure rebind the BufferedRenderer if (bufferedRenderer.store) { bufferedRenderer.bindStore(store); } } else if (bufferedStore) { me.verticalScroller = bufferedRenderer = me.addPlugin(Ext.apply({ ptype: 'bufferedrenderer' }, me.initialConfig.verticalScroller)); } if (view.store !== store) { // If coming from a reconfigure, we need to set the actual store property on the view. Setting the // store will then also set the dataSource. // // Note that if it's a grid feature then this is sorted out in view.bindStore(), and it's own // implementation of .bindStore() will be called. view.bindStore(store, false); } me.mon(store, { load: me.onStoreLoad, scope: me }); me.storeRelayers = me.relayEvents(store, [ /** * @event filterchange * @inheritdoc Ext.data.Store#filterchange */ 'filterchange', /** * @event groupchange * @inheritdoc Ext.data.Store#groupchange */ 'groupchange' ]); // If buffered rendering is being used, scroll position must be preserved across refreshes if (bufferedRenderer) { me.invalidateScrollerOnRefresh = false; } if (me.invalidateScrollerOnRefresh !== undefined) { view.preserveScrollOnRefresh = !me.invalidateScrollerOnRefresh; } }, unbindStore: function() { var me = this, store = me.store; if (store) { me.store = null; me.mun(store, { load: me.onStoreLoad, scope: me }); Ext.destroy(me.storeRelayers); } }, // documented on GridPanel reconfigure: function(store, columns) { var me = this, view = me.getView(), originalDeferinitialRefresh, oldStore = me.store, headerCt = me.headerCt, oldColumns = headerCt ? headerCt.items.getRange() : me.columns; // Make copy in case the beforereconfigure listener mutates it. if (columns) { columns = Ext.Array.slice(columns); } me.reconfiguring = true; me.fireEvent('beforereconfigure', me, store, columns, oldStore, oldColumns); if (me.lockable) { me.reconfigureLockable(store, columns); } else { Ext.suspendLayouts(); if (columns) { // new columns, delete scroll pos delete me.scrollLeftPos; headerCt.removeAll(); headerCt.add(columns); } // The following test compares the result of an assignment of the store var with the oldStore var // This saves a large amount of code. if (store && (store = Ext.StoreManager.lookup(store)) !== oldStore) { // Only unbind the store if a new one was passed if (me.store) { me.unbindStore(); } // On reconfigure, view refresh must be inline. originalDeferinitialRefresh = view.deferInitialRefresh; view.deferInitialRefresh = false; me.bindStore(store); view.deferInitialRefresh = originalDeferinitialRefresh; } else { me.getView().refresh(); } headerCt.setSortState(); Ext.resumeLayouts(true); } me.fireEvent('reconfigure', me, store, columns, oldStore, oldColumns); delete me.reconfiguring; }, beforeDestroy: function(){ var task = this.scrollTask; if (task) { task.cancel(); this.scrollTask = null; } this.callParent(); }, onDestroy: function(){ var me = this; if (me.lockable) { me.destroyLockable(); } me.callParent(); me.columns = me.storeRelayers = me.columnManager = me.visibleColumnManager = null; }, destroy: function() { // Clear out references here because other things (plugins/features) may need to know about them during destruction var me = this; me.callParent(); if (me.isDestroyed) { me.view = me.selModel = me.headerCt = null; } } }); /** * Utility class for manipulating CSS rules * @singleton */ Ext.define('Ext.util.CSS', function() { var CSS, rules = null, doc = document, camelRe = /(-[a-z])/gi, camelFn = function(m, a){ return a.charAt(1).toUpperCase(); }; return { singleton: true, rules: rules, initialized: false, constructor: function() { // Cache a reference to the singleton CSS = this; }, /** * Creates a stylesheet from a text blob of rules. * These rules will be wrapped in a STYLE tag and appended to the HEAD of the document. * @param {String} cssText The text containing the css rules * @param {String} id An id to add to the stylesheet for later removal * @return {CSSStyleSheet} */ createStyleSheet : function(cssText, id) { var ss, head = doc.getElementsByTagName("head")[0], styleEl = doc.createElement("style"); styleEl.setAttribute("type", "text/css"); if (id) { styleEl.setAttribute("id", id); } if (Ext.isIE) { head.appendChild(styleEl); ss = styleEl.styleSheet; ss.cssText = cssText; } else { try{ styleEl.appendChild(doc.createTextNode(cssText)); } catch(e) { styleEl.cssText = cssText; } head.appendChild(styleEl); ss = styleEl.styleSheet ? styleEl.styleSheet : (styleEl.sheet || doc.styleSheets[doc.styleSheets.length-1]); } CSS.cacheStyleSheet(ss); return ss; }, /** * Removes a style or link tag by id * @param {String} id The id of the tag */ removeStyleSheet : function(id) { var existing = doc.getElementById(id); if (existing) { existing.parentNode.removeChild(existing); } }, /** * Dynamically swaps an existing stylesheet reference for a new one * @param {String} id The id of an existing link tag to remove * @param {String} url The href of the new stylesheet to include */ swapStyleSheet : function(id, url) { var ss; CSS.removeStyleSheet(id); ss = doc.createElement("link"); ss.setAttribute("rel", "stylesheet"); ss.setAttribute("type", "text/css"); ss.setAttribute("id", id); ss.setAttribute("href", url); doc.getElementsByTagName("head")[0].appendChild(ss); }, /** * Refresh the rule cache if you have dynamically added stylesheets * @return {Object} An object (hash) of rules indexed by selector */ refreshCache : function() { return CSS.getRules(true); }, // @private cacheStyleSheet : function(ss) { if (!rules) { rules = CSS.rules = {}; } try {// try catch for cross domain access issue var ssRules = ss.cssRules || ss.rules, i = ssRules.length - 1, imports = ss.imports, len = imports ? imports.length : 0, rule, j; // Old IE has a different way of handling imports for (j = 0; j < len; ++j) { CSS.cacheStyleSheet(imports[j]); } for (; i >= 0; --i) { rule = ssRules[i]; // If it's an @import rule, import its stylesheet if (rule.styleSheet) { CSS.cacheStyleSheet(rule.styleSheet); } CSS.cacheRule(rule, ss); } } catch(e) {} }, cacheRule: function(cssRule, styleSheet) { // If it's an @import rule, import its stylesheet if (cssRule.styleSheet) { return CSS.cacheStyleSheet(cssRule.styleSheet); } var selectorText = cssRule.selectorText, selectorCount, j; if (selectorText) { // Split in case there are multiple, comma-delimited selectors selectorText = selectorText.split(','); selectorCount = selectorText.length; for (j = 0; j < selectorCount; j++) { // IE<8 does not keep a reference to parentStyleSheet in the rule, so we // must cache an object like this until IE<8 is deprecated. rules[Ext.String.trim(selectorText[j]).toLowerCase()] = { parentStyleSheet: styleSheet, cssRule: cssRule }; }; } }, /** * Gets all css rules for the document * @param {Boolean} refreshCache true to refresh the internal cache * @return {Object} An object (hash) of rules indexed by selector */ getRules : function(refreshCache) { var result = {}, selector; if (rules === null || refreshCache) { CSS.refreshCache(); } for (selector in rules) { result[selector] = rules[selector].cssRule; } return result; }, refreshCache: function() { var ds = doc.styleSheets, i = 0, len = ds.length; rules = CSS.rules = {} for (; i < len; i++) { try { if (!ds[i].disabled) { CSS.cacheStyleSheet(ds[i]); } } catch(e) {} } }, /** * Gets an an individual CSS rule by selector(s) * @param {String/String[]} selector The CSS selector or an array of selectors to try. The first selector that is found is returned. * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically * @return {CSSStyleRule} The CSS rule or null if one is not found */ getRule: function(selector, refreshCache, rawCache) { var i, result; if (!rules || refreshCache) { CSS.refreshCache(); } if (!Ext.isArray(selector)) { result = rules[selector.toLowerCase()] if (result && !rawCache) { result = result.cssRule; } return result || null; } for (i = 0; i < selector.length; i++) { if (rules[selector[i]]) { return rawCache ? rules[selector[i].toLowerCase()] : rules[selector[i].toLowerCase()].cssRule; } } return null; }, /** * Creates a rule. * @param {CSSStyleSheet} styleSheet The StyleSheet to create the rule in as returned from {@link #createStyleSheet}. * @param {String} selector The selector to target the rule. * @param {String} property The cssText specification eg `"color:red;font-weight:bold;text-decoration:underline"` * @return {CSSStyleRule} The created rule */ createRule: function(styleSheet, selector, cssText) { var result, ruleSet = styleSheet.cssRules || styleSheet.rules, index = ruleSet.length; if (styleSheet.insertRule) { styleSheet.insertRule(selector + '{' + cssText + '}', index); } else { styleSheet.addRule(selector, cssText||' '); } CSS.cacheRule(result = ruleSet[index], styleSheet); return result; }, /** * Updates a rule property * @param {String/String[]} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found. * @param {String} property The css property or a cssText specification eg `"color:red;font-weight:bold;text-decoration:underline"` * @param {String} value The new value for the property * @return {Boolean} true If a rule was found and updated */ updateRule : function(selector, property, value) { var rule, i, styles; if (!Ext.isArray(selector)) { rule = CSS.getRule(selector); if (rule) { // 2 arg form means cssText sent, so parse it and update each style if (arguments.length == 2) { styles = Ext.Element.parseStyles(property); for (property in styles) { rule.style[property.replace(camelRe, camelFn)] = styles[property]; } } else { rule.style[property.replace(camelRe, camelFn)] = value; } return true; } } else { for (i = 0; i < selector.length; i++) { if (CSS.updateRule(selector[i], property, value)) { return true; } } } return false; }, deleteRule: function(selector) { var rule = CSS.getRule(selector, false, true), styleSheet, index; if (rule) { styleSheet = rule.parentStyleSheet; index = Ext.Array.indexOf(styleSheet.cssRules || styleSheet.rules, rule.cssRule); if (styleSheet.deleteRule) { styleSheet.deleteRule(index); } else { styleSheet.removeRule(index); } delete rules[selector]; } } }; }); /** * Component layout for {@link Ext.view.Table} * @private * */ Ext.define('Ext.view.TableLayout', { extend: Ext.layout.component.Auto , alias: ['layout.tableview'], type: 'tableview', beginLayout: function(ownerContext) { var me = this, otherSide = me.owner.lockingPartner, owner = me.owner; me.callParent(arguments); // If we are in a twinned grid (locked view) then set up bidirectional links with the other side's layout context if (otherSide) { me.lockedGrid = me.owner.up('[lockable]'); me.lockedGrid.needsRowHeightSync = true; if (!ownerContext.lockingPartner) { ownerContext.lockingPartner = ownerContext.context.getItem(otherSide, otherSide.el); if (ownerContext.lockingPartner && !ownerContext.lockingPartner.lockingPartner) { ownerContext.lockingPartner.lockingPartner = ownerContext; } } } // Grab a ContextItem for the header container ownerContext.headerContext = ownerContext.context.getCmp(me.headerCt); // Grab ContextItem for the table only if there is a table to size if (me.owner.body.dom) { ownerContext.bodyContext = ownerContext.getEl(me.owner.body); } if (Ext.isWebKit) { owner.el.select(owner.getBodySelector()).setStyle('table-layout', 'auto'); } }, calculate: function(ownerContext) { var me = this, lockingPartner = me.lockingPartner, owner = me.owner, contentHeight = 0, emptyEl; // We can only complete our work (setting the CSS rules governing column widths) if the // Grid's HeaderContainer's ColumnLayout has set the widths of its columns. if (ownerContext.headerContext.hasProp('columnWidthsDone')) { if (!me.setColumnWidths(ownerContext)) { me.done = false; return; } ownerContext.state.columnWidthsSynced = true; if (ownerContext.bodyContext) { emptyEl = me.owner.el.down('.' + owner.ownerCt.emptyCls, true); if (!emptyEl) { contentHeight = ownerContext.bodyContext.el.dom.offsetHeight; ownerContext.bodyContext.setHeight(contentHeight, false); } else { contentHeight = emptyEl.offsetHeight; } // If there is horizontal overflow, and the grid is shrinkwrapping height, then allow the horizontal scrollbar to contibute to contentHeight if (ownerContext.headerContext.state.boxPlan.tooNarrow && ownerContext.ownerCtContext.sizeModel.height.shrinkWrap) { contentHeight += Ext.getScrollbarSize().height; } ownerContext.setProp('contentHeight', contentHeight); } // If we are part of a twinned table view set (locking grid) // Then only complete when both sides are complete. if (lockingPartner && !lockingPartner.state.columnWidthsSynced) { me.done = false; } else { me.callParent(arguments); } } else { me.done = false; } }, measureContentHeight: function(ownerContext) { var lockingPartner = ownerContext.lockingPartner; // Only able to produce a valid contentHeight if there's no table // ... or we have flushed all column widths to the table (or both tables if we are a pair) if (!ownerContext.bodyContext || (ownerContext.state.columnWidthsSynced && (!lockingPartner || lockingPartner.state.columnWidthsSynced))) { return this.callParent(arguments); } }, setColumnWidths: function(ownerContext) { var me = this, owner = me.owner, context = ownerContext.context, columns = me.headerCt.getVisibleGridColumns(), column, i = 0, len = columns.length, tableWidth = 0, columnLineWidth = 0, childContext, colWidth, isContentBox = !Ext.isBorderBox; // So that the setProp can trigger this layout. if (context) { context.currentLayout = me; } // Set column width corresponding to each header for (i = 0; i < len; i++) { column = columns[i]; childContext = context.getCmp(column); colWidth = childContext.props.width; if (isNaN(colWidth)) { // We don't have a width set, so we need to trigger when this child // actually gets a width assigned so we can continue. Technically this // shouldn't happen however we have a bug inside ColumnLayout where // columnWidthsDone is set incorrectly. This is just a workaround. childContext.getProp('width'); return false; } tableWidth += colWidth; // https://sencha.jira.com/browse/EXTJSIV-9263 - Browsers which cannot be switched to border box when doctype present (IE6 & IE7) - must subtract borders width from width of cells. if (isContentBox && owner.columnLines) { // https://sencha.jira.com/browse/EXTJSIV-9744 - default border width to 1 because // We are looking at the *header* border widths and Neptune, being a borderless theme // omits the border from the last column *HEADER*. But we are interrogating that to // know the width of border lines between cells which are not omitted. if (!columnLineWidth) { columnLineWidth = context.getCmp(column).borderInfo.width || 1; } colWidth -= columnLineWidth; } // Select column sizing elements within every within the grid. // 90% of the time, there will be only one table. // The RowWrap and Summary Features embed tables within colspanning cells, and these also // get sizers which need updating. // On IE8, sizing elements to control column width was about 2.25 times // faster than selecting all the cells in the column to be resized. // Column sizing using dynamic CSS rules is *extremely* expensive on IE. owner.body.select(owner.getColumnSizerSelector(column)).setWidth(colWidth); } // Set widths of all tables (includes tables embedded in RowWrap and Summary rows) owner.el.select(owner.getBodySelector()).setWidth(tableWidth); return true; }, finishedLayout: function() { var me = this, owner = me.owner; me.callParent(arguments); if (Ext.isWebKit) { owner.el.select(owner.getBodySelector()).setStyle('table-layout', ''); } // Make sure only one side gets to do the sync on completion - it's an expensive process. // Only do it if the syncRowHeightConfig hasn't been set to false. if (owner.refreshCounter && me.lockedGrid && me.lockedGrid.syncRowHeight && me.lockedGrid.needsRowHeightSync) { me.lockedGrid.syncRowHeights(); me.lockedGrid.needsRowHeightSync = false; } } }); /** * @private * A cache of View elements keyed using the index of the associated record in the store. * * This implements the methods of {Ext.dom.CompositeElement} which are used by {@link Ext.view.AbstractView} * to privide a map of record nodes and methods to manipulate the nodes. */ Ext.define('Ext.view.NodeCache', { constructor: function(view) { this.view = view; this.clear(); this.el = new Ext.dom.AbstractElement.Fly(); }, /** * Removes all elements from this NodeCache. * @param {Boolean} [removeDom] True to also remove the elements from the document. */ clear: function(removeDom) { var me = this, elements = this.elements, i, el; if (removeDom) { for (i in elements) { el = elements[i]; el.parentNode.removeChild(el); } } me.elements = {}; me.count = me.startIndex = 0; me.endIndex = -1; }, /** * Clears this NodeCache and adds the elements passed. * @param {HTMLElement[]} els An array of DOM elements from which to fill this NodeCache. * @return {Ext.view.NodeCache} this */ fill: function(newElements, startIndex) { var me = this, elements = me.elements = {}, i, len = newElements.length; if (!startIndex) { startIndex = 0; } for (i = 0; i < len; i++) { elements[startIndex + i] = newElements[i]; } me.startIndex = startIndex; me.endIndex = startIndex + len - 1; me.count = len; return this; }, insert: function(insertPoint, nodes) { var me = this, elements = me.elements, i, nodeCount = nodes.length; // If not inserting into empty cache, validate, and possibly shuffle. if (me.count) { // Move following nodes forwards by positions if (insertPoint < me.count) { for (i = me.endIndex + nodeCount; i >= insertPoint + nodeCount; i--) { elements[i] = elements[i - nodeCount]; elements[i].setAttribute('data-recordIndex', i); } } me.endIndex = me.endIndex + nodeCount; } // Empty cache. set up counters else { me.startIndex = insertPoint; me.endIndex = insertPoint + nodeCount - 1; } // Insert new nodes into place for (i = 0; i < nodeCount; i++, insertPoint++) { elements[insertPoint] = nodes[i]; elements[insertPoint].setAttribute('data-recordIndex', insertPoint); } me.count += nodeCount; }, item: function(index, asDom) { var el = this.elements[index], result = null; if (el) { result = asDom ? this.elements[index] : this.el.attach(this.elements[index]); } return result; }, first: function(asDom) { return this.item(this.startIndex, asDom); }, last: function(asDom) { return this.item(this.endIndex, asDom); }, getCount : function() { return this.count; }, slice: function(start, end) { var elements = this.elements, result = [], i; if (arguments.length < 2) { end = this.endIndex; } else { end = Math.min(this.endIndex, end - 1); } for (i = start||this.startIndex; i <= end; i++) { result.push(elements[i]); } return result; }, /** * Replaces the specified element with the passed element. * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, the Element itself, the index of the * element in this composite to replace. * @param {String/Ext.Element} replacement The id of an element or the Element itself. * @param {Boolean} [domReplace] True to remove and replace the element in the document too. */ replaceElement: function(el, replacement, domReplace) { var elements = this.elements, index = (typeof el === 'number') ? el : this.indexOf(el); if (index > -1) { replacement = Ext.getDom(replacement); if (domReplace) { el = elements[index]; el.parentNode.insertBefore(replacement, el); Ext.removeNode(el); replacement.setAttribute('data-recordIndex', index); } this.elements[index] = replacement; } return this; }, /** * Find the index of the passed element within the composite collection. * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, or an Ext.dom.Element, or an HtmlElement * to find within the composite collection. * @return {Number} The index of the passed Ext.dom.Element in the composite collection, or -1 if not found. */ indexOf: function(el) { var elements = this.elements, index; el = Ext.getDom(el); for (index = this.startIndex; index <= this.endIndex; index++) { if (elements[index] === el) { return index; } } return -1; }, removeRange: function(start, end, removeDom) { var me = this, elements = me.elements, el, i, removeCount, fromPos; if (end === undefined) { end = me.count; } else { end = Math.min(me.endIndex + 1, end + 1); } if (!start) { start = 0; } removeCount = end - start; for (i = start, fromPos = end; i < me.endIndex; i++, fromPos++) { // Within removal range and we are removing from DOM if (removeDom && i < end) { Ext.removeNode(elements[i]); } // If the from position is occupied, shuffle that entry back into reference "i" if (fromPos <= me.endIndex) { el = elements[i] = elements[fromPos]; el.setAttribute('data-recordIndex', i); } // The from position has walked off the end, so delete reference "i" else { delete elements[i]; } } me.count -= removeCount; me.endIndex -= removeCount; }, /** * Removes the specified element(s). * @param {String/HTMLElement/Ext.Element/Number} el The id of an element, the Element itself, the index of the * element in this composite or an array of any of those. * @param {Boolean} [removeDom] True to also remove the element from the document */ removeElement: function(keys, removeDom) { var me = this, inKeys, key, elements = me.elements, el, deleteCount, keyIndex = 0, index, fromIndex; // Sort the keys into ascending order so that we can iterate through the elements // collection, and delete items encountered in the keys array as we encounter them. if (Ext.isArray(keys)) { inKeys = keys; keys = []; deleteCount = inKeys.length; for (keyIndex = 0; keyIndex < deleteCount; keyIndex++) { key = inKeys[keyIndex]; if (typeof key !== 'number') { key = me.indexOf(key); } // Could be asked to remove data above the start, or below the end of rendered zone in a buffer rendered view // So only collect keys which are within our range if (key >= me.startIndex && key <= me.endIndex) { keys[keys.length] = key; } } Ext.Array.sort(keys); deleteCount = keys.length; } else { // Could be asked to remove data above the start, or below the end of rendered zone in a buffer rendered view if (keys < me.startIndex || keys > me.endIndex) { return; } deleteCount = 1; keys = [keys]; } // Iterate through elements starting at the element referenced by the first deletion key. // We also start off and index zero in the keys to delete array. for (index = fromIndex = keys[0], keyIndex = 0; index <= me.endIndex; index++, fromIndex++) { // If the current index matches the next key in the delete keys array, this // entry is being deleted, so increment the fromIndex to skip it. // Advance to next entry in keys array. if (keyIndex < deleteCount && index === keys[keyIndex]) { fromIndex++; keyIndex++; if (removeDom) { Ext.removeNode(elements[index]); } } // Shuffle entries forward of the delete range back into contiguity. if (fromIndex <= me.endIndex && fromIndex >= me.startIndex) { el = elements[index] = elements[fromIndex]; el.setAttribute('data-recordIndex', index); } else { delete elements[index]; } } me.endIndex -= deleteCount; me.count -= deleteCount; }, /** * Appends/prepends records depending on direction flag * @param {Ext.data.Model[]} newRecords Items to append/prepend * @param {Number} direction `-1' = scroll up, `0` = scroll down. * @param {Number} removeCount The number of records to remove from the end. if scrolling * down, rows are removed from the top and the new rows are added at the bottom. */ scroll: function(newRecords, direction, removeCount) { var me = this, elements = me.elements, recCount = newRecords.length, i, el, removeEnd, newNodes, nodeContainer = me.view.getNodeContainer(), frag = document.createDocumentFragment(); // Scrolling up (content moved down - new content needed at top, remove from bottom) if (direction == -1) { for (i = (me.endIndex - removeCount) + 1; i <= me.endIndex; i++) { el = elements[i]; delete elements[i]; el.parentNode.removeChild(el); } me.endIndex -= removeCount; // grab all nodes rendered, not just the data rows newNodes = me.view.bufferRender(newRecords, me.startIndex -= recCount); for (i = 0; i < recCount; i++) { elements[me.startIndex + i] = newNodes[i]; frag.appendChild(newNodes[i]); } nodeContainer.insertBefore(frag, nodeContainer.firstChild); } // Scrolling down (content moved up - new content needed at bottom, remove from top) else { removeEnd = me.startIndex + removeCount; for (i = me.startIndex; i < removeEnd; i++) { el = elements[i]; delete elements[i]; el.parentNode.removeChild(el); } me.startIndex = i; // grab all nodes rendered, not just the data rows newNodes = me.view.bufferRender(newRecords, me.endIndex + 1); for (i = 0; i < recCount; i++) { elements[me.endIndex += 1] = newNodes[i]; frag.appendChild(newNodes[i]); } nodeContainer.appendChild(frag); } // Keep count consistent. me.count = me.endIndex - me.startIndex + 1; } }); /** * This class encapsulates the user interface for a tabular data set. * It acts as a centralized manager for controlling the various interface * elements of the view. This includes handling events, such as row and cell * level based DOM events. It also reacts to events from the underlying {@link Ext.selection.Model} * to provide visual feedback to the user. * * This class does not provide ways to manipulate the underlying data of the configured * {@link Ext.data.Store}. * * This is the base class for both {@link Ext.grid.View} and {@link Ext.tree.View} and is not * to be used directly. */ Ext.define('Ext.view.Table', { extend: Ext.view.View , alias: 'widget.tableview', componentLayout: 'tableview', baseCls: Ext.baseCSSPrefix + 'grid-view', unselectableCls: Ext.baseCSSPrefix + 'unselectable', /** * @cfg {String} [firstCls='x-grid-cell-first'] * A CSS class to add to the *first* cell in every row to enable special styling for the first column. * If no styling is needed on the first column, this may be configured as `null`. */ firstCls: Ext.baseCSSPrefix + 'grid-cell-first', /** * @cfg {String} [lastCls='x-grid-cell-last'] * A CSS class to add to the *last* cell in every row to enable special styling for the last column. * If no styling is needed on the last column, this may be configured as `null`. */ lastCls: Ext.baseCSSPrefix + 'grid-cell-last', headerRowSelector: 'tr.' + Ext.baseCSSPrefix + 'grid-header-row', selectedItemCls: Ext.baseCSSPrefix + 'grid-row-selected', beforeSelectedItemCls: Ext.baseCSSPrefix + 'grid-row-before-selected', selectedCellCls: Ext.baseCSSPrefix + 'grid-cell-selected', focusedItemCls: Ext.baseCSSPrefix + 'grid-row-focused', beforeFocusedItemCls: Ext.baseCSSPrefix + 'grid-row-before-focused', tableFocusedFirstCls: Ext.baseCSSPrefix + 'grid-table-focused-first', tableSelectedFirstCls: Ext.baseCSSPrefix + 'grid-table-selected-first', tableOverFirstCls: Ext.baseCSSPrefix + 'grid-table-over-first', overItemCls: Ext.baseCSSPrefix + 'grid-row-over', beforeOverItemCls: Ext.baseCSSPrefix + 'grid-row-before-over', altRowCls: Ext.baseCSSPrefix + 'grid-row-alt', dirtyCls: Ext.baseCSSPrefix + 'grid-dirty-cell', rowClsRe: new RegExp('(?:^|\\s*)' + Ext.baseCSSPrefix + 'grid-row-(first|last|alt)(?:\\s+|$)', 'g'), cellRe: new RegExp(Ext.baseCSSPrefix + 'grid-cell-headerId-([^\\s]+)(?:\\s|$)', ''), positionBody: true, // cfg docs inherited trackOver: true, /** * Override this function to apply custom CSS classes to rows during rendering. This function should return the * CSS class name (or empty string '' for none) that will be added to the row's wrapping div. To apply multiple * class names, simply return them space-delimited within the string (e.g. 'my-class another-class'). * Example usage: * * viewConfig: { * getRowClass: function(record, rowIndex, rowParams, store){ * return record.get("valid") ? "row-valid" : "row-error"; * } * } * * @param {Ext.data.Model} record The record corresponding to the current row. * @param {Number} index The row index. * @param {Object} rowParams **DEPRECATED.** For row body use the * {@link Ext.grid.feature.RowBody#getAdditionalData getAdditionalData} method of the rowbody feature. * @param {Ext.data.Store} store The store this grid is bound to * @return {String} a CSS class name to add to the row. * @method */ getRowClass: null, /** * @cfg {Boolean} stripeRows * True to stripe the rows. * * This causes the CSS class **`x-grid-row-alt`** to be added to alternate rows of * the grid. A default CSS rule is provided which sets a background color, but you can override this * with a rule which either overrides the **background-color** style using the `!important` * modifier, or which uses a CSS selector of higher specificity. */ stripeRows: true, /** * @cfg {Boolean} markDirty * True to show the dirty cell indicator when a cell has been modified. */ markDirty : true, /** * @cfg {Boolean} enableTextSelection * True to enable text selections. */ ariaRole: 'grid', /** * @private * Simple initial tpl for TableView just to satisfy the validation within AbstractView.initComponent. */ tpl: '{%values.view.tableTpl.applyOut(values, out)%}', tableTpl: [ '{%', 'var view=values.view,tableCls="' + Ext.baseCSSPrefix + '" + view.id + "-table ' + Ext.baseCSSPrefix + 'grid-table";', '%}', '
', '{[view.renderColumnSizer(out)]}', '{[view.renderTHead(values, out)]}', '{[view.renderTFoot(values, out)]}', '', '{%', 'view.renderRows(values.rows, values.viewStartIndex, out);', '%}', '', '
', { priority: 0 } ], rowTpl: [ '{%', 'var dataRowCls = values.recordIndex === -1 ? "" : " ' + Ext.baseCSSPrefix + 'grid-data-row";', '%}', '', '' + '{%', 'parent.view.renderCell(values, parent.record, parent.recordIndex, parent.rowIndex, xindex - 1, out, parent)', '%}', '', '', { priority: 0 } ], cellTpl: [ '', '
{style}" {ariaCellInnerAttr}>{value}
', '', { priority: 0 } ], /** * @private * Flag to disable refreshing SelectionModel on view refresh. Table views render rows with selected CSS class already added if necessary. */ refreshSelmodelOnRefresh: false, tableValues: {}, // Private properties used during the row and cell render process. // They are allocated here on the prototype, and cleared/re-used to avoid GC churn during repeated rendering. rowValues: { itemClasses: [], rowClasses: [] }, cellValues: { classes: [ Ext.baseCSSPrefix + 'grid-cell ' + Ext.baseCSSPrefix + 'grid-td' // for styles shared between cell and rowwrap ] }, /// Private used for buffered rendering renderBuffer: document.createElement('div'), constructor: function(config) { // Adjust our base class if we are inside a TreePanel if (config.grid.isTree) { config.baseCls = Ext.baseCSSPrefix + 'tree-view'; } this.callParent([config]); }, initComponent: function() { var me = this, scroll = me.scroll; this.addEvents( /** * @event beforecellclick * Fired before the cell click is processed. Return false to cancel the default action. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'beforecellclick', /** * @event cellclick * Fired when table cell is clicked. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'cellclick', /** * @event beforecelldblclick * Fired before the cell double click is processed. Return false to cancel the default action. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'beforecelldblclick', /** * @event celldblclick * Fired when table cell is double clicked. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'celldblclick', /** * @event beforecellcontextmenu * Fired before the cell right click is processed. Return false to cancel the default action. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'beforecellcontextmenu', /** * @event cellcontextmenu * Fired when table cell is right clicked. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'cellcontextmenu', /** * @event beforecellmousedown * Fired before the cell mouse down is processed. Return false to cancel the default action. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'beforecellmousedown', /** * @event cellmousedown * Fired when the mousedown event is captured on the cell. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'cellmousedown', /** * @event beforecellmouseup * Fired before the cell mouse up is processed. Return false to cancel the default action. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'beforecellmouseup', /** * @event cellmouseup * Fired when the mouseup event is captured on the cell. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'cellmouseup', /** * @event beforecellkeydown * Fired before the cell key down is processed. Return false to cancel the default action. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'beforecellkeydown', /** * @event cellkeydown * Fired when the keydown event is captured on the cell. * @param {Ext.view.Table} this * @param {HTMLElement} td The TD element for the cell. * @param {Number} cellIndex * @param {Ext.data.Model} record * @param {HTMLElement} tr The TR element for the cell. * @param {Number} rowIndex * @param {Ext.EventObject} e */ 'cellkeydown' ); /** * @private * @property {Ext.dom.AbstractElement.Fly} body * A flyweight Ext.Element which encapsulates a reference to the view's main row containing element. * *Note that the `dom` reference will not be present until the first data refresh* */ me.body = new Ext.dom.Element.Fly(); me.body.id = me.id + 'gridBody'; // Scrolling within a TableView is controlled by the scroll config of its owning GridPanel // It must see undefined in this property in order to leave the scroll styles alone at afterRender time me.autoScroll = undefined; // If trackOver has been turned off, null out the overCls because documented behaviour // in AbstractView is to turn trackOver on if overItemCls is set. if (!me.trackOver) { me.overItemCls = null; me.beforeOverItemCls = null; } // Convert grid scroll config to standard Component scrolling configurations. if (scroll === true || scroll === 'both') { me.autoScroll = true; } else if (scroll === 'horizontal') { me.overflowX = 'auto'; } else if (scroll === 'vertical') { me.overflowY = 'auto'; } me.selModel.view = me.headerCt.view = me; // Features need a reference to the grid. // Grid needs an immediate reference to its view so that the view can reliably be got from the grid during initialization me.grid.view = me; me.initFeatures(me.grid); delete me.grid; me.itemSelector = me.getItemSelector(); me.all = new Ext.view.NodeCache(me); me.callParent(); }, getVisibleColumnManager: function(){ var owner = this.ownerCt, lock = owner.ownerLockable; return lock ? lock.getVisibleColumnManager() : owner.getVisibleColumnManager(); }, /** * @private * Move a grid column from one position to another * @param {Number} fromIdx The index from which to move columns * @param {Number} toIdx The index at which to insert columns. * @param {Number} [colsToMove=1] The number of columns to move beginning at the `fromIdx` */ moveColumn: function(fromIdx, toIdx, colsToMove) { var me = this, fragment = (colsToMove > 1) ? document.createDocumentFragment() : undefined, destinationCellIdx = toIdx, colCount = me.getGridColumns().length, lastIndex = colCount - 1, doFirstLastClasses = (me.firstCls || me.lastCls) && (toIdx === 0 || toIdx == colCount || fromIdx === 0 || fromIdx == lastIndex), i, j, rows, len, tr, cells, tables; // Dragging between locked and unlocked side first refreshes the view, and calls onHeaderMoved with // fromIndex and toIndex the same. if (me.rendered && toIdx !== fromIdx) { // Grab all rows which have column cells in. // That is data rows and column sizing rows. rows = me.el.query(me.getDataRowSelector()); if (toIdx > fromIdx && fragment) { destinationCellIdx -= colsToMove; } for (i = 0, len = rows.length; i < len; i++) { tr = rows[i]; cells = tr.childNodes; // Keep first cell class and last cell class correct *only if needed* if (doFirstLastClasses) { if (cells.length === 1) { Ext.fly(cells[0]).addCls(me.firstCls); Ext.fly(cells[0]).addCls(me.lastCls); continue; } if (fromIdx === 0) { Ext.fly(cells[0]).removeCls(me.firstCls); Ext.fly(cells[1]).addCls(me.firstCls); } else if (fromIdx === lastIndex) { Ext.fly(cells[lastIndex]).removeCls(me.lastCls); Ext.fly(cells[lastIndex - 1]).addCls(me.lastCls); } if (toIdx === 0) { Ext.fly(cells[0]).removeCls(me.firstCls); Ext.fly(cells[fromIdx]).addCls(me.firstCls); } else if (toIdx === colCount) { Ext.fly(cells[lastIndex]).removeCls(me.lastCls); Ext.fly(cells[fromIdx]).addCls(me.lastCls); } } if (fragment) { for (j = 0; j < colsToMove; j++) { fragment.appendChild(cells[fromIdx]); } tr.insertBefore(fragment, cells[destinationCellIdx] || null); } else { tr.insertBefore(cells[fromIdx], cells[destinationCellIdx] || null); } } // Shuffle the elements at the ta=op of all in the grid tables = me.el.query(me.getBodySelector()); for (i = 0, len = tables.length; i < len; i++) { tr = tables[i]; if (fragment) { for (j = 0; j < colsToMove; j++) { fragment.appendChild(tr.childNodes[fromIdx]); } tr.insertBefore(fragment, tr.childNodes[destinationCellIdx] || null); } else { tr.insertBefore(tr.childNodes[fromIdx], tr.childNodes[destinationCellIdx] || null); } } } }, // scroll the view to the top scrollToTop: Ext.emptyFn, /** * Add a listener to the main view element. It will be destroyed with the view. * @private */ addElListener: function(eventName, fn, scope){ this.mon(this, eventName, fn, scope, { element: 'el' }); }, /** * Get the leaf columns used for rendering the grid rows. * @private */ getGridColumns: function() { return this.ownerCt.getVisibleColumnManager().getColumns(); }, /** * Get a leaf level header by index regardless of what the nesting * structure is. * @private * @param {Number} index The index */ getHeaderAtIndex: function(index) { return this.ownerCt.getVisibleColumnManager().getHeaderAtIndex(index); }, /** * Get the cell (td) for a particular record and column. * @param {Ext.data.Model} record * @param {Ext.grid.column.Column} column * @private */ getCell: function(record, column) { var row = this.getNode(record, true); return Ext.fly(row).down(column.getCellSelector()); }, /** * Get a reference to a feature * @param {String} id The id of the feature * @return {Ext.grid.feature.Feature} The feature. Undefined if not found */ getFeature: function(id) { var features = this.featuresMC; if (features) { return features.get(id); } }, // @private // Finds a features by ftype in the features array findFeature: function(ftype) { if (this.features) { return Ext.Array.findBy(this.features, function(feature) { if (feature.ftype === ftype) { return true; } }); } }, /** * Initializes each feature and bind it to this view. * @private */ initFeatures: function(grid) { var me = this, i, features, feature, len; me.tableTpl = Ext.XTemplate.getTpl(this, 'tableTpl'); me.rowTpl = Ext.XTemplate.getTpl(this, 'rowTpl'); me.cellTpl = Ext.XTemplate.getTpl(this, 'cellTpl'); me.featuresMC = new Ext.util.MixedCollection(); features = me.features = me.constructFeatures(); len = features ? features.length : 0; for (i = 0; i < len; i++) { feature = features[i]; // inject a reference to view and grid - Features need both feature.view = me; feature.grid = grid; me.featuresMC.add(feature); feature.init(grid); } }, renderTHead: function(values, out) { var headers = values.view.headerFns, len, i; if (headers) { for (i = 0, len = headers.length; i < len; ++i) { headers[i].call(this, values, out); } } }, // Currently, we don't have ordering support for header/footer functions, // they will be pushed on at construction time. If the need does arise, // we can add this functionality in the future, but for now it's not // really necessary since currently only the summary feature uses this. addHeaderFn: function(){ var headers = this.headerFns; if (!headers) { headers = this.headerFns = []; } headers.push(fn); }, renderTFoot: function(values, out){ var footers = values.view.footerFns, len, i; if (footers) { for (i = 0, len = footers.length; i < len; ++i) { footers[i].call(this, values, out); } } }, addFooterFn: function(fn){ var footers = this.footerFns; if (!footers) { footers = this.footerFns = []; } footers.push(fn); }, addTableTpl: function(newTpl) { return this.addTpl('tableTpl', newTpl); }, addRowTpl: function(newTpl) { return this.addTpl('rowTpl', newTpl); }, addCellTpl: function(newTpl) { return this.addTpl('cellTpl', newTpl); }, addTpl: function(which, newTpl) { var me = this, tpl, prevTpl; newTpl = Ext.Object.chain(newTpl); // If we have been passed an object of the form // { // before: fn // after: fn // } if (!newTpl.isTemplate) { newTpl.applyOut = me.tplApplyOut; } // Stop at the first TPL who's priority is less than the passed rowTpl for (tpl = me[which]; newTpl.priority < tpl.priority; tpl = tpl.nextTpl) { prevTpl = tpl; } // If we had skipped over some, link the previous one to the passed rowTpl if (prevTpl) { prevTpl.nextTpl = newTpl; } // First one else { me[which] = newTpl; } newTpl.nextTpl = tpl; return newTpl; }, tplApplyOut: function(values, out) { if (this.before) { if (this.before(values, out) === false) { return; } } this.nextTpl.applyOut(values, out); if (this.after) { this.after(values, out); } }, /** * @private * Converts the features array as configured, into an array of instantiated Feature objects. * * Must have no side effects other than Feature instantiation. * * MUST NOT update the this.features property, and MUST NOT update the instantiated Features. */ constructFeatures: function() { var me = this, features = me.features, feature, result, i = 0, len; if (features) { result = []; len = features.length; for (; i < len; i++) { feature = features[i]; if (!feature.isFeature) { feature = Ext.create('feature.' + feature.ftype, feature); } result[i] = feature; } } return result; }, beforeRender: function() { var me = this; me.callParent(); if (!me.enableTextSelection) { me.protoEl.unselectable(); } }, // Private template method implemented starting at the AbstractView class. onViewScroll: function(e, t) { // We ignore scrolling caused by focusing if (!this.ignoreScroll) { this.callParent(arguments); this.fireEvent('bodyscroll', e, t); } }, // private // Create the DOM element which enapsulates the passed record. // Used when updating existing rows, so drills down into resulting structure . createRowElement: function(record, index) { var me = this, div = me.renderBuffer; me.tpl.overwrite(div, me.collectData([record], index)); // Return first element within node containing element return Ext.fly(div).down(me.getNodeContainerSelector(), true).firstChild; }, // private // Override so that we can use a quicker way to access the row nodes. // They are simply all child nodes of the TBODY element. bufferRender: function(records, index) { var me = this, div = me.renderBuffer; me.tpl.overwrite(div, me.collectData(records, index)); return Ext.Array.toArray(Ext.fly(div).down(me.getNodeContainerSelector(), true).childNodes); }, collectData: function(records, startIndex) { this.rowValues.view = this; return { view: this, rows: records, viewStartIndex: startIndex, tableStyle: this.bufferedRenderer ? ('position:absolute;top:' + this.bufferedRenderer.bodyTop) : '' }; }, // Overridden implementation. // Called by refresh to collect the view item nodes. // Note that these may be wrapping rows which *contain* rows which map to records collectNodes: function(targetEl) { this.all.fill(this.getNodeContainer().childNodes, this.all.startIndex); }, // Private. Called when the table changes height. // For example, see examples/grid/group-summary-grid.html // If we have flexed column headers, we need to update the header layout // because it may have to accommodate (or cease to accommodate) a vertical scrollbar. // Only do this on platforms which have a space-consuming scrollbar. // Only do it when vertical scrolling is enabled. refreshSize: function() { var me = this, grid, bodySelector = me.getBodySelector(); // On every update of the layout system due to data update, capture the view's main element in our private flyweight. // IF there *is* a main element. Some TplFactories emit naked rows. if (bodySelector) { me.body.attach(me.el.child(bodySelector, true)); } if (!me.hasLoadingHeight) { grid = me.up('tablepanel'); // Suspend layouts in case the superclass requests a layout. We might too, so they // must be coalescsed. Ext.suspendLayouts(); me.callParent(); // Since columns and tables are not sized by generated CSS rules any more, EVERY table refresh // has to be followed by a layout to ensure correct table and column sizing. grid.updateLayout(); Ext.resumeLayouts(true); } }, statics: { getBoundView: function(node) { return Ext.getCmp(node.getAttribute('data-boundView')); } }, getRecord: function(node) { var me = this, recordIndex; // If store.destroyStore has been called before some delayed event fires on a node, we must ignore the event. if (me.store.isDestroyed) { return; } node = me.getNode(node); if (node) { // If we're grouping, the indexes may be off // because of collapsed groups, so just grab it by id if (!me.hasActiveGrouping()) { recordIndex = node.getAttribute('data-recordIndex'); if (recordIndex) { recordIndex = parseInt(recordIndex, 10); if (recordIndex > -1) { // The index is the index in the original Store, not in a GroupStore // The Grouping Feature increments the index to skip over unrendered records in collapsed groups return me.store.data.getAt(recordIndex); } } } return me.store.getByInternalId(node.getAttribute('data-recordId')); } }, indexOf: function(node) { node = this.getNode(node, false); if (!node && node !== 0) { return -1; } return this.all.indexOf(node); }, indexInStore: function(node) { node = node.isCollapsedPlaceholder ? this.getNode(node) : this.getNode(node, false); if (!node && node !== 0) { return -1; } var recordIndex = node.getAttribute('data-recordIndex'); if (recordIndex) { return parseInt(recordIndex, 10); } return this.dataSource.indexOf(this.getRecord(node)); }, renderRows: function(rows, viewStartIndex, out) { var rowValues = this.rowValues, rowCount = rows.length, i; rowValues.view = this; rowValues.columns = this.ownerCt.getVisibleColumnManager().getColumns(); for (i = 0; i < rowCount; i++, viewStartIndex++) { rowValues.itemClasses.length = rowValues.rowClasses.length = 0; this.renderRow(rows[i], viewStartIndex, out); } // Dereference objects since rowValues is a persistent on our prototype rowValues.view = rowValues.columns = rowValues.record = null; }, /* Alternative column sizer element renderer. renderTHeadColumnSizer: function(out) { var columns = this.getGridColumns(), len = columns.length, i, column, width; out.push(''); for (i = 0; i < len; i++) { column = columns[i]; width = column.hidden ? 0 : (column.lastBox ? column.lastBox.width : Ext.grid.header.Container.prototype.defaultWidth); out.push(''); } out.push(''); }, */ renderColumnSizer: function(out) { var columns = this.getGridColumns(), len = columns.length, i, column, width; for (i = 0; i < len; i++) { column = columns[i]; width = column.hidden ? 0 : (column.lastBox ? column.lastBox.width : Ext.grid.header.Container.prototype.defaultWidth); out.push(''); } }, /** * @private * Renders the HTML markup string for a single row into the passed array as a sequence of strings, or * returns the HTML markup for a single row. * * @param {Ext.data.Model} record The record to render. * @param {String[]} [out] A string array onto which to append the resulting HTML string. If omitted, * the resulting HTML string is returned. * @return {String} **only when the out parameter is omitted** The resulting HTML string. */ renderRow: function(record, rowIdx, out) { var me = this, isMetadataRecord = rowIdx === -1, selModel = me.selModel, rowValues = me.rowValues, itemClasses = rowValues.itemClasses, rowClasses = rowValues.rowClasses, cls, rowTpl = me.rowTpl; // Set up mandatory properties on rowValues rowValues.record = record; rowValues.recordId = record.internalId; // recordIndex is index in true store (NOT the data source - possibly a GroupStore) rowValues.recordIndex = me.store.indexOf(record); // rowIndex is the row number in the view. rowValues.rowIndex = rowIdx; rowValues.rowId = me.getRowId(record); rowValues.itemCls = rowValues.rowCls = ''; if (!rowValues.columns) { rowValues.columns = me.ownerCt.getVisibleColumnManager().getColumns(); } itemClasses.length = rowClasses.length = 0; // If it's a metadata record such as a summary record. // So do not decorate it with the regular CSS. // The Feature which renders it must know how to decorate it. if (!isMetadataRecord) { itemClasses[0] = Ext.baseCSSPrefix + "grid-row"; if (!me.ownerCt.disableSelection && selModel.isRowSelected) { // Selection class goes on the outermost row, so it goes into itemClasses if (selModel.isRowSelected(record)) { itemClasses.push(me.selectedItemCls); } /* TODO: When merging into sencha-5.0.x branch. These classes should be pushed into the itemClasses array to go on the outermost view item element */ // Ensure selection class is added to selected records, and to the record *before* any selected record // When looking ahead to see if the next record is selected, ensure we do not look past the end! if (me.rowValues.recordIndex < me.store.getTotalCount() - 1 && selModel.isRowSelected(me.rowValues.recordIndex + 1) && !me.isRowStyleFirst(rowIdx + 1)) { rowClasses.push(me.beforeSelectedItemCls); } } if (me.stripeRows && rowIdx % 2 !== 0) { rowClasses.push(me.altRowCls); } if (me.getRowClass) { cls = me.getRowClass(record, rowIdx, null, me.dataSource); if (cls) { rowClasses.push(cls); } } } if (out) { rowTpl.applyOut(rowValues, out); } else { return rowTpl.apply(rowValues); } }, /** * @private * Emits the HTML representing a single grid cell into the passed output stream (which is an array of strings). * * @param {Ext.grid.column.Column} column The column definition for which to render a cell. * @param {Number} recordIndex The row index (zero based within the {@link #store}) for which to render the cell. * @param {Number} rowIndex The row index (zero based within this view for which to render the cell. * @param {Number} columnIndex The column index (zero based) for which to render the cell. * @param {String[]} out The output stream into which the HTML strings are appended. */ renderCell: function(column, record, recordIndex, rowIndex, columnIndex, out) { var me = this, selModel = me.selModel, cellValues = me.cellValues, classes = cellValues.classes, fieldValue = record.data[column.dataIndex], cellTpl = me.cellTpl, fullIndex, value, clsInsertPoint; cellValues.record = record; cellValues.column = column; cellValues.recordIndex = recordIndex; cellValues.rowIndex = rowIndex; cellValues.columnIndex = columnIndex; cellValues.cellIndex = columnIndex; cellValues.align = column.align; cellValues.tdCls = column.tdCls; cellValues.innerCls = column.innerCls; cellValues.style = cellValues.tdAttr = ""; cellValues.unselectableAttr = me.enableTextSelection ? '' : 'unselectable="on"'; if (column.renderer && column.renderer.call) { fullIndex = me.ownerCt.columnManager.getHeaderIndex(column); value = column.renderer.call(column.scope || me.ownerCt, fieldValue, cellValues, record, recordIndex, fullIndex, me.dataSource, me); if (cellValues.css) { // This warning attribute is used by the compat layer // TODO: remove when compat layer becomes deprecated record.cssWarning = true; cellValues.tdCls += ' ' + cellValues.css; delete cellValues.css; } } else { value = fieldValue; } cellValues.value = (value == null || value === '') ? ' ' : value; // Calculate classes to add to cell classes[1] = column.getCellId(); // On IE8, array[len] = 'foo' is twice as fast as array.push('foo') // So keep an insertion point and use assignment to help IE! clsInsertPoint = 2; if (column.tdCls) { classes[clsInsertPoint++] = column.tdCls; } if (me.markDirty && record.isModified(column.dataIndex)) { classes[clsInsertPoint++] = me.dirtyCls; } if (column.isFirstVisible) { classes[clsInsertPoint++] = me.firstCls; } if (column.isLastVisible) { classes[clsInsertPoint++] = me.lastCls; } if (!me.enableTextSelection) { classes[clsInsertPoint++] = me.unselectableCls; } if (cellValues.tdCls) { classes[clsInsertPoint++] = cellValues.tdCls; } if (selModel && selModel.isCellModel && selModel.isCellSelected(me, recordIndex, columnIndex)) { classes[clsInsertPoint++] = (me.selectedCellCls); } // Chop back array to only what we've set classes.length = clsInsertPoint; cellValues.tdCls = classes.join(' '); cellTpl.applyOut(cellValues, out); // Dereference objects since cellValues is a persistent var in the XTemplate's scope chain cellValues.column = null; }, /** * Returns the node given the passed Record, or index or node. * @param {HTMLElement/String/Number/Ext.data.Model} nodeInfo The node or record * @param {Boolean} [dataRow] `true` to return the data row (not the top level row if wrapped), `false` * to return the top level row. * @return {HTMLElement} The node or null if it wasn't found */ getNode: function(nodeInfo, dataRow) { var fly, result = this.callParent(arguments); if (result && result.tagName) { if (dataRow) { if (!(fly = Ext.fly(result)).is(this.dataRowSelector)) { return fly.down(this.dataRowSelector, true); } } else if (dataRow === false) { if (!(fly = Ext.fly(result)).is(this.itemSelector)) { return fly.up(this.itemSelector, null, true); } } } return result; }, getRowId: function(record){ return this.id + '-record-' + record.internalId; }, constructRowId: function(internalId){ return this.id + '-record-' + internalId; }, getNodeById: function(id, dataRow){ id = this.constructRowId(id); return this.retrieveNode(id, dataRow); }, getNodeByRecord: function(record, dataRow) { var id = this.getRowId(record); return this.retrieveNode(id, dataRow); }, retrieveNode: function(id, dataRow){ var result = this.el.getById(id, true), itemSelector = this.itemSelector, fly; if (dataRow === false && result) { if (!(fly = Ext.fly(result)).is(itemSelector)) { return fly.up(itemSelector, null, true); } } return result; }, // Links back from grid rows are installed by the XTemplate as data attributes updateIndexes: Ext.emptyFn, // Outer table bodySelector: 'table', // Element which contains rows nodeContainerSelector: 'tbody', // view item (may be a wrapper) itemSelector: 'tr.' + Ext.baseCSSPrefix + 'grid-row', // row which contains cells as opposed to wrapping rows dataRowSelector: 'tr.' + Ext.baseCSSPrefix + 'grid-data-row', // cell cellSelector: 'td.' + Ext.baseCSSPrefix + 'grid-cell', // `` sizerSelector: 'col.' + Ext.baseCSSPrefix + 'grid-cell-headerId', innerSelector: 'div.' + Ext.baseCSSPrefix + 'grid-cell-inner', getNodeContainer: function() { return this.el.down(this.nodeContainerSelector, true); }, /** * Returns a CSS selector which selects the outermost element(s) in this view. */ getBodySelector: function() { return this.bodySelector + '.' + Ext.baseCSSPrefix + this.id + '-table'; }, /** * Returns a CSS selector which selects the element which contains record nodes. */ getNodeContainerSelector: function() { return this.nodeContainerSelector; }, /** * Returns a CSS selector which selects the element(s) which define the width of a column. * * This is used by the {@link Ext.view.TableLayout} when resizing columns. * */ getColumnSizerSelector: function(header) { return this.sizerSelector + '-' + header.getItemId(); }, /** * Returns a CSS selector which selects items of the view rendered by the rowTpl */ getItemSelector: function() { return this.itemSelector; }, /** * Returns a CSS selector which selects a row which contains cells. * * These *may not* correspond to actual records in the store. This selector may be used * to identify things like total rows or header rows as injected by features which modify * the rowTpl. * */ getDataRowSelector: function() { return this.dataRowSelector; }, /** * Returns a CSS selector which selects a particular column if the desired header is passed, * or a general cell selector is no parameter is passed. * * @param {Ext.grid.column.Column} [header] The column for which to return the selector. If * omitted, the general cell selector which matches **ant cell** will be returned. * */ getCellSelector: function(header) { return header ? header.getCellSelector() : this.cellSelector; }, /* * Returns a CSS selector which selects the content carrying element within cells. */ getCellInnerSelector: function(header) { return this.getCellSelector(header) + ' ' + this.innerSelector; }, /** * Adds a CSS Class to a specific row. * @param {HTMLElement/String/Number/Ext.data.Model} rowInfo An HTMLElement, index or instance of a model * representing this row * @param {String} cls */ addRowCls: function(rowInfo, cls) { var row = this.getNode(rowInfo, false); if (row) { Ext.fly(row).addCls(cls); } }, /** * Removes a CSS Class from a specific row. * @param {HTMLElement/String/Number/Ext.data.Model} rowInfo An HTMLElement, index or instance of a model * representing this row * @param {String} cls */ removeRowCls: function(rowInfo, cls) { var row = this.getNode(rowInfo, false); if (row) { Ext.fly(row).removeCls(cls); } }, setHighlightedItem: function(item) { var me = this, highlighted = me.highlightedItem; if (highlighted && me.el.isAncestor(highlighted) && me.isRowStyleFirst(highlighted)) { me.toggleRowTableCls(highlighted, me.tableOverFirstCls, false); } item = me.getNode(item, false); // make sure item is not a "data row" if (item && me.isRowStyleFirst(item)) { me.toggleRowTableCls(item, me.tableOverFirstCls, true); } me.callParent(arguments); }, // GridSelectionModel invokes onRowSelect as selection changes onRowSelect: function(rowIdx) { var me = this, beforeSelectedItemCls = me.beforeSelectedItemCls; me.addRowCls(rowIdx, me.selectedItemCls); if (me.isRowStyleFirst(rowIdx)) { me.toggleRowTableCls(rowIdx, me.tableSelectedFirstCls, true); if (rowIdx > 0) { me.removeRowCls(rowIdx - 1, beforeSelectedItemCls); } } else { me.addRowCls(rowIdx - 1, beforeSelectedItemCls); } }, // GridSelectionModel invokes onRowDeselect as selection changes onRowDeselect: function(rowIdx) { var me = this; me.removeRowCls(rowIdx, [me.selectedItemCls, me.focusedItemCls]); if (me.isRowStyleFirst(rowIdx)) { me.toggleRowTableCls(rowIdx, [me.tableFocusedFirstCls, me.tableSelectedFirstCls], false); } else { me.removeRowCls(rowIdx - 1, [me.beforeFocusedItemCls, me.beforeSelectedItemCls]); } }, onCellSelect: function(position) { var cell = this.getCellByPosition(position); if (cell) { cell.addCls(this.selectedCellCls); } }, onCellDeselect: function(position) { var cell = this.getCellByPosition(position, true); if (cell) { Ext.fly(cell).removeCls(this.selectedCellCls); } }, getCellByPosition: function(position, returnDom) { if (position) { var row = this.getNode(position.row, true), header = this.ownerCt.getColumnManager().getHeaderAtIndex(position.column); if (header && row) { return Ext.fly(row).down(this.getCellSelector(header), returnDom); } } return false; }, getFocusEl: function() { return this.focusEl; }, // GridSelectionModel invokes onRowFocus to 'highlight' // the last row focused onRowFocus: function(rowIdx, highlight, supressFocus) { var me = this; if (highlight) { me.addRowCls(rowIdx, me.focusedItemCls); if (me.isRowStyleFirst(rowIdx)) { me.toggleRowTableCls(rowIdx, me.tableFocusedFirstCls, true); } else { me.addRowCls(rowIdx - 1, me.beforeFocusedItemCls); } if (!supressFocus) { me.focusRow(rowIdx); } //this.el.dom.setAttribute('aria-activedescendant', row.id); } else { me.removeRowCls(rowIdx, me.focusedItemCls); if (me.isRowStyleFirst(rowIdx)) { me.toggleRowTableCls(rowIdx, me.tableFocusedFirstCls, false); } else { me.removeRowCls(rowIdx - 1, me.beforeFocusedItemCls); } } if ((Ext.isIE6 || Ext.isIE7) && !me.ownerCt.rowLines) { me.repaintRow(rowIdx) } }, /** * Focuses a particular row and brings it into view. Will fire the rowfocus event. * @param {HTMLElement/String/Number/Ext.data.Model} row An HTMLElement template node, index of a template node, the id of a template node or the * @param {Boolean/Number} [delay] Delay the focus this number of milliseconds (true for 10 milliseconds). * record associated with the node. */ focusRow: function(row, delay) { var me = this, record, focusTask = me.getFocusTask(); if (delay) { focusTask.delay(Ext.isNumber(delay) ? delay : 10, me.focusRow, me, [row, false]); return; } // An immediate focus call must cancel any outstanding delayed focus calls. focusTask.cancel(); // Do not attempt to focus if hidden or within collapsed Panel // Maintainer: Note that to avoid an unnecessary call to me.getNode if not visible, or another, nested if test, // the assignment of the row var is embedded inside the condition expression. if (me.isVisible(true) && (row = me.getNode(row, true))) { me.scrollRowIntoView(row); record = me.getRecord(row); me.selModel.setLastFocused(record); me.doFocus(row); me.fireEvent('rowfocus', record, row, me.indexInStore(row)); } }, scrollRowIntoView: function(row) { row = this.getNode(row, true); if (row) { Ext.fly(row).scrollIntoView(this.el, false); } }, /** * Focuses a particular cell and brings it into view. Will fire the rowfocus event. * @param {Ext.grid.CellContext} pos The cell to select * @param {Boolean/Number} [delay] Delay the focus this number of milliseconds (true for 10 milliseconds). */ focusCell: function(position, delay) { var me = this, cell, focusTask = me.getFocusTask(); if (delay) { focusTask.delay(Ext.isNumber(delay) ? delay : 10, me.focusCell, me, [position, false]); return; } // An immediate focus call must cancel any outstanding delayed focus calls. focusTask.cancel(); // Do not attempt to focus if hidden or within collapsed Panel // Maintainer: Note that to avoid an unnecessary call to me.getCellByPosition if not visible, or another, nested if test, // the assignment of the cell var is embedded inside the condition expression. if (me.isVisible(true) && (cell = me.getCellByPosition(position))) { me.scrollCellIntoView(cell); me.doFocus(me.getNode(position.row)); me.fireEvent('cellfocus', position.record, cell, position); } }, // Private // Implementation which saves and restores scroll position on IE. doFocus: function(rowDom) { var me = this, saveScroll = Ext.isIE, scrollLeft; if (saveScroll) { scrollLeft = me.el.getScrollLeft(); me.ignoreScroll = true; } (me.focusEl = Ext.get(rowDom)).focus(); if (saveScroll) { me.el.setScrollLeft(scrollLeft); me.ignoreScroll = false; } }, scrollCellIntoView: function(cell) { // Allow cell context object to be passed. // TODO: change to .isCellContext check when implement cell context class if (cell.row != null && cell.column != null) { cell = this.getCellByPosition(cell); } if (cell) { Ext.fly(cell).scrollIntoView(this.el, true); } }, /** * Scrolls by delta. This affects this individual view ONLY and does not * synchronize across views or scrollers. * @param {Number} delta * @param {String} [dir] Valid values are scrollTop and scrollLeft. Defaults to scrollTop. * @private */ scrollByDelta: function(delta, dir) { dir = dir || 'scrollTop'; var elDom = this.el.dom; elDom[dir] = (elDom[dir] += delta); }, /** * @private * Used to test if a row being updated is a basic data row as opposed to containing extra markup * provided by a Feature, eg a wrapping row containing extra elements such as group header, group summary, * row body etc. * * If A row being updated *is not* a data row, then the elements within it which are not valid data rows * must be copied. * @param row * @return {Boolean} `true` if the passed element is a basic data row. */ isDataRow: function(row) { return Ext.fly(row).hasCls(Ext.baseCSSPrefix + 'grid-data-row'); }, syncRowHeights: function(firstRow, secondRow) { firstRow = Ext.get(firstRow); secondRow = Ext.get(secondRow); firstRow.dom.style.height = secondRow.dom.style.height = ''; var me = this, rowTpl = me.rowTpl, firstRowHeight = firstRow.dom.offsetHeight, secondRowHeight = secondRow.dom.offsetHeight; // If the two rows *need* syncing... if (firstRowHeight !== secondRowHeight) { // loop thru all of rowTpls asking them to sync the two row heights if they know how to. while (rowTpl) { if (rowTpl.syncRowHeights) { // If any rowTpl in the chain returns false, quit processing if (rowTpl.syncRowHeights(firstRow, secondRow) === false) { break; } } rowTpl = rowTpl.nextTpl; } // If that did not fix it, see if we have nested data rows, and equalize the data row heights firstRowHeight = firstRow.dom.offsetHeight; secondRowHeight = secondRow.dom.offsetHeight; if (firstRowHeight !== secondRowHeight) { // See if the real data row has been nested deeper by a Feature. firstRow = firstRow.down('[data-recordId]') || firstRow; secondRow = secondRow.down('[data-recordId]') || secondRow; // Yes, there's a nested data row on each side. Sync the heights of the two. if (firstRow && secondRow) { firstRow.dom.style.height = secondRow.dom.style.height = ''; firstRowHeight = firstRow.dom.offsetHeight; secondRowHeight = secondRow.dom.offsetHeight; if (firstRowHeight > secondRowHeight) { firstRow.setHeight(firstRowHeight); secondRow.setHeight(firstRowHeight); } else if (secondRowHeight > firstRowHeight) { firstRow.setHeight(secondRowHeight); secondRow.setHeight(secondRowHeight); } } } } }, onIdChanged: function(store, rec, oldId, newId, oldInternalId){ var me = this, rowDom; if (me.viewReady) { rowDom = me.getNodeById(oldInternalId); if (rowDom) { rowDom.setAttribute('data-recordId', rec.internalId); rowDom.id = me.getRowId(rec); } } }, // private onUpdate: function(store, record, operation, changedFieldNames) { var me = this, rowTpl = me.rowTpl, index, oldRow, oldRowDom, oldDataRow, newRowDom, newAttrs, attLen, attName, attrIndex, overItemCls, beforeOverItemCls, focusedItemCls, beforeFocusedItemCls, selectedItemCls, beforeSelectedItemCls, columns; if (me.viewReady) { // Table row being updated oldRowDom = me.getNodeByRecord(record, false); // Row might not be rendered due to buffered rendering or being part of a collapsed group... if (oldRowDom) { overItemCls = me.overItemCls; beforeOverItemCls = me.beforeOverItemCls; focusedItemCls = me.focusedItemCls; beforeFocusedItemCls = me.beforeFocusedItemCls; selectedItemCls = me.selectedItemCls; beforeSelectedItemCls = me.beforeSelectedItemCls; index = me.indexInStore(record); oldRow = Ext.fly(oldRowDom, '_internal'); newRowDom = me.createRowElement(record, index); if (oldRow.hasCls(overItemCls)) { Ext.fly(newRowDom).addCls(overItemCls); } if (oldRow.hasCls(beforeOverItemCls)) { Ext.fly(newRowDom).addCls(beforeOverItemCls); } if (oldRow.hasCls(focusedItemCls)) { Ext.fly(newRowDom).addCls(focusedItemCls); } if (oldRow.hasCls(beforeFocusedItemCls)) { Ext.fly(newRowDom).addCls(beforeFocusedItemCls); } if (oldRow.hasCls(selectedItemCls)) { Ext.fly(newRowDom).addCls(selectedItemCls); } if (oldRow.hasCls(beforeSelectedItemCls)) { Ext.fly(newRowDom).addCls(beforeSelectedItemCls); } columns = me.ownerCt.getVisibleColumnManager().getColumns(); // Copy new row attributes across. Use IE-specific method if possible. // In IE10, there is a problem where the className will not get updated // in the view, even though the className on the dom element is correct. // See EXTJSIV-9462 if (Ext.isIE9m && oldRowDom.mergeAttributes) { oldRowDom.mergeAttributes(newRowDom, true); } else { newAttrs = newRowDom.attributes; attLen = newAttrs.length; for (attrIndex = 0; attrIndex < attLen; attrIndex++) { attName = newAttrs[attrIndex].name; if (attName !== 'id') { oldRowDom.setAttribute(attName, newAttrs[attrIndex].value); } } } // If we have columns which may *need* updating (think locked side of lockable grid with all columns unlocked) // and the changed record is within our view, then update the view if (columns.length && (oldDataRow = me.getNode(oldRowDom, true))) { me.updateColumns(record, oldDataRow, me.getNode(newRowDom, true), columns, changedFieldNames); } // loop thru all of rowTpls asking them to sync the content they are responsible for if any. while (rowTpl) { if (rowTpl.syncContent) { if (rowTpl.syncContent(oldRowDom, newRowDom) === false) { break; } } rowTpl = rowTpl.nextTpl; } // Since we don't actually replace the row, we need to fire the event with the old row // because it's the thing that is still in the DOM me.fireEvent('itemupdate', record, index, oldRowDom); me.refreshSize(); } } }, updateColumns: function(record, oldRowDom, newRowDom, columns, changedFieldNames) { var me = this, newAttrs, attLen, attName, attrIndex, colCount = columns.length, colIndex, column, oldCell, newCell, row, // See if our View has an editingPlugin, or if we are a locking twin, see if the top LockingView // has an editingPlugin. // We do not support one editing plugin on the top lockable and some other on the twinned views. editingPlugin = me.editingPlugin || (me.lockingPartner && me.ownerCt.ownerLockable.view.editingPlugin), // See if the found editing plugin is active. isEditing = editingPlugin && editingPlugin.editing, cellSelector = me.getCellSelector(); // Copy new row attributes across. Use IE-specific method if possible. // Must do again at this level because the row DOM passed here may be the nested row in a row wrap. if (oldRowDom.mergeAttributes) { oldRowDom.mergeAttributes(newRowDom, true); } else { newAttrs = newRowDom.attributes; attLen = newAttrs.length; for (attrIndex = 0; attrIndex < attLen; attrIndex++) { attName = newAttrs[attrIndex].name; if (attName !== 'id') { oldRowDom.setAttribute(attName, newAttrs[attrIndex].value); } } } // Replace changed cells in the existing row structure with the new version from the rendered row. for (colIndex = 0; colIndex < colCount; colIndex++) { column = columns[colIndex]; // If the field at this column index was changed, or column has a custom renderer // (which means value could rely on any other changed field) the update the cell's content. if (me.shouldUpdateCell(record, column, changedFieldNames)) { // Pluck out cells using the column's unique cell selector. // Becuse in a wrapped row, there may be several TD elements. cellSelector = me.getCellSelector(column); oldCell = Ext.DomQuery.selectNode(cellSelector, oldRowDom); newCell = Ext.DomQuery.selectNode(cellSelector, newRowDom); // If an editor plugin is active, we carefully replace just the *contents* of the cell. if (isEditing) { Ext.fly(oldCell).syncContent(newCell); } // Otherwise, we simply replace whole TDs with a new version else { // Use immediate parentNode when replacing in case the main row was a wrapping row row = oldCell.parentNode; row.insertBefore(newCell, oldCell); row.removeChild(oldCell); } } } }, shouldUpdateCell: function(record, column, changedFieldNames){ // Though this may not be the most efficient, a renderer could be dependent on any field in the // store, so we must always update the cell. // If no changeFieldNames array was passed, we have to assume that that information // is unknown and update all cells. if (column.hasCustomRenderer || !changedFieldNames) { return true; } if (changedFieldNames) { var len = changedFieldNames.length, i, field; for (i = 0; i < len; ++i) { field = changedFieldNames[i]; if (field === column.dataIndex || field === record.idProperty) { return true; } } } return false; }, /** * Refreshes the grid view. Sets the sort state and focuses the previously focused row. */ refresh: function() { var me = this; me.callParent(arguments); me.headerCt.setSortState(); // Create horizontal stretcher element if no records in view and there is overflow of the header container. // Element will be transient and destroyed by the next refresh. if (me.el && !me.all.getCount() && me.headerCt && me.headerCt.tooNarrow) { me.el.createChild({ role: 'presentation', style:'position:absolute;height:1px;width:1px;left:' + (me.headerCt.getFullWidth() - 1) + 'px' }); } me.refreshSelection(); }, refreshSelection: function() { var me = this, selModel = me.selModel, selected, len, i; if (selModel.isRowModel) { selected = selModel.selected.items; len = selected.length; for (i = 0; i < len; i++) { me.onRowSelect(me.indexOf(me.getNode(selected[i]))); } } me.selModel.onLastFocusChanged(null, me.selModel.lastFocused, true); }, processItemEvent: function(record, row, rowIndex, e) { // Only process the event if it occurred within a row which maps to a record in the store if (this.indexInStore(row) !== -1) { var me = this, cell = e.getTarget(me.getCellSelector(), row), cellIndex, map = me.statics().EventMap, selModel = me.getSelectionModel(), type = e.type, features = me.features, len = features.length, i, result, feature, header; if (type == 'keydown' && !cell && selModel.getCurrentPosition) { // CellModel, otherwise we can't tell which cell to invoke cell = me.getCellByPosition(selModel.getCurrentPosition(), true); } // cellIndex is an attribute only of TD elements. Other TplFactories must use the data-cellIndex attribute. if (cell) { if (!cell.parentNode) { // If we have no parentNode, the td has been removed from the DOM, probably via an update, // so just jump out since the target for the event isn't valid return false; } // We can't use the cellIndex because we don't render hidden columns header = me.getHeaderByCell(cell); // Find the index of the header in the *full* (including hidden columns) leaf column set. // Because In 4.0.0 we rendered hidden cells, and the cellIndex included the hidden ones. cellIndex = me.ownerCt.getColumnManager().getHeaderIndex(header); } else { cellIndex = -1; } result = me.fireEvent('uievent', type, me, cell, rowIndex, cellIndex, e, record, row); if ((result === false || me.callParent(arguments) === false) && selModel.onVetoUIEvent) { selModel.onVetoUIEvent(type, me, cell, rowIndex, cellIndex, e, record, row); return false; } for (i = 0; i < len; ++i) { feature = features[i]; // In some features, the first/last row might be wrapped to contain extra info, // such as grouping or summary, so we may need to stop the event if (feature.wrapsItem) { if (feature.vetoEvent(record, row, rowIndex, e) === false) { // If the feature is vetoing the event, there's a good chance that // it's for some feature action in the wrapped row. me.processSpecialEvent(e); return false; } } } // Don't handle cellmouseenter and cellmouseleave events for now if (type == 'mouseover' || type == 'mouseout') { return true; } if(!cell) { // if the element whose event is being processed is not an actual cell (for example if using a rowbody // feature and the rowbody element's event is being processed) then do not fire any "cell" events return true; } return !( // We are adding cell and feature events (me['onBeforeCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) || (me.fireEvent('beforecell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false) || (me['onCell' + map[type]](cell, cellIndex, record, row, rowIndex, e) === false) || (me.fireEvent('cell' + type, me, cell, cellIndex, record, row, rowIndex, e) === false) ); } else { // If it's not in the store, it could be a feature event, so check here this.processSpecialEvent(e); return false; } }, processSpecialEvent: function(e) { var me = this, features = me.features, ln = features.length, type = e.type, i, feature, prefix, featureTarget, beforeArgs, args, panel = me.ownerCt; me.callParent(arguments); if (type == 'mouseover' || type == 'mouseout') { return; } for (i = 0; i < ln; i++) { feature = features[i]; if (feature.hasFeatureEvent) { featureTarget = e.getTarget(feature.eventSelector, me.getTargetEl()); if (featureTarget) { prefix = feature.eventPrefix; // allows features to implement getFireEventArgs to change the // fireEvent signature beforeArgs = feature.getFireEventArgs('before' + prefix + type, me, featureTarget, e); args = feature.getFireEventArgs(prefix + type, me, featureTarget, e); if ( // before view event (me.fireEvent.apply(me, beforeArgs) === false) || // panel grid event (panel.fireEvent.apply(panel, beforeArgs) === false) || // view event (me.fireEvent.apply(me, args) === false) || // panel event (panel.fireEvent.apply(panel, args) === false) ) { return false; } } } } return true; }, onCellMouseDown: Ext.emptyFn, onCellMouseUp: Ext.emptyFn, onCellClick: Ext.emptyFn, onCellDblClick: Ext.emptyFn, onCellContextMenu: Ext.emptyFn, onCellKeyDown: Ext.emptyFn, onBeforeCellMouseDown: Ext.emptyFn, onBeforeCellMouseUp: Ext.emptyFn, onBeforeCellClick: Ext.emptyFn, onBeforeCellDblClick: Ext.emptyFn, onBeforeCellContextMenu: Ext.emptyFn, onBeforeCellKeyDown: Ext.emptyFn, /** * Expands a particular header to fit the max content width. * @deprecated Use {@link #autoSizeColumn} instead. */ expandToFit: function(header) { this.autoSizeColumn(header); }, /** * Sizes the passed header to fit the max content width. * *Note that group columns shrinkwrap around the size of leaf columns. Auto sizing a group column * autosizes descendant leaf columns.* * @param {Ext.grid.column.Column/Number} header The header (or index of header) to auto size. */ autoSizeColumn: function(header) { if (Ext.isNumber(header)) { header = this.getGridColumns[header]; } if (header) { if (header.isGroupHeader) { header.autoSize(); return; } delete header.flex; header.setWidth(this.getMaxContentWidth(header)); } }, /** * Returns the max contentWidth of the header's text and all cells * in the grid under this header. * @private */ getMaxContentWidth: function(header) { var me = this, cells = me.el.query(header.getCellInnerSelector()), originalWidth = header.getWidth(), i = 0, ln = cells.length, columnSizer = me.body.select(me.getColumnSizerSelector(header)), max = Math.max, widthAdjust = 0, maxWidth; if (ln > 0) { if (Ext.supports.ScrollWidthInlinePaddingBug) { widthAdjust += me.getCellPaddingAfter(cells[0]); } if (me.columnLines) { widthAdjust += Ext.fly(cells[0].parentNode).getBorderWidth('lr'); } } // Set column width to 1px so we can detect the content width by measuring scrollWidth columnSizer.setWidth(1); // We are about to measure the offsetWidth of the textEl to determine how much // space the text occupies, but it will not report the correct width if the titleEl // has text-overflow:ellipsis. Set text-overflow to 'clip' before proceeding to // ensure we get the correct measurement. header.titleEl.setStyle('text-overflow', 'clip'); // Allow for padding round text of header maxWidth = header.textEl.dom.offsetWidth + header.titleEl.getPadding('lr'); // revert to using text-overflow defined by the stylesheet header.titleEl.setStyle('text-overflow', ''); for (; i < ln; i++) { maxWidth = max(maxWidth, cells[i].scrollWidth); } // in some browsers, the "after" padding is not accounted for in the scrollWidth maxWidth += widthAdjust; // 40 is the minimum column width. TODO: should this be configurable? maxWidth = max(maxWidth, 40); // Set column width back to original width columnSizer.setWidth(originalWidth); return maxWidth; }, getPositionByEvent: function(e) { var me = this, cellNode = e.getTarget(me.cellSelector), rowNode = e.getTarget(me.itemSelector), record = me.getRecord(rowNode), header = me.getHeaderByCell(cellNode); return me.getPosition(record, header); }, getHeaderByCell: function(cell) { if (cell) { var match = cell.className.match(this.cellRe); if (match && match[1]) { return this.ownerCt.getVisibleColumnManager().getHeaderById(match[1]); } } return false; }, /** * @param {Object} position The current row and column: an object containing the following properties: * * - row - The row index * - column - The column index * * @param {String} direction 'up', 'down', 'right' and 'left' * @param {Ext.EventObject} e event * @param {Boolean} preventWrap Set to true to prevent wrap around to the next or previous row. * @param {Function} verifierFn A function to verify the validity of the calculated position. * When using this function, you must return true to allow the newPosition to be returned. * @param {Object} scope Scope to run the verifierFn in * @returns {Ext.grid.CellContext} An object encapsulating the unique cell position. * * @private */ walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) { // Caller (probably CellModel) had no current position. This can happen // if the main el is focused and any navigation key is presssed. if (!pos) { return false; } var me = this, row = pos.row, column = pos.column, rowCount = me.dataSource.getCount(), allCols = me.ownerCt.getColumnManager(), visible = me.ownerCt.getVisibleColumnManager(), firstIndex = allCols.getHeaderIndex(visible.getFirst()), lastIndex = allCols.getHeaderIndex(visible.getLast()), newRow = row, newColumn = column, activeHeader = allCols.getHeaderAtIndex(column); // no active header or its currently hidden if (!activeHeader || activeHeader.hidden || !rowCount) { return false; } e = e || {}; direction = direction.toLowerCase(); switch (direction) { case 'right': // has the potential to wrap if its last if (column === lastIndex) { // if bottom row and last column, deny right if (preventWrap || row === rowCount - 1) { return false; } if (!e.ctrlKey) { // otherwise wrap to nextRow and firstCol newRow = me.walkRows(row, 1); if (newRow !== row) { newColumn = firstIndex; } } // go right } else { if (!e.ctrlKey) { newColumn = allCols.getHeaderIndex(visible.getNextSibling(activeHeader)); } else { newColumn = lastIndex; } } break; case 'left': // has the potential to wrap if (column === firstIndex) { // if top row and first column, deny left if (preventWrap || row === 0) { return false; } if (!e.ctrlKey) { // otherwise wrap to prevRow and lastIndex newRow = me.walkRows(row, -1); if (newRow !== row) { newColumn = lastIndex; } } // go left } else { if (!e.ctrlKey) { newColumn = allCols.getHeaderIndex(visible.getPreviousSibling(activeHeader)); } else { newColumn = firstIndex; } } break; case 'up': // if top row, deny up if (row === 0) { return false; // go up } else { if (!e.ctrlKey) { newRow = me.walkRows(row, -1); } else { // Go to first row by walking down from row -1 newRow = me.walkRows(-1, 1); } } break; case 'down': // if bottom row, deny down if (row === rowCount - 1) { return false; // go down } else { if (!e.ctrlKey) { newRow = me.walkRows(row, 1); } else { // Go to first row by walking up from beyond the last row newRow = me.walkRows(rowCount, -1); } } break; } if (verifierFn && verifierFn.call(scope || me, {row: newRow, column: newColumn}) !== true) { return false; } newColumn = allCols.getHeaderAtIndex(newColumn); return new Ext.grid.CellContext(me).setPosition(newRow, newColumn); }, /** * Increments the passed row index by the passed increment which may be +ve or -ve * * Skips hidden rows. * * If no row is visible in the specified direction, returns the input row index unchanged. * @param {Number} startRow The zero-based row index to start from. * @param {Number} distance The distance to move the row by. May be +ve or -ve. */ walkRows: function(startRow, distance) { // Note that we use the **dataSource** here because row indices mean view row indices // so records in collapsed groups must be omitted. var me = this, moved = 0, lastValid = startRow, node, last = (me.dataSource.buffered ? me.dataSource.getTotalCount() : me.dataSource.getCount()) - 1, limit = (distance < 0) ? 0 : last, increment = limit ? 1 : -1, result = startRow; do { // Walked off the end: return the last encountered valid row if (limit ? result >= limit : result <= 0) { return lastValid || limit; } // Move the result pointer on by one position. We have to count intervening VISIBLE nodes result += increment; // Stepped onto VISIBLE record: Increment the moved count. // We must not count stepping onto a non-rendered record as a move. if ((node = Ext.fly(me.getNode(result, true))) && node.isVisible(true)) { moved += increment; lastValid = result; } } while (moved !== distance); return result; }, /** * Navigates from the passed record by the passed increment which may be +ve or -ve * * Skips hidden records. * * If no record is visible in the specified direction, returns the starting record index unchanged. * @param {Ext.data.Model} startRec The Record to start from. * @param {Number} distance The distance to move from the record. May be +ve or -ve. */ walkRecs: function(startRec, distance) { // Note that we use the **store** to access the records by index because the dataSource omits records in collapsed groups. // This is used by selection models which use the **store** var me = this, moved = 0, lastValid = startRec, node, last = (me.store.buffered ? me.store.getTotalCount() : me.store.getCount()) - 1, limit = (distance < 0) ? 0 : last, increment = limit ? 1 : -1, testIndex = me.store.indexOf(startRec), rec; do { // Walked off the end: return the last encountered valid record if (limit ? testIndex >= limit : testIndex <= 0) { return lastValid; } // Move the result pointer on by one position. We have to count intervening VISIBLE nodes testIndex += increment; // Stepped onto VISIBLE record: Increment the moved count. // We must not count stepping onto a non-rendered record as a move. rec = me.store.getAt(testIndex); if ((node = Ext.fly(me.getNodeByRecord(rec, true))) && node.isVisible(true)) { moved += increment; lastValid = rec; } } while (moved !== distance); return lastValid; }, getFirstVisibleRowIndex: function() { var me = this, count = (me.dataSource.buffered ? me.dataSource.getTotalCount() : me.dataSource.getCount()), result = me.indexOf(me.all.first()) - 1; do { result += 1; if (result === count) { return; } } while (!Ext.fly(me.getNode(result, true)).isVisible(true)); return result; }, getLastVisibleRowIndex: function() { var me = this, result = me.indexOf(me.all.last()); do { result -= 1; if (result === -1) { return; } } while (!Ext.fly(me.getNode(result, true)).isVisible(true)); return result; }, getHeaderCt: function() { return this.headerCt; }, getPosition: function(record, header) { return new Ext.grid.CellContext(this).setPosition(record, header); }, beforeDestroy: function() { var me = this; if (me.rendered) { me.el.removeAllListeners(); } me.callParent(arguments); }, onDestroy: function() { var me = this, features = me.featuresMC, len, i; if (features) { for (i = 0, len = features.getCount(); i < len; ++i) { features.getAt(i).destroy(); } } me.featuresMC = null; this.callParent(arguments); }, // after adding a row stripe rows from then on onAdd: function(ds, records, index) { var me = this, selModel = me.selModel, nextIndex, isNextRowSelected, isNextRowFocused; me.callParent(arguments); me.doStripeRows(index); if (me.rendered && selModel.isRowModel && !records[0].isCollapsedPlaceholder) { nextIndex = index + records.length; isNextRowSelected = selModel.isRowSelected(nextIndex); isNextRowFocused = me.indexOf(selModel.lastFocused) === (nextIndex); if (isNextRowSelected || isNextRowFocused) { // calling onRowDeselect ensures before focus/selected border gets removed from // previous row if the row previously at this index was selected or focused. me.onRowDeselect(index); } if (isNextRowSelected) { me.onRowSelect(nextIndex); } if (selModel.isRowSelected(index)) { me.onRowSelect(index); } } me.selModel.onLastFocusChanged(null, me.selModel.lastFocused, true); }, // after removing a row stripe rows from then on onRemove: function(ds, records, indexes) { var me = this, index, selModel = me.selModel, len = indexes.length, i = 0, delta = 0, record; // Ensure "beforeSelected" classes are maintained correctly. // Some of the removed rows my have been carrying the beforeSelected class. me.callParent(arguments); me.doStripeRows(indexes[0]); if (me.rendered && selModel.isRowModel && !records[0].isCollapsedPlaceholder) { for (; i < len; i++, delta++) { index = indexes[i] - delta; record = me.store.getAt(index); me.onRowDeselect(index); if (selModel.isRowSelected(record) && me.getNode(record)) { me.onRowSelect(index); } } } selModel.onLastFocusChanged(null, selModel.lastFocused, true); }, /** * Stripes rows from a particular row index. * @param {Number} startRow * @param {Number} [endRow] argument specifying the last row to process. * By default process up to the last row. * @private */ doStripeRows: function(startRow, endRow) { var me = this, rows, rowsLn, i, row; // ensure stripeRows configuration is turned on if (me.rendered && me.stripeRows) { rows = me.getNodes(startRow, endRow); for (i = 0, rowsLn = rows.length; i < rowsLn; i++) { row = rows[i]; // Remove prior applied row classes. row.className = row.className.replace(me.rowClsRe, ' '); startRow++; // Every odd row will get an additional cls if (startRow % 2 === 0) { row.className += (' ' + me.altRowCls); } } } }, repaintRow: function(rowIdx) { var node = this.getNode(rowIdx), tds, i; if (node) { tds = node.childNodes; i = tds.length; while (i--) { tds[i].className = tds[i].className; } } }, // private // returns the table that gains a top border when the first grid row is focused, selected, // or hovered. Usually the main grid table but can be a sub-table, if a grouping // feature is being used. getRowStyleTableEl: function(item /* view item or row index */) { var me = this; if (!item.tagName) { item = this.getNode(item); } return (me.hasActiveGrouping() ? Ext.fly(item) : this.el).down('table.' + Ext.baseCSSPrefix + 'grid-table'); }, // private // adds or removes a css class to or from the table that gains a top border when the // first grid row is focused, selected, or hovered. Usually the main grid table but // can be a sub-table, if a grouping feature is being used. toggleRowTableCls: function(item /* view item or row index */, cls, enabled) { var me = this, table, root; if (!item.tagName) { item = this.getNode(item); } root = me.isGrouping ? Ext.fly(item) : this.el; if (root) { table = root.down('table.' + Ext.baseCSSPrefix + 'grid-table'); } if (table) { table[enabled ? 'addCls' : 'removeCls'](cls); } }, // private // returns true if the row should be treated as the first row stylistically. Typically // only returns true for the first row in a grid. Returns true for the first row // in each group of a grouped grid. isRowStyleFirst: function(item /* view item or row index */) { var me = this, index; // An item not in the view if (item === -1) { return false; } if (!item.tagName) { index = item; item = this.getNode(item); } else { index = me.indexOf(item); } return (!index || me.hasActiveGrouping() && item && Ext.fly(item).hasCls(Ext.baseCSSPrefix + 'grid-group-row')); }, hasActiveGrouping: function(){ return this.isGrouping && this.store.isGrouped(); }, getCellPaddingAfter: function(cell) { return Ext.fly(cell).getPadding('r'); }, hasVerticalScroll: function(){ var me = this, first; if (me.ownerCt.isLocked || !me.scrollFlags.y) { return false; } first = me.el.down('table'); if (!first) { return false; } return this.getHeight() < first.getHeight(); } }); /** * The grid View class provides extra {@link Ext.grid.Panel} specific functionality to the * {@link Ext.view.Table}. In general, this class is not instanced directly, instead a viewConfig * option is passed to the grid: * * Ext.create('Ext.grid.Panel', { * // other options * viewConfig: { * stripeRows: false * } * }); * * ## Drag Drop * * Drag and drop functionality can be achieved in the grid by attaching a {@link Ext.grid.plugin.DragDrop} plugin * when creating the view. * * Ext.create('Ext.grid.Panel', { * // other options * viewConfig: { * plugins: { * ddGroup: 'people-group', * ptype: 'gridviewdragdrop', * enableDrop: false * } * } * }); */ Ext.define('Ext.grid.View', { extend: Ext.view.Table , alias: 'widget.gridview', /** * @cfg {Boolean} * True to stripe the rows. * * This causes the CSS class **`x-grid-row-alt`** to be added to alternate rows of the grid. A default CSS rule is * provided which sets a background color, but you can override this with a rule which either overrides the * **background-color** style using the `!important` modifier, or which uses a CSS selector of higher specificity. */ stripeRows: true, autoScroll: true }); /** * @author Aaron Conran * @docauthor Ed Spencer * * Grids are an excellent way of showing large amounts of tabular data on the client side. Essentially a supercharged * ``, GridPanel makes it easy to fetch, sort and filter large amounts of data. * * Grids are composed of two main pieces - a {@link Ext.data.Store Store} full of data and a set of columns to render. * * ## Basic GridPanel * * @example * Ext.create('Ext.data.Store', { * storeId:'simpsonsStore', * fields:['name', 'email', 'phone'], * data:{'items':[ * { 'name': 'Lisa', "email":"[email protected]", "phone":"555-111-1224" }, * { 'name': 'Bart', "email":"[email protected]", "phone":"555-222-1234" }, * { 'name': 'Homer', "email":"[email protected]", "phone":"555-222-1244" }, * { 'name': 'Marge', "email":"[email protected]", "phone":"555-222-1254" } * ]}, * proxy: { * type: 'memory', * reader: { * type: 'json', * root: 'items' * } * } * }); * * Ext.create('Ext.grid.Panel', { * title: 'Simpsons', * store: Ext.data.StoreManager.lookup('simpsonsStore'), * columns: [ * { text: 'Name', dataIndex: 'name' }, * { text: 'Email', dataIndex: 'email', flex: 1 }, * { text: 'Phone', dataIndex: 'phone' } * ], * height: 200, * width: 400, * renderTo: Ext.getBody() * }); * * The code above produces a simple grid with three columns. We specified a Store which will load JSON data inline. * In most apps we would be placing the grid inside another container and wouldn't need to use the * {@link #height}, {@link #width} and {@link #renderTo} configurations but they are included here to make it easy to get * up and running. * * The grid we created above will contain a header bar with a title ('Simpsons'), a row of column headers directly underneath * and finally the grid rows under the headers. * * ## Configuring columns * * By default, each column is sortable and will toggle between ASC and DESC sorting when you click on its header. Each * column header is also reorderable by default, and each gains a drop-down menu with options to hide and show columns. * It's easy to configure each column - here we use the same example as above and just modify the columns config: * * columns: [ * { * text: 'Name', * dataIndex: 'name', * sortable: false, * hideable: false, * flex: 1 * }, * { * text: 'Email', * dataIndex: 'email', * hidden: true * }, * { * text: 'Phone', * dataIndex: 'phone', * width: 100 * } * ] * * We turned off sorting and hiding on the 'Name' column so clicking its header now has no effect. We also made the Email * column hidden by default (it can be shown again by using the menu on any other column). We also set the Phone column to * a fixed with of 100px and flexed the Name column, which means it takes up all remaining width after the other columns * have been accounted for. See the {@link Ext.grid.column.Column column docs} for more details. * * ## Renderers * * As well as customizing columns, it's easy to alter the rendering of individual cells using renderers. A renderer is * tied to a particular column and is passed the value that would be rendered into each cell in that column. For example, * we could define a renderer function for the email column to turn each email address into a mailto link: * * columns: [ * { * text: 'Email', * dataIndex: 'email', * renderer: function(value) { * return Ext.String.format('{1}', value, value); * } * } * ] * * See the {@link Ext.grid.column.Column column docs} for more information on renderers. * * ## Selection Models * * Sometimes all you want is to render data onto the screen for viewing, but usually it's necessary to interact with or * update that data. Grids use a concept called a Selection Model, which is simply a mechanism for selecting some part of * the data in the grid. The two main types of Selection Model are RowSelectionModel, where entire rows are selected, and * CellSelectionModel, where individual cells are selected. * * Grids use a Row Selection Model by default, but this is easy to customise like so: * * Ext.create('Ext.grid.Panel', { * selType: 'cellmodel', * store: ... * }); * * Specifying the `cellmodel` changes a couple of things. Firstly, clicking on a cell now * selects just that cell (using a {@link Ext.selection.RowModel rowmodel} will select the entire row), and secondly the * keyboard navigation will walk from cell to cell instead of row to row. Cell-based selection models are usually used in * conjunction with editing. * * ## Sorting & Filtering * * Every grid is attached to a {@link Ext.data.Store Store}, which provides multi-sort and filtering capabilities. It's * easy to set up a grid to be sorted from the start: * * var myGrid = Ext.create('Ext.grid.Panel', { * store: { * fields: ['name', 'email', 'phone'], * sorters: ['name', 'phone'] * }, * columns: [ * { text: 'Name', dataIndex: 'name' }, * { text: 'Email', dataIndex: 'email' } * ] * }); * * Sorting at run time is easily accomplished by simply clicking each column header. If you need to perform sorting on * more than one field at run time it's easy to do so by adding new sorters to the store: * * myGrid.store.sort([ * { property: 'name', direction: 'ASC' }, * { property: 'email', direction: 'DESC' } * ]); * * See {@link Ext.data.Store} for examples of filtering. * * ## State saving * * When configured {@link #stateful}, grids save their column state (order and width) encapsulated within the default * Panel state of changed width and height and collapsed/expanded state. * * Each {@link #columns column} of the grid may be configured with a {@link Ext.grid.column.Column#stateId stateId} which * identifies that column locally within the grid. * * ## Plugins and Features * * Grid supports addition of extra functionality through features and plugins: * * - {@link Ext.grid.plugin.CellEditing CellEditing} - editing grid contents one cell at a time. * * - {@link Ext.grid.plugin.RowEditing RowEditing} - editing grid contents an entire row at a time. * * - {@link Ext.grid.plugin.DragDrop DragDrop} - drag-drop reordering of grid rows. * * - {@link Ext.toolbar.Paging Paging toolbar} - paging through large sets of data. * * - {@link Ext.grid.plugin.BufferedRenderer Infinite scrolling} - another way to handle large sets of data. * * - {@link Ext.grid.RowNumberer RowNumberer} - automatically numbered rows. * * - {@link Ext.grid.feature.Grouping Grouping} - grouping together rows having the same value in a particular field. * * - {@link Ext.grid.feature.Summary Summary} - a summary row at the bottom of a grid. * * - {@link Ext.grid.feature.GroupingSummary GroupingSummary} - a summary row at the bottom of each group. */ Ext.define('Ext.grid.Panel', { extend: Ext.panel.Table , alias: ['widget.gridpanel', 'widget.grid'], alternateClassName: ['Ext.list.ListView', 'Ext.ListView', 'Ext.grid.GridPanel'], viewType: 'gridview', lockable: false, /** * @cfg {Boolean} rowLines False to remove row line styling */ rowLines: true // Columns config is required in Grid /** * @cfg {Ext.grid.column.Column[]/Object} columns (required) * @inheritdoc */ /** * @event beforereconfigure * Fires before a reconfigure to enable modification of incoming Store and columns. * @param {Ext.grid.Panel} this * @param {Ext.data.Store} store The store that was passed to the {@link #method-reconfigure} method * @param {Object[]} columns The column configs that were passed to the {@link #method-reconfigure} method * @param {Ext.data.Store} oldStore The store that will be replaced * @param {Ext.grid.column.Column[]} The column headers that will be replaced. */ /** * @event reconfigure * Fires after a reconfigure. * @param {Ext.grid.Panel} this * @param {Ext.data.Store} store The store that was passed to the {@link #method-reconfigure} method * @param {Object[]} columns The column configs that were passed to the {@link #method-reconfigure} method * @param {Ext.data.Store} oldStore The store that was replaced * @param {Ext.grid.column.Column[]} The column headers that were replaced. */ /** * @method reconfigure * Reconfigures the grid with a new store/columns. Either the store or the columns can be omitted if you don't wish * to change them. * @param {Ext.data.Store} store (Optional) The new store. * @param {Object[]} columns (Optional) An array of column configs */ }); /** * @private * A set of overrides required by the presence of the BufferedRenderer plugin. * * These overrides of Ext.view.Table take into account the affect of a buffered renderer and * divert execution from the default course where necessary. */ Ext.define('Ext.grid.plugin.BufferedRendererTableView', { override: 'Ext.view.Table', // Listener function for the Store's add event onAdd: function(store, records, index) { var me = this, bufferedRenderer = me.bufferedRenderer, rows = me.all; // The newly added records will put us over the buffered view size, so we cannot just add as normal. if (me.rendered && bufferedRenderer && (rows.getCount() + records.length) > bufferedRenderer.viewSize) { // Index puts the new row(s) in the visible area, then we have to refresh the view if (index < rows.startIndex + bufferedRenderer.viewSize && (index + records.length) > rows.startIndex) { me.refreshView(); } // New rows outside of visible area, just ensure that the scroll range is updated else { bufferedRenderer.stretchView(me, bufferedRenderer.getScrollHeight()); } } // No BufferedRenderer present // or // View has not yet reached the viewSize: we can add as normal. else { me.callParent([store, records, index]); } }, onRemove: function(store, records, indices) { var me = this, bufferedRenderer = me.bufferedRenderer, storeSize, all, startIndex; // Ensure all records are removed from the view me.callParent([store, records, indices]); // If there's a BufferedRenderer, the view must refresh to keep the view correct. // Removing *may* have removed all of the rendered rows, leaving whitespace below the group header, // so the buffered renderer will be needed to keep the buffer rendered zone valid - to pull records up from // below the removed zone into visibility. if (me.rendered && bufferedRenderer) { storeSize = me.dataSource.getCount(); all = me.all; // If that remove left a gap below the rendered range, ask the buffered renderer to render its // current view size. This will do the minimum work required, and *append* rows to the table only // if necessary if (storeSize > all.getCount()) { startIndex = all.startIndex; bufferedRenderer.renderRange(startIndex, Math.min(startIndex + bufferedRenderer.viewSize, storeSize) - 1); } // No overflow, still we have to ensure the scroll range is updated else { bufferedRenderer.stretchView(me, bufferedRenderer.getScrollHeight()); } } }, // When there's a buffered renderer present, store refresh events cause TableViews to go to scrollTop:0 onDataRefresh: function() { var me = this; if (me.bufferedRenderer) { // Clear NodeCache. Do NOT remove nodes from DOM - that would blur the view, and then refresh will not refocus after the refresh. me.all.clear(); me.bufferedRenderer.onStoreClear(); } me.callParent(); } }); /** * @private * Private Container class used by the {@link Ext.grid.RowEditor} to hold its buttons. */ Ext.define('Ext.grid.RowEditorButtons', { extend: Ext.container.Container , alias: 'widget.roweditorbuttons', frame: true, shrinkWrap: true, position: 'bottom', constructor: function(config) { var me = this, rowEditor = config.rowEditor, cssPrefix = Ext.baseCSSPrefix, plugin = rowEditor.editingPlugin; config = Ext.apply({ baseCls: cssPrefix + 'grid-row-editor-buttons', defaults: { xtype: 'button', ui: rowEditor.buttonUI, scope: plugin, flex: 1, minWidth: Ext.panel.Panel.prototype.minButtonWidth }, items: [{ cls: cssPrefix + 'row-editor-update-button', itemId: 'update', handler: plugin.completeEdit, text: rowEditor.saveBtnText, disabled: rowEditor.updateButtonDisabled }, { cls: cssPrefix + 'row-editor-cancel-button', handler: plugin.cancelEdit, text: rowEditor.cancelBtnText }] }, config); me.callParent([config]); me.addClsWithUI(me.position); }, setButtonPosition: function(position) { var me = this, rowEditor = this.rowEditor, rowEditorHeight = rowEditor.getHeight(), rowEditorBody = rowEditor.body, bottom = '', top = ''; me.removeClsWithUI(me.position); me.position = position; me.addClsWithUI(position); // we tried setting the top/bottom value in the stylesheet based on form field // height + row editor padding, but that approach does not work when there are // larger things inside the editor, e.g. textarea, so we have to measure // the row editor height and position the buttons accordingly (see EXTJSIV-9914). if (position === 'top') { bottom = (rowEditorHeight - rowEditorBody.getBorderWidth('t')) + 'px'; } else { top = (rowEditorHeight - rowEditorBody.getBorderWidth('b')) + 'px'; } me.el.setStyle({ top: top, bottom: bottom }); }, getFramingInfoCls: function(){ return this.baseCls + '-' + this.ui + '-' + this.position; }, getFrameInfo: function() { var frameInfo = this.callParent(); // Trick Renderable into rendering the top framing elements, even though they // are not needed in the default "bottom" position. This allows us to flip the // buttons into "top" position without re-rendering. frameInfo.top = true; return frameInfo; } }); // Currently has the following issues: // - Does not handle postEditValue // - Fields without editors need to sync with their values in Store // - starting to edit another record while already editing and dirty should probably prevent it // - aggregating validation messages // - tabIndex is not managed bc we leave elements in dom, and simply move via positioning // - layout issues when changing sizes/width while hidden (layout bug) /** * Internal utility class used to provide row editing functionality. For developers, they should use * the RowEditing plugin to use this functionality with a grid. * * @private */ Ext.define('Ext.grid.RowEditor', { extend: Ext.form.Panel , alias: 'widget.roweditor', // saveBtnText : 'Update', // // cancelBtnText: 'Cancel', // // errorsText: 'Errors', // // dirtyText: 'You need to commit or cancel your changes', // lastScrollLeft: 0, lastScrollTop: 0, border: false, errorCls: Ext.baseCSSPrefix + 'grid-row-editor-errors-item', buttonUI: 'default', // Change the hideMode to offsets so that we get accurate measurements when // the roweditor is hidden for laying out things like a TriggerField. hideMode: 'offsets', initComponent: function() { var me = this, grid = me.editingPlugin.grid, Container = Ext.container.Container, form; me.cls = Ext.baseCSSPrefix + 'grid-editor ' + Ext.baseCSSPrefix + 'grid-row-editor'; me.layout = { type: 'hbox', align: 'middle' }; me.lockable = grid.lockable; // Create field containing structure for when editing a lockable grid. if (me.lockable) { me.items = [ // Locked columns container shrinkwraps the fields me.lockedColumnContainer = new Container({ id: grid.id + '-locked-editor-cells', layout: { type: 'hbox', align: 'middle' }, // Locked grid has a border, we must be exactly the same width margin: '0 1 0 0' }), // Normal columns container flexes the remaining RowEditor width me.normalColumnContainer = new Container({ flex: 1, id: grid.id + '-normal-editor-cells', layout: { type: 'hbox', align: 'middle' } }) ]; } else { me.lockedColumnContainer = me.normalColumnContainer = me; } me.callParent(arguments); if (me.fields) { me.addFieldsForColumn(me.fields, true); me.insertColumnEditor(me.fields); delete me.fields; } me.mon(me.hierarchyEventSource, { scope: me, show: me.repositionIfVisible }); form = me.getForm(); form.trackResetOnLoad = true; form.on('validitychange', me.onValidityChange, me); }, // // Grid listener added when this is rendered. // Keep our containing element sized correctly // onGridResize: function() { var me = this, clientWidth = me.getClientWidth(), grid = me.editingPlugin.grid, gridBody = grid.body, btns = me.getFloatingButtons(); me.setLocalX(gridBody.getOffsetsTo(grid)[0] + gridBody.getBorderWidth('l') - grid.el.getBorderWidth('l')); me.setWidth(clientWidth); btns.setLocalX((clientWidth - btns.getWidth()) / 2); }, syncAllFieldWidths: function() { var me = this; // In a locked grid, a RowEditor uses 2 inner containers, so need to use CQ to retrieve // configured editors which were stamped with the isEditorComponent property in Editing.createColumnField Ext.Array.each(me.query('[isEditorComponent]'), function(editorComponent) { if (editorComponent.column.isVisible()) { me.onColumnShow(editorComponent.column); } }, me); }, syncFieldWidth: function(column) { var field = column.getEditor(), width; field._marginWidth = (field._marginWidth || field.el.getMargin('lr')); width = column.getWidth() - field._marginWidth; field.setWidth(width); if (field.xtype === 'displayfield') { // displayfield must have the width set on the inputEl for ellipsis to work field.inputWidth = width; } }, onValidityChange: function(form, valid) { var me = this; if (me.errorSummary && me.isVisible()) { me[valid ? 'hideToolTip' : 'showToolTip'](); } me.updateButton(valid); me.isValid = valid; }, updateButton: function(valid){ var buttons = this.floatingButtons; if (buttons) { buttons.child('#update').setDisabled(!valid); } else { // set flag so we can disabled when created if needed this.updateButtonDisabled = !valid; } }, afterRender: function() { var me = this, plugin = me.editingPlugin, grid = plugin.grid, view = grid.lockable ? grid.normalGrid.view : grid.view; me.callParent(arguments); // The scrollingViewEl is the TableView which scrolls me.scrollingView = view; me.scrollingViewEl = view.el; view.mon(me.scrollingViewEl, 'scroll', me.onViewScroll, me); // Prevent from bubbling click events to the grid view me.mon(me.el, { click: Ext.emptyFn, stopPropagation: true }); // Ensure that the editor width always matches the total header width me.mon(grid, { resize: me.onGridResize, scope: me }); me.el.swallowEvent([ 'keypress', 'keydown' ]); me.fieldScroller = me.normalColumnContainer.layout.innerCt; me.fieldScroller.dom.style.overflow = 'hidden'; me.fieldScroller.on({ scroll: me.onFieldContainerScroll, scope: me }); me.initKeyNav(); me.mon(plugin.view, { beforerefresh: me.onBeforeViewRefresh, refresh: me.onViewRefresh, itemremove: me.onViewItemRemove, scope: me }); // Prevent trying to reposition while we set everything up me.preventReposition = true; me.syncAllFieldWidths(); delete me.preventReposition; }, initKeyNav: function() { var me = this, plugin = me.editingPlugin; me.keyNav = new Ext.util.KeyNav(me.el, { enter: plugin.onEnterKey, esc: plugin.onEscKey, scope: plugin }); }, onBeforeViewRefresh: function(view) { var me = this, viewDom = view.el.dom; if (me.el.dom.parentNode === viewDom) { viewDom.removeChild(me.el.dom); } }, onViewRefresh: function(view) { var me = this, context = me.context, row; // Recover our row node after a view refresh if (context && (row = view.getNode(context.record, true))) { context.row = row; me.reposition(); if (me.tooltip && me.tooltip.isVisible()) { me.tooltip.setTarget(context.row); } } else { me.editingPlugin.cancelEdit(); } }, onViewItemRemove: function(record, index) { var context = this.context; if (context && record === context.record) { // if the record being edited was removed, cancel editing this.editingPlugin.cancelEdit(); } }, onViewScroll: function() { var me = this, viewEl = me.editingPlugin.view.el, scrollingViewEl = me.scrollingViewEl, scrollTop = scrollingViewEl.dom.scrollTop, scrollLeft = scrollingViewEl.getScrollLeft(), scrollLeftChanged = scrollLeft !== me.lastScrollLeft, scrollTopChanged = scrollTop !== me.lastScrollTop, row; me.lastScrollTop = scrollTop; me.lastScrollLeft = scrollLeft; if (me.isVisible()) { row = Ext.getDom(me.context.row.id); // Only reposition if the row is in the DOM (buffered rendering may mean the context row is not there) if (row && viewEl.contains(row)) { if (scrollTopChanged) { // The row element in the context may be stale due to buffered rendering removing out-of-view rows, then re-inserting newly rendered ones me.context.row = row; me.reposition(null, true); if ((me.tooltip && me.tooltip.isVisible()) || me.hiddenTip) { me.repositionTip(); } me.syncEditorClip(); } } // If row is NOT in the DOM, ensure the editor is out of sight else { me.setLocalY(-400); } } // Keep fields' left/right scroll position synced with view's left/right scroll if (me.rendered && scrollLeftChanged) { me.syncFieldsHorizontalScroll(); } }, // Synchronize the horizontal scroll position of the fields with the state of the grid view syncFieldsHorizontalScroll: function() { // Set overflow style here because it is an embedded element and the "style" Component config does not target it. this.fieldScroller.setScrollLeft(this.lastScrollLeft); }, // Synchronize the horizontal scroll position of the grid view with the fields. onFieldContainerScroll: function() { this.scrollingViewEl.setScrollLeft(this.fieldScroller.getScrollLeft()); }, onColumnResize: function(column, width) { var me = this; if (me.rendered && !me.editingPlugin.reconfiguring) { // Need to ensure our lockable/normal horizontal scrollrange is set me.onGridResize(); me.onViewScroll(); if (!column.isGroupHeader) { me.syncFieldWidth(column); me.repositionIfVisible(); } } }, onColumnHide: function(column) { if (!this.editingPlugin.reconfiguring && !column.isGroupHeader) { column.getEditor().hide(); this.repositionIfVisible(); } }, onColumnShow: function(column) { var me = this; if (me.rendered && !me.editingPlugin.reconfiguring && !column.isGroupHeader && column.getEditor) { column.getEditor().show(); me.syncFieldWidth(column); if (!me.preventReposition) { this.repositionIfVisible(); } } }, onColumnMove: function(column, fromIdx, toIdx) { var me = this, i, incr = 1, len, field, fieldIdx, fieldContainer = column.isLocked() ? me.lockedColumnContainer : me.normalColumnContainer; // If moving a group, move each leaf header if (column.isGroupHeader) { Ext.suspendLayouts(); column = column.getGridColumns(); if (toIdx > fromIdx) { toIdx--; incr = 0; } this.addFieldsForColumn(column); for (i = 0, len = column.length; i < len; i++, fromIdx += incr, toIdx += incr) { field = column[i].getEditor(); fieldIdx = fieldContainer.items.indexOf(field); // If the field is not in the container (moved from the main headerCt, INTO a group header) // then insert it into the correct place if (fieldIdx === -1) { fieldContainer.insert(toIdx, field); } // If the field has not already been processed by an onColumnAdd (move from a group header INTO the main headerCt), then move it else if (fieldIdx != toIdx) { fieldContainer.move(fromIdx, toIdx); } } Ext.resumeLayouts(true); } else { if (toIdx > fromIdx) { toIdx--; } this.addFieldsForColumn(column); field = column.getEditor(); fieldIdx = fieldContainer.items.indexOf(field); if (fieldIdx === -1) { fieldContainer.insert(toIdx, field); } else if (fieldIdx != toIdx) { fieldContainer.move(fromIdx, toIdx); } } }, onColumnAdd: function(column) { // If a column header added, process its leaves if (column.isGroupHeader) { column = column.getGridColumns(); } //this.preventReposition = true; this.addFieldsForColumn(column); this.insertColumnEditor(column); this.preventReposition = false; }, insertColumnEditor: function(column) { var me = this, plugin = me.editingPlugin, grid = plugin.grid, lockable = grid.lockable, fieldContainer, len, i; if (Ext.isArray(column)) { for (i = 0, len = column.length; i < len; i++) { me.insertColumnEditor(column[i]); } return; } if (!column.getEditor) { return; } if (column.isLocked()) { fieldContainer = me.lockedColumnContainer; grid = grid.lockedGrid; } else { fieldContainer = me.normalColumnContainer; if (lockable) { grid = grid.normalGrid; } } // Insert the column's field into the editor panel. fieldContainer.insert(grid.getColumnManager().getHeaderIndex(column), column.getEditor()); }, onColumnRemove: function(ct, column) { column = column.isGroupHeader ? column.getGridColumns() : column; this.removeColumnEditor(column); }, removeColumnEditor: function(column, destroy) { var me = this, field, len, i; if (Ext.isArray(column)) { for (i = 0, len = column.length; i < len; i++) { me.removeColumnEditor(column[i]); } return; } if (column.hasEditor() && column.field.isComponent) { field = column.getEditor(); if (field) { // If the column is removed and destroyed (or we are being told to destroy), destroy the field. if (destroy || column.isDestroyed) { field.destroy(); } // Otherwise, just remove the field but preserve it for use when the column is reinserted. else if (field.ownerCt) { field.ownerCt.remove(field, false); } } } }, onColumnReplace: function(map, fieldId, column, oldColumn) { this.onColumnRemove(oldColumn.ownerCt, oldColumn); }, getFloatingButtons: function() { var me = this, btns = me.floatingButtons; if (!btns) { me.floatingButtons = btns = new Ext.grid.RowEditorButtons({ rowEditor: me }); } return btns; }, repositionIfVisible: function(c) { var me = this, view = me.view; // If we're showing ourselves, jump out // If the component we're showing doesn't contain the view if (c && (c == me || !c.el.isAncestor(view.el))) { return; } if (me.isVisible() && view.isVisible(true)) { me.reposition(); } }, getRefOwner: function() { return this.editingPlugin.grid; }, // Lie to the CQ system about our nesting structure. // Pretend all the fields are always immediate children. // Include the two buttons. getRefItems: function(deep) { var me = this, result; if (me.lockable) { result = me.lockedColumnContainer.getRefItems(deep); result.push.apply(result, me.normalColumnContainer.getRefItems(deep)); } else { result = me.callParent(arguments); } result.push.apply(result, me.getFloatingButtons().getRefItems(deep)); return result; }, reposition: function(animateConfig, fromScrollHandler) { var me = this, context = me.context, row = context && Ext.get(context.row), yOffset = 0, rowTop, localY, deltaY, afterPosition; // Position this editor if the context row is rendered (buffered rendering may mean that it's not in the DOM at all) if (row && Ext.isElement(row.dom)) { deltaY = me.syncButtonPosition(me.getScrollDelta()); if (!me.editingPlugin.grid.rowLines) { // When the grid does not have rowLines we add a bottom border to the previous // row when the row is focused, but subtract the border width from the // top padding to keep the row from changing size. This adjusts the top offset // of the cell edtor to account for the added border. yOffset = -parseInt(row.first().getStyle('border-bottom-width'), 10); } rowTop = me.calculateLocalRowTop(row); localY = me.calculateEditorTop(rowTop) + yOffset; // If not being called from scroll handler... // If the editor's top will end up above the fold // or the bottom will end up below the fold, // organize an afterPosition handler which will bring it into view and focus the correct input field if (!fromScrollHandler) { afterPosition = function() { if (deltaY) { me.scrollingViewEl.scrollBy(0, deltaY, true); } me.focusContextCell(); } } me.syncEditorClip(); // Get the y position of the row relative to its top-most static parent. // offsetTop will be relative to the table, and is incorrect // when mixed with certain grid features (e.g., grouping). if (animateConfig) { me.animate(Ext.applyIf({ to: { top: localY }, duration: animateConfig.duration || 125, callback: afterPosition }, animateConfig)); } else { me.setLocalY(localY); if (afterPosition) { afterPosition(); } } } }, /** * @private * Returns the scroll delta required to scroll the context row into view in order to make * the whole of this editor visible. * @return {Number} the scroll delta. Zero if scrolling is not required. */ getScrollDelta: function() { var me = this, scrollingViewDom = me.scrollingViewEl.dom, context = me.context, body = me.body, deltaY = 0; if (context) { deltaY = Ext.fly(context.row).getOffsetsTo(scrollingViewDom)[1] - body.getBorderPadding().beforeY; if (deltaY > 0) { deltaY = Math.max(deltaY + me.getHeight() + me.floatingButtons.getHeight() - scrollingViewDom.clientHeight - body.getBorderWidth('b'), 0); } } return deltaY; }, // // Calculates the top pixel position of the passed row within the view's scroll space. // So in a large, scrolled grid, this could be several thousand pixels. // calculateLocalRowTop: function(row) { var grid = this.editingPlugin.grid; return Ext.fly(row).getOffsetsTo(grid)[1] - grid.el.getBorderWidth('t') + this.lastScrollTop; }, // Given the top pixel position of a row in the scroll space, // calculate the editor top position in the view's encapsulating element. // This will only ever be in the visible range of the view's element. calculateEditorTop: function(rowTop) { return rowTop - this.body.getBorderPadding().beforeY - this.lastScrollTop; }, getClientWidth: function() { var me = this, grid = me.editingPlugin.grid, result; if (me.lockable) { result = grid.lockedGrid.getWidth() + grid.normalGrid.view.el.dom.clientWidth - 1; } else { result = grid.view.el.dom.clientWidth; } return result; }, getEditor: function(fieldInfo) { var me = this; if (Ext.isNumber(fieldInfo)) { // In a locked grid, a RowEditor uses 2 inner containers, so need to use CQ to retrieve // configured editors which were stamped with the isEditorComponent property in Editing.createColumnField return me.query('[isEditorComponent]')[fieldInfo]; } else if (fieldInfo.isHeader && !fieldInfo.isGroupHeader) { return fieldInfo.getEditor(); } }, addFieldsForColumn: function(column, initial) { var me = this, i, length, field; if (Ext.isArray(column)) { for (i = 0, length = column.length; i < length; i++) { me.addFieldsForColumn(column[i], initial); } return; } if (column.getEditor) { // Get a default display field if necessary field = column.getEditor(null, me.getDefaultFieldCfg()); if (column.align === 'right') { field.fieldStyle = 'text-align:right'; } if (column.xtype === 'actioncolumn') { field.fieldCls += ' ' + Ext.baseCSSPrefix + 'form-action-col-field' } if (me.isVisible() && me.context) { if (field.is('displayfield')) { me.renderColumnData(field, me.context.record, column); } else { field.suspendEvents(); field.setValue(me.context.record.get(column.dataIndex)); field.resumeEvents(); } } if (column.hidden) { me.onColumnHide(column); } else if (column.rendered && !initial) { // Setting after initial render me.onColumnShow(column); } } }, getDefaultFieldCfg: function() { return { xtype: 'displayfield', // Override Field's implementation so that the default display fields will not return values. This is done because // the display field will pick up column renderers from the grid. getModelData: function() { return null; } }; }, loadRecord: function(record) { var me = this, form = me.getForm(), fields = form.getFields(), items = fields.items, length = items.length, i, displayFields, isValid; // temporarily suspend events on form fields before loading record to prevent the fields' change events from firing for (i = 0; i < length; i++) { items[i].suspendEvents(); } form.loadRecord(record); for (i = 0; i < length; i++) { items[i].resumeEvents(); } isValid = form.isValid(); if (me.errorSummary) { if (isValid) { me.hideToolTip(); } else { me.showToolTip(); } } me.updateButton(isValid); // render display fields so they honor the column renderer/template displayFields = me.query('>displayfield'); length = displayFields.length; for (i = 0; i < length; i++) { me.renderColumnData(displayFields[i], record); } }, renderColumnData: function(field, record, activeColumn) { var me = this, grid = me.editingPlugin.grid, headerCt = grid.headerCt, view = me.scrollingView, store = view.dataSource, column = activeColumn || field.column, value = record.get(column.dataIndex), renderer = column.editRenderer || column.renderer, metaData, rowIdx, colIdx; // honor our column's renderer (TemplateHeader sets renderer for us!) if (renderer) { metaData = { tdCls: '', style: '' }; rowIdx = store.indexOf(record); colIdx = headerCt.getHeaderIndex(column); value = renderer.call( column.scope || headerCt.ownerCt, value, metaData, record, rowIdx, colIdx, store, view ); } field.setRawValue(value); field.resetOriginalValue(); }, beforeEdit: function() { var me = this, scrollDelta; if (me.isVisible() && me.errorSummary && !me.autoCancel && me.isDirty()) { // Scroll the visible RowEditor that is in error state back into view scrollDelta = me.getScrollDelta(); if (scrollDelta) { me.scrollingViewEl.scrollBy(0, scrollDelta, true) } me.showToolTip(); return false; } }, /** * Start editing the specified grid at the specified position. * @param {Ext.data.Model} record The Store data record which backs the row to be edited. * @param {Ext.data.Model} columnHeader The Column object defining the column to be focused */ startEdit: function(record, columnHeader) { var me = this, editingPlugin = me.editingPlugin, grid = editingPlugin.grid, context = me.context = editingPlugin.context; if (!me.rendered) { me.width = me.getClientWidth(); me.render(grid.el, grid.el.dom.firstChild); me.getFloatingButtons().render(me.el); // On first show we need to ensure that we have the scroll positions cached me.onViewScroll(); } else { me.syncFieldsHorizontalScroll(); } // Select the record before showing the editor, since // selecting will steal focus context.grid.getSelectionModel().select(record); if (me.isVisible()) { me.reposition(true); } else { me.show(); } // Make sure the container el is correctly sized. me.onGridResize(); // Reload the record data me.loadRecord(record); }, // determines the amount by which the row editor will overflow, and flips the buttons // to the top of the editor if the required scroll amount is greater than the available // scroll space. Returns the scrollDelta required to scroll the editor into view after // adjusting the button position. syncButtonPosition: function(scrollDelta) { var me = this, floatingButtons = me.getFloatingButtons(), scrollingViewElDom = me.scrollingViewEl.dom, overflow = this.getScrollDelta() - (scrollingViewElDom.scrollHeight - scrollingViewElDom.scrollTop - scrollingViewElDom.clientHeight); if (overflow > 0) { if (!me._buttonsOnTop) { floatingButtons.setButtonPosition('top'); me._buttonsOnTop = true; } scrollDelta = 0; } else if (me._buttonsOnTop !== false) { floatingButtons.setButtonPosition('bottom'); me._buttonsOnTop = false; } return scrollDelta; }, // since the editor is rendered to the grid el, it must be clipped when scrolled // outside of the grid view area so that it does not overlap the scrollbar or docked items syncEditorClip: function() { var me = this, overflow = me.getScrollDelta(), btnHeight; if (overflow) { // The editor is overflowing outside of the view area, either above or below me.isOverflowing = true; btnHeight = me.floatingButtons.getHeight(); if (overflow > 0) { // editor is overflowing the bottom of the view me.clipBottom(Math.max(me.getHeight() - overflow + btnHeight, -btnHeight)); } else if (overflow < 0) { // editor is overflowing the top of the view overflow = Math.abs(overflow); me.clipTop(Math.max(overflow, 0)); } } else if (me.isOverflowing) { me.clearClip(); me.isOverflowing = false; } }, // Focus the cell on start edit based upon the current context focusContextCell: function() { var column = this.context.column, field; if (!column.isDestroyed) { field = this.getEditor(column); if (field && field.focus) { field.focus(); } } }, cancelEdit: function() { var me = this, form = me.getForm(), fields = form.getFields(), items = fields.items, length = items.length, i; me.hide(); form.clearInvalid(); // temporarily suspend events on form fields before reseting the form to prevent the fields' change events from firing for (i = 0; i < length; i++) { items[i].suspendEvents(); } form.reset(); for (i = 0; i < length; i++) { items[i].resumeEvents(); } }, completeEdit: function() { var me = this, form = me.getForm(); if (!form.isValid()) { return false; } form.updateRecord(me.context.record); me.hide(); return true; }, onShow: function() { var me = this; me.callParent(arguments); if (me.needsSyncFieldWidths) { me.suspendLayouts(); me.syncAllFieldWidths(); me.resumeLayouts(true); } delete me.needsSyncFieldWidths; me.reposition(); }, onHide: function() { var me = this; me.callParent(arguments); if (me.tooltip) { me.hideToolTip(); } if (me.context) { me.context.view.focusRow(me.context.record); me.context = null; } }, isDirty: function() { var me = this, form = me.getForm(); return form.isDirty(); }, getToolTip: function() { return this.tooltip || (this.tooltip = new Ext.tip.ToolTip({ cls: Ext.baseCSSPrefix + 'grid-row-editor-errors', title: this.errorsText, autoHide: false, closable: true, closeAction: 'disable', anchor: 'left', anchorToTarget: false })); }, hideToolTip: function() { var me = this, tip = me.getToolTip(); if (tip.rendered) { tip.disable(); } me.hiddenTip = false; }, showToolTip: function() { var me = this, tip = me.getToolTip(); tip.showAt([0, 0]); tip.update(me.getErrors()); me.repositionTip(); tip.enable(); }, repositionTip: function() { var me = this, tip = me.getToolTip(), context = me.context, row = Ext.get(context.row), viewEl = me.scrollingViewEl, viewHeight = viewEl.dom.clientHeight, viewTop = me.lastScrollTop, viewBottom = viewTop + viewHeight, rowHeight = row.getHeight(), rowTop = row.getOffsetsTo(me.context.view.body)[1], rowBottom = rowTop + rowHeight; if (rowBottom > viewTop && rowTop < viewBottom) { tip.showAt(tip.getAlignToXY(viewEl, 'tl-tr', [15, row.getOffsetsTo(viewEl)[1]])); me.hiddenTip = false; } else { tip.hide(); me.hiddenTip = true; } }, getErrors: function() { var me = this, errors = [], fields = me.query('>[isFormField]'), length = fields.length, i; for (i = 0; i < length; i++) { errors = errors.concat( Ext.Array.map(fields[i].getErrors(), me.createErrorListItem) ); } // Only complain about unsaved changes if all the fields are valid if (!errors.length && !me.autoCancel && me.isDirty()) { errors[0] = me.createErrorListItem(me.dirtyText); } return '
    ' + errors.join('') + '
'; }, createErrorListItem: function(e) { return '
  • ' + e + '
  • '; }, beforeDestroy: function(){ Ext.destroy(this.floatingButtons, this.tooltip); this.callParent(); }, clipBottom: function(value) { this.el.setStyle('clip', 'rect(-1000px auto ' + value + 'px auto)'); }, clipTop: function(value) { this.el.setStyle('clip', 'rect(' + value + 'px auto 1000px auto)'); }, clearClip: function(el) { this.el.setStyle( 'clip', Ext.isIE8m || Ext.isIEQuirks ? 'rect(-1000px auto 1000px auto)' : 'auto' ); } }); /** * @private */ Ext.define('Ext.view.DropZone', { extend: Ext.dd.DropZone , indicatorCls: Ext.baseCSSPrefix + 'grid-drop-indicator', indicatorHtml: [ '', '' ].join(''), constructor: function(config) { var me = this; Ext.apply(me, config); // Create a ddGroup unless one has been configured. // User configuration of ddGroups allows users to specify which // DD instances can interact with each other. Using one // based on the id of the View would isolate it and mean it can only // interact with a DragZone on the same View also using a generated ID. if (!me.ddGroup) { me.ddGroup = 'view-dd-zone-' + me.view.id; } // The DropZone's encapsulating element is the View's main element. It must be this because drop gestures // may require scrolling on hover near a scrolling boundary. In Ext 4.x two DD instances may not use the // same element, so a DragZone on this same View must use the View's parent element as its element. me.callParent([me.view.el]); }, // Fire an event through the client DataView. Lock this DropZone during the event processing so that // its data does not become corrupted by processing mouse events. fireViewEvent: function() { var me = this, result; me.lock(); result = me.view.fireEvent.apply(me.view, arguments); me.unlock(); return result; }, getTargetFromEvent : function(e) { var node = e.getTarget(this.view.getItemSelector()), mouseY, nodeList, testNode, i, len, box; // Not over a row node: The content may be narrower than the View's encapsulating element, so return the closest. // If we fall through because the mouse is below the nodes (or there are no nodes), we'll get an onContainerOver call. if (!node) { mouseY = e.getPageY(); for (i = 0, nodeList = this.view.getNodes(), len = nodeList.length; i < len; i++) { testNode = nodeList[i]; box = Ext.fly(testNode).getBox(); if (mouseY <= box.bottom) { return testNode; } } } return node; }, getIndicator: function() { var me = this; if (!me.indicator) { me.indicator = new Ext.Component({ ariaRole: 'presentation', html: me.indicatorHtml, cls: me.indicatorCls, ownerCt: me.view, floating: true, shadow: false }); } return me.indicator; }, getPosition: function(e, node) { var y = e.getXY()[1], region = Ext.fly(node).getRegion(), pos; if ((region.bottom - y) >= (region.bottom - region.top) / 2) { pos = "before"; } else { pos = "after"; } return pos; }, /** * @private Determines whether the record at the specified offset from the passed record * is in the drag payload. * @param records * @param record * @param offset * @returns {Boolean} True if the targeted record is in the drag payload */ containsRecordAtOffset: function(records, record, offset) { if (!record) { return false; } var view = this.view, recordIndex = view.indexOf(record), nodeBefore = view.getNode(recordIndex + offset, true), recordBefore = nodeBefore ? view.getRecord(nodeBefore) : null; return recordBefore && Ext.Array.contains(records, recordBefore); }, positionIndicator: function(node, data, e) { var me = this, view = me.view, pos = me.getPosition(e, node), overRecord = view.getRecord(node), draggingRecords = data.records, indicatorY; if (!Ext.Array.contains(draggingRecords, overRecord) && ( pos == 'before' && !me.containsRecordAtOffset(draggingRecords, overRecord, -1) || pos == 'after' && !me.containsRecordAtOffset(draggingRecords, overRecord, 1) )) { me.valid = true; if (me.overRecord != overRecord || me.currentPosition != pos) { indicatorY = Ext.fly(node).getY() - view.el.getY() - 1; if (pos == 'after') { indicatorY += Ext.fly(node).getHeight(); } me.getIndicator().setWidth(Ext.fly(view.el).getWidth()).showAt(0, indicatorY); // Cache the overRecord and the 'before' or 'after' indicator. me.overRecord = overRecord; me.currentPosition = pos; } } else { me.invalidateDrop(); } }, invalidateDrop: function() { if (this.valid) { this.valid = false; this.getIndicator().hide(); } }, // The mouse is over a View node onNodeOver: function(node, dragZone, e, data) { var me = this; if (!Ext.Array.contains(data.records, me.view.getRecord(node))) { me.positionIndicator(node, data, e); } return me.valid ? me.dropAllowed : me.dropNotAllowed; }, // Moved out of the DropZone without dropping. // Remove drop position indicator notifyOut: function(node, dragZone, e, data) { var me = this; me.callParent(arguments); me.overRecord = me.currentPosition = null me.valid = false; if (me.indicator) { me.indicator.hide(); } }, // The mouse is past the end of all nodes (or there are no nodes) onContainerOver : function(dd, e, data) { var me = this, view = me.view, count = view.dataSource.getCount(); // There are records, so position after the last one if (count) { me.positionIndicator(view.all.last(), data, e); } // No records, position the indicator at the top else { me.overRecord = me.currentPosition = null; me.getIndicator().setWidth(Ext.fly(view.el).getWidth()).showAt(0, 0); me.valid = true; } return me.dropAllowed; }, onContainerDrop : function(dd, e, data) { return this.onNodeDrop(dd, null, e, data); }, onNodeDrop: function(targetNode, dragZone, e, data) { var me = this, dropHandled = false, // Create a closure to perform the operation which the event handler may use. // Users may now set the wait parameter in the beforedrop handler, and perform any kind // of asynchronous processing such as an Ext.Msg.confirm, or an Ajax request, // and complete the drop gesture at some point in the future by calling either the // processDrop or cancelDrop methods. dropHandlers = { wait: false, processDrop: function () { me.invalidateDrop(); me.handleNodeDrop(data, me.overRecord, me.currentPosition); dropHandled = true; me.fireViewEvent('drop', targetNode, data, me.overRecord, me.currentPosition); }, cancelDrop: function() { me.invalidateDrop(); dropHandled = true; } }, performOperation = false; if (me.valid) { performOperation = me.fireViewEvent('beforedrop', targetNode, data, me.overRecord, me.currentPosition, dropHandlers); if (dropHandlers.wait) { return; } if (performOperation !== false) { // If either of the drop handlers were called in the event handler, do not do it again. if (!dropHandled) { dropHandlers.processDrop(); } } } return performOperation; }, destroy: function(){ Ext.destroy(this.indicator); delete this.indicator; this.callParent(); } }); /** * @private */ Ext.define('Ext.grid.ViewDropZone', { extend: Ext.view.DropZone , indicatorHtml: '', indicatorCls: Ext.baseCSSPrefix + 'grid-drop-indicator', handleNodeDrop : function(data, record, position) { var view = this.view, store = view.getStore(), index, records, i, len; // If the copy flag is set, create a copy of the models if (data.copy) { records = data.records; data.records = []; for (i = 0, len = records.length; i < len; i++) { data.records.push(records[i].copy()); } } else { /* * Remove from the source store. We do this regardless of whether the store * is the same bacsue the store currently doesn't handle moving records * within the store. In the future it should be possible to do this. * Here was pass the isMove parameter if we're moving to the same view. */ data.view.store.remove(data.records, data.view === view); } if (record && position) { index = store.indexOf(record); // 'after', or undefined (meaning a drop at index -1 on an empty View)... if (position !== 'before') { index++; } store.insert(index, data.records); } // No position specified - append. else { store.add(data.records); } view.getSelectionModel().select(data.records); } }); /** * Plugin to add header resizing functionality to a HeaderContainer. * Always resizing header to the left of the splitter you are resizing. */ Ext.define('Ext.grid.plugin.HeaderResizer', { extend: Ext.AbstractPlugin , alias: 'plugin.gridheaderresizer', disabled: false, config: { /** * @cfg {Boolean} dynamic * True to resize on the fly rather than using a proxy marker. * @accessor */ dynamic: false }, colHeaderCls: Ext.baseCSSPrefix + 'column-header', minColWidth: 40, maxColWidth: 1000, wResizeCursor: 'col-resize', eResizeCursor: 'col-resize', // not using w and e resize bc we are only ever resizing one // column //wResizeCursor: Ext.isWebKit ? 'w-resize' : 'col-resize', //eResizeCursor: Ext.isWebKit ? 'e-resize' : 'col-resize', init: function(headerCt) { this.headerCt = headerCt; headerCt.on('render', this.afterHeaderRender, this, {single: true}); }, /** * @private * AbstractComponent calls destroy on all its plugins at destroy time. */ destroy: function() { var tracker = this.tracker; if (tracker) { delete tracker.onBeforeStart; delete tracker.onStart; delete tracker.onDrag; delete tracker.onEnd; tracker.destroy(); this.tracker = null; } }, afterHeaderRender: function() { var headerCt = this.headerCt, el = headerCt.el; headerCt.mon(el, 'mousemove', this.onHeaderCtMouseMove, this); this.tracker = new Ext.dd.DragTracker({ disabled: this.disabled, onBeforeStart: Ext.Function.bind(this.onBeforeStart, this), onStart: Ext.Function.bind(this.onStart, this), onDrag: Ext.Function.bind(this.onDrag, this), onEnd: Ext.Function.bind(this.onEnd, this), tolerance: 3, autoStart: 300, el: el }); }, // As we mouse over individual headers, change the cursor to indicate // that resizing is available, and cache the resize target header for use // if/when they mousedown. onHeaderCtMouseMove: function(e, t) { var me = this, prevSiblings, headerEl, overHeader, resizeHeader, resizeHeaderOwnerGrid, ownerGrid; if (me.headerCt.dragging) { if (me.activeHd) { me.activeHd.el.dom.style.cursor = ''; delete me.activeHd; } } else { headerEl = e.getTarget('.' + me.colHeaderCls, 3, true); if (headerEl){ overHeader = Ext.getCmp(headerEl.id); // On left edge, go back to the previous non-hidden header. if (overHeader.isOnLeftEdge(e)) { resizeHeader = overHeader.previousNode('gridcolumn:not([hidden]):not([isGroupHeader])') // There may not *be* a previous non-hidden header. if (resizeHeader) { ownerGrid = me.headerCt.up('tablepanel'); resizeHeaderOwnerGrid = resizeHeader.up('tablepanel'); // Need to check that previousNode didn't go outside the current grid/tree // But in the case of a Grid which contains a locked and normal grid, allow previousNode to jump // from the first column of the normalGrid to the last column of the lockedGrid if (!((resizeHeaderOwnerGrid === ownerGrid) || ((ownerGrid.ownerCt.isXType('tablepanel')) && ownerGrid.ownerCt.view.lockedGrid === resizeHeaderOwnerGrid))) { resizeHeader = null; } } } // Else, if on the right edge, we're resizing the column we are over else if (overHeader.isOnRightEdge(e)) { resizeHeader = overHeader; } // Between the edges: we are not resizing else { resizeHeader = null; } // We *are* resizing if (resizeHeader) { // If we're attempting to resize a group header, that cannot be resized, // so find its last visible leaf header; Group headers are sized // by the size of their child headers. if (resizeHeader.isGroupHeader) { prevSiblings = resizeHeader.getGridColumns(); resizeHeader = prevSiblings[prevSiblings.length - 1]; } // Check if the header is resizable. Continue checking the old "fixed" property, bug also // check whether the resizable property is set to false. if (resizeHeader && !(resizeHeader.fixed || (resizeHeader.resizable === false) || me.disabled)) { me.activeHd = resizeHeader; overHeader.el.dom.style.cursor = me.eResizeCursor; if (overHeader.triggerEl) { overHeader.triggerEl.dom.style.cursor = me.eResizeCursor; } } // reset } else { overHeader.el.dom.style.cursor = ''; if (overHeader.triggerEl) { overHeader.triggerEl.dom.style.cursor = ''; } me.activeHd = null; } } } }, // only start when there is an activeHd onBeforeStart : function(e) { // cache the activeHd because it will be cleared. this.dragHd = this.activeHd; if (!!this.dragHd && !this.headerCt.dragging) { this.tracker.constrainTo = this.getConstrainRegion(); return true; } else { this.headerCt.dragging = false; return false; } }, // get the region to constrain to, takes into account max and min col widths getConstrainRegion: function() { var me = this, dragHdEl = me.dragHd.el, rightAdjust = 0, nextHd, lockedGrid; // If forceFit, then right constraint is based upon not being able to force the next header // beyond the minColWidth. If there is no next header, then the header may not be expanded. if (me.headerCt.forceFit) { nextHd = me.dragHd.nextNode('gridcolumn:not([hidden]):not([isGroupHeader])'); if (nextHd) { if (!me.headerInSameGrid(nextHd)) { nextHd = null; } rightAdjust = nextHd.getWidth() - me.minColWidth; } } // If resize header is in a locked grid, the maxWidth has to be 30px within the available locking grid's width else if ((lockedGrid = me.dragHd.up('tablepanel')).isLocked) { rightAdjust = me.dragHd.up('[scrollerOwner]').getWidth() - lockedGrid.getWidth() - 30; } // Else ue our default max width else { rightAdjust = me.maxColWidth - dragHdEl.getWidth(); } return me.adjustConstrainRegion( dragHdEl.getRegion(), 0, rightAdjust, 0, me.minColWidth ); }, // initialize the left and right hand side markers around // the header that we are resizing onStart: function(e){ var me = this, dragHd = me.dragHd, width = dragHd.el.getWidth(), headerCt = dragHd.getOwnerHeaderCt(), x, y, gridSection, markerOwner, lhsMarker, rhsMarker, markerHeight; me.headerCt.dragging = true; me.origWidth = width; // setup marker proxies if (!me.dynamic) { gridSection = markerOwner = headerCt.up('tablepanel'); if (gridSection.ownerLockable) { markerOwner = gridSection.ownerLockable; } x = me.getLeftMarkerX(markerOwner); lhsMarker = markerOwner.getLhsMarker(); rhsMarker = markerOwner.getRhsMarker(); markerHeight = gridSection.body.getHeight() + headerCt.getHeight(); y = headerCt.getOffsetsTo(markerOwner)[1]; lhsMarker.setLocalY(y); rhsMarker.setLocalY(y); lhsMarker.setHeight(markerHeight); rhsMarker.setHeight(markerHeight); me.setMarkerX(lhsMarker, x); me.setMarkerX(rhsMarker, x + width); } }, // synchronize the rhsMarker with the mouse movement onDrag: function(e){ var me = this, markerOwner; if (me.dynamic) { me.doResize(); } else { markerOwner = this.headerCt.up('tablepanel'); if (markerOwner.ownerLockable) { markerOwner = markerOwner.ownerLockable; } this.setMarkerX(this.getMovingMarker(markerOwner), this.calculateDragX(markerOwner)); } }, getMovingMarker: function(markerOwner){ return markerOwner.getRhsMarker(); }, onEnd: function(e) { this.headerCt.dragging = false; if (this.dragHd) { if (!this.dynamic) { var markerOwner = this.headerCt.up('tablepanel'); // hide markers if (markerOwner.ownerLockable) { markerOwner = markerOwner.ownerLockable; } this.setMarkerX(markerOwner.getLhsMarker(), -9999); this.setMarkerX(markerOwner.getRhsMarker(), -9999); } this.doResize(); } }, doResize: function() { var me = this, dragHd = me.dragHd, nextHd, offset; if (dragHd) { offset = me.tracker.getOffset('point'); // resize the dragHd if (dragHd.flex) { delete dragHd.flex; } Ext.suspendLayouts(); // Set the new column width. me.adjustColumnWidth(offset[0]); // In the case of forceFit, change the following Header width. // Constraining so that neither neighbour can be sized to below minWidth is handled in getConstrainRegion if (me.headerCt.forceFit) { nextHd = dragHd.nextNode('gridcolumn:not([hidden]):not([isGroupHeader])'); if (nextHd && !me.headerInSameGrid(nextHd)) { nextHd = null; } if (nextHd) { delete nextHd.flex; nextHd.setWidth(nextHd.getWidth() - offset[0]); } } // Apply the two width changes by laying out the owning HeaderContainer Ext.resumeLayouts(true); } }, // nextNode can traverse out of this grid, possibly to others on the page, so limit it here headerInSameGrid: function(header) { var grid = this.dragHd.up('tablepanel'); return !!header.up(grid); }, disable: function() { this.disabled = true; if (this.tracker) { this.tracker.disable(); } }, enable: function() { this.disabled = false; if (this.tracker) { this.tracker.enable(); } }, calculateDragX: function(markerOwner) { return this.tracker.getXY('point')[0] - markerOwner.getX() - markerOwner.el.getBorderWidth('l'); }, getLeftMarkerX: function(markerOwner) { return this.dragHd.getX() - markerOwner.getX() - markerOwner.el.getBorderWidth('l') - 1; }, setMarkerX: function(marker, x) { marker.setLocalX(x); }, adjustConstrainRegion: function(region, t, r, b, l) { return region.adjust(t, r, b, l); }, adjustColumnWidth: function(offsetX) { this.dragHd.setWidth(this.origWidth + offsetX); } }); /** * @private */ Ext.define('Ext.grid.header.DragZone', { extend: Ext.dd.DragZone , colHeaderSelector: '.' + Ext.baseCSSPrefix + 'column-header', colInnerSelector: '.' + Ext.baseCSSPrefix + 'column-header-inner', maxProxyWidth: 120, constructor: function(headerCt) { var me = this; me.headerCt = headerCt; me.ddGroup = me.getDDGroup(); me.autoGroup = true; me.callParent([headerCt.el]); me.proxy.el.addCls(Ext.baseCSSPrefix + 'grid-col-dd'); }, getDDGroup: function() { return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id; }, getDragData: function(e) { if (e.getTarget(this.colInnerSelector)) { var header = e.getTarget(this.colHeaderSelector), headerCmp, ddel; if (header) { headerCmp = Ext.getCmp(header.id); if (!this.headerCt.dragging && headerCmp.draggable && !(headerCmp.isOnLeftEdge(e) || headerCmp.isOnRightEdge(e))) { ddel = document.createElement('div'); ddel.role = 'presentation'; ddel.innerHTML = Ext.getCmp(header.id).text; return { ddel: ddel, header: headerCmp }; } } } return false; }, onBeforeDrag: function() { return !(this.headerCt.dragging || this.disabled); }, onInitDrag: function() { this.headerCt.dragging = true; this.callParent(arguments); }, onDragDrop: function() { this.headerCt.dragging = false; this.callParent(arguments); }, afterRepair: function() { this.callParent(); this.headerCt.dragging = false; }, getRepairXY: function() { return this.dragData.header.el.getXY(); }, disable: function() { this.disabled = true; }, enable: function() { this.disabled = false; } }); /** * @private */ Ext.define('Ext.grid.header.DropZone', { extend: Ext.dd.DropZone , colHeaderCls: Ext.baseCSSPrefix + 'column-header', proxyOffsets: [-4, -9], constructor: function(headerCt) { var me = this; me.headerCt = headerCt; me.ddGroup = me.getDDGroup(); me.autoGroup = true; me.callParent([headerCt.el]); }, getDDGroup: function() { return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id; }, getTargetFromEvent : function(e){ return e.getTarget('.' + this.colHeaderCls); }, getTopIndicator: function() { if (!this.topIndicator) { this.self.prototype.topIndicator = Ext.DomHelper.append(Ext.getBody(), { role: 'presentation', cls: "col-move-top", html: " " }, true); this.self.prototype.indicatorXOffset = Math.floor((this.topIndicator.dom.offsetWidth + 1) / 2); } return this.topIndicator; }, getBottomIndicator: function() { if (!this.bottomIndicator) { this.self.prototype.bottomIndicator = Ext.DomHelper.append(Ext.getBody(), { role: 'presentation', cls: "col-move-bottom", html: " " }, true); } return this.bottomIndicator; }, getLocation: function(e, t) { var x = e.getXY()[0], region = Ext.fly(t).getRegion(), pos; if ((region.right - x) <= (region.right - region.left) / 2) { pos = "after"; } else { pos = "before"; } return { pos: pos, header: Ext.getCmp(t.id), node: t }; }, positionIndicator: function(data, node, e){ var me = this, dragHeader = data.header, dropLocation = me.getLocation(e, node), targetHeader = dropLocation.header, pos = dropLocation.pos, nextHd, prevHd, topIndicator, bottomIndicator, topAnchor, bottomAnchor, topXY, bottomXY, headerCtEl, minX, maxX, allDropZones, ln, i, dropZone; // Avoid expensive CQ lookups and DOM calculations if dropPosition has not changed if (targetHeader === me.lastTargetHeader && pos === me.lastDropPos) { return; } nextHd = dragHeader.nextSibling('gridcolumn:not([hidden])'); prevHd = dragHeader.previousSibling('gridcolumn:not([hidden])'); me.lastTargetHeader = targetHeader; me.lastDropPos = pos; // Cannot drag to before non-draggable start column if (!targetHeader.draggable && pos === 'before' && targetHeader.getIndex() === 0) { return false; } data.dropLocation = dropLocation; if ((dragHeader !== targetHeader) && ((pos === "before" && nextHd !== targetHeader) || (pos === "after" && prevHd !== targetHeader)) && !targetHeader.isDescendantOf(dragHeader)) { // As we move in between different DropZones that are in the same // group (such as the case when in a locked grid), invalidateDrop // on the other dropZones. allDropZones = Ext.dd.DragDropManager.getRelated(me); ln = allDropZones.length; i = 0; for (; i < ln; i++) { dropZone = allDropZones[i]; if (dropZone !== me && dropZone.invalidateDrop) { dropZone.invalidateDrop(); } } me.valid = true; topIndicator = me.getTopIndicator(); bottomIndicator = me.getBottomIndicator(); if (pos === 'before') { topAnchor = 'bc-tl'; bottomAnchor = 'tc-bl'; } else { topAnchor = 'bc-tr'; bottomAnchor = 'tc-br'; } // Calculate arrow positions. Offset them to align exactly with column border line topXY = topIndicator.getAlignToXY(targetHeader.el, topAnchor); bottomXY = bottomIndicator.getAlignToXY(targetHeader.el, bottomAnchor); // constrain the indicators to the viewable section headerCtEl = me.headerCt.el; minX = headerCtEl.getX() - me.indicatorXOffset; maxX = headerCtEl.getX() + headerCtEl.getWidth(); topXY[0] = Ext.Number.constrain(topXY[0], minX, maxX); bottomXY[0] = Ext.Number.constrain(bottomXY[0], minX, maxX); // position and show indicators topIndicator.setXY(topXY); bottomIndicator.setXY(bottomXY); topIndicator.show(); bottomIndicator.show(); // invalidate drop operation and hide indicators } else { me.invalidateDrop(); } }, invalidateDrop: function() { this.valid = false; this.hideIndicators(); }, onNodeOver: function(node, dragZone, e, data) { var me = this, from = data.header, doPosition, to, fromPanel, toPanel; if (data.header.el.dom === node) { doPosition = false; } else { data.isLock = data.isUnlock = false; to = me.getLocation(e, node).header; // Dragging within the same container - always valid doPosition = (from.ownerCt === to.ownerCt); // If from different containers, and they are not sealed, then continue checking if (!doPosition && (!from.ownerCt.sealed && !to.ownerCt.sealed)) { doPosition = true; fromPanel = from.up('tablepanel'); toPanel = to.up('tablepanel'); // If it's a lock operation, check that it's allowable. data.isLock = toPanel.isLocked && !fromPanel.isLocked; data.isUnlock = !toPanel.isLocked && fromPanel.isLocked; if ((data.isUnlock && from.lockable === false) || (data.isLock && !from.isLockable())) { doPosition = false; } } } if (doPosition) { me.positionIndicator(data, node, e); } else { me.valid = false; } return me.valid ? me.dropAllowed : me.dropNotAllowed; }, hideIndicators: function() { var me = this; me.getTopIndicator().hide(); me.getBottomIndicator().hide(); me.lastTargetHeader = me.lastDropPos = null; }, onNodeOut: function() { this.hideIndicators(); }, onNodeDrop: function(node, dragZone, e, data) { if (this.valid) { var dragHeader = data.header, dropLocation = data.dropLocation, targetHeader = dropLocation.header, fromCt = dragHeader.ownerCt, localFromIdx = fromCt.items.indexOf(dragHeader), // Container.items is a MixedCollection toCt = targetHeader.ownerCt, localToIdx = toCt.items.indexOf(targetHeader), headerCt = this.headerCt, // Use the visible column manager here, the indexes we want are for moving // the actual cells in the grid, which is only visible items columns = headerCt.visibleColumnManager, fromIdx = columns.getHeaderIndex(dragHeader), toIdx = columns.getHeaderIndex(targetHeader), colsToMove = dragHeader.isGroupHeader ? dragHeader.query(':not([hidden]):not([isGroupHeader])').length : 1, sameCt = fromCt === toCt, scrollerOwner, savedWidth; // Drop position is to the right of the targetHeader, increment the toIdx correctly if (dropLocation.pos === 'after') { localToIdx++; toIdx += targetHeader.isGroupHeader ? targetHeader.query(':not([hidden]):not([isGroupHeader])').length : 1; } // If we are dragging in between two HeaderContainers that have had the lockable // mixin injected we will lock/unlock headers in between sections, and then continue // with another execution of onNodeDrop to ensure the header is dropped into the correct group if (data.isLock) { scrollerOwner = fromCt.up('[scrollerOwner]'); scrollerOwner.lock(dragHeader, localToIdx, toCt); } else if (data.isUnlock) { scrollerOwner = fromCt.up('[scrollerOwner]'); scrollerOwner.unlock(dragHeader, localToIdx, toCt); } // This is a drop within the same HeaderContainer. else { this.invalidateDrop(); // Cache the width here, we need to get it before we removed it from the DOM savedWidth = dragHeader.getWidth(); // Dragging within the same container. if (sameCt) { // If dragging rightwards, then after removal, the insertion index will be less. if (localToIdx > localFromIdx) { localToIdx -= 1; } // A no-op. This can happen when cross lockable drag operations recurse (see above). // If a drop was a lock/unlock, and the lock/unlock call placed the column in the // desired position (lock places at end, unlock places at beginning) then we're done. if (localToIdx === localFromIdx) { // We still need to inform the rest of the components so that events can be fired. headerCt.onHeaderMoved(dragHeader, colsToMove, fromIdx, toIdx); return; } } // Suspend layouts while we sort all this out. Ext.suspendLayouts(); dragHeader.dropMoving = true; if (sameCt) { toCt.move(localFromIdx, localToIdx); } else { fromCt.remove(dragHeader, false); toCt.insert(localToIdx, dragHeader); } delete dragHeader.dropMoving; // Group headers acquire the aggregate width of their child headers // Therefore a child header may not flex; it must contribute a fixed width. // But we restore the flex value when moving back into the main header container if (toCt.isGroupHeader) { // Adjust the width of the "to" group header only if we dragged in from somewhere else. if (!sameCt) { dragHeader.savedFlex = dragHeader.flex; delete dragHeader.flex; dragHeader.width = savedWidth; } } else { if (dragHeader.savedFlex) { dragHeader.flex = dragHeader.savedFlex; delete dragHeader.width; } } // Refresh columns cache in case we remove an emptied group column headerCt.purgeCache(); Ext.resumeLayouts(true); headerCt.onHeaderMoved(dragHeader, colsToMove, fromIdx, toIdx); // Ext.grid.header.Container will handle the removal of empty groups, don't handle it here } } } }); /** * @private */ Ext.define('Ext.grid.plugin.HeaderReorderer', { extend: Ext.AbstractPlugin , alias: 'plugin.gridheaderreorderer', init: function(headerCt) { this.headerCt = headerCt; headerCt.on({ render: this.onHeaderCtRender, single: true, scope: this }); }, /** * @private * AbstractComponent calls destroy on all its plugins at destroy time. */ destroy: function() { Ext.destroy(this.dragZone, this.dropZone); }, onHeaderCtRender: function() { var me = this; me.dragZone = new Ext.grid.header.DragZone(me.headerCt); me.dropZone = new Ext.grid.header.DropZone(me.headerCt); if (me.disabled) { me.dragZone.disable(); } }, enable: function() { this.disabled = false; if (this.dragZone) { this.dragZone.enable(); } }, disable: function() { this.disabled = true; if (this.dragZone) { this.dragZone.disable(); } } }); /** * Container which holds headers and is docked at the top or bottom of a TablePanel. * The HeaderContainer drives resizing/moving/hiding of columns within the TableView. * As headers are hidden, moved or resized the headercontainer is responsible for * triggering changes within the view. */ Ext.define('Ext.grid.header.Container', { extend: Ext.container.Container , border: true, alias: 'widget.headercontainer', baseCls: Ext.baseCSSPrefix + 'grid-header-ct', dock: 'top', /** * @cfg {Number} weight * HeaderContainer overrides the default weight of 0 for all docked items to 100. * This is so that it has more priority over things like toolbars. */ weight: 100, defaultType: 'gridcolumn', detachOnRemove: false, /** * @cfg {Number} defaultWidth * Width of the header if no width or flex is specified. */ defaultWidth: 100, /** * @cfg {Boolean} [sealed=false] * Specify as `true` to constrain column dragging so that a column cannot be dragged into or out of this column. * * **Note that this config is only valid for column headers which contain child column headers, eg:** * { * sealed: true * text: 'ExtJS', * columns: [{ * text: '3.0.4', * dataIndex: 'ext304' * }, { * text: '4.1.0', * dataIndex: 'ext410' * } * } * */ // sortAscText: 'Sort Ascending', // // sortDescText: 'Sort Descending', // // sortClearText: 'Clear Sort', // // columnsText: 'Columns', // headerOpenCls: Ext.baseCSSPrefix + 'column-header-open', menuSortAscCls: Ext.baseCSSPrefix + 'hmenu-sort-asc', menuSortDescCls: Ext.baseCSSPrefix + 'hmenu-sort-desc', menuColsIcon: Ext.baseCSSPrefix + 'cols-icon', // private; will probably be removed by 4.0 triStateSort: false, ddLock: false, dragging: false, /** * @property {Boolean} isGroupHeader * True if this HeaderContainer is in fact a group header which contains sub headers. */ /** * @cfg {Boolean} sortable * Provides the default sortable state for all Headers within this HeaderContainer. * Also turns on or off the menus in the HeaderContainer. Note that the menu is * shared across every header and therefore turning it off will remove the menu * items for every header. */ sortable: true, /** * @cfg {Boolean} [enableColumnHide=true] * False to disable column hiding within this grid. */ enableColumnHide: true, initComponent: function() { var me = this; me.headerCounter = 0; me.plugins = me.plugins || []; // TODO: Pass in configurations to turn on/off dynamic // resizing and disable resizing all together // Only set up a Resizer and Reorderer for the topmost HeaderContainer. // Nested Group Headers are themselves HeaderContainers if (!me.isColumn) { if (me.enableColumnResize) { me.resizer = new Ext.grid.plugin.HeaderResizer(); me.plugins.push(me.resizer); } if (me.enableColumnMove) { me.reorderer = new Ext.grid.plugin.HeaderReorderer(); me.plugins.push(me.reorderer); } } // If this is a leaf column header, and is NOT functioning as a container, // use Container layout with a no-op calculate method. if (me.isColumn && !me.isGroupHeader) { if (!me.items || me.items.length === 0) { me.isContainer = false; me.layout = { type: 'container', calculate: Ext.emptyFn }; } } // HeaderContainer and Group header needs a gridcolumn layout. else { me.layout = Ext.apply({ type: 'gridcolumn', align: 'stretch' }, me.initialConfig.layout); // If the header isn't a column ([isColumn] or [isGroupHeader]), then it's the root header. if (!me.isGroupHeader) { me.isRootHeader = true; // Create column managers for the root header. me.columnManager = new Ext.grid.ColumnManager(false, me); me.visibleColumnManager = new Ext.grid.ColumnManager(true, me); // In the grid config, if grid.columns is a header container instance and not a columns // config, then it currently has no knowledge of a containing grid. Create the column // manager now and bind it to the grid later in Ext.panel.Table:initComponent(). // // In most cases, though, grid.columns will be a config, so the grid is already known // and the column manager can be bound to it. if (me.grid) { me.grid.columnManager = me.columnManager; me.grid.visibleColumnManager = me.visibleColumnManager; } } else { // Is a group header, also create column managers. me.visibleColumnManager = new Ext.grid.ColumnManager(true, me); me.columnManager = new Ext.grid.ColumnManager(false, me); } } me.defaults = me.defaults || {}; Ext.applyIf(me.defaults, { triStateSort: me.triStateSort, sortable: me.sortable }); me.menuTask = new Ext.util.DelayedTask(me.updateMenuDisabledState, me); me.callParent(); me.addEvents( /** * @event columnresize * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition * @param {Number} width */ 'columnresize', /** * @event headerclick * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition * @param {Ext.EventObject} e * @param {HTMLElement} t */ 'headerclick', /** * @event headercontextmenu * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition * @param {Ext.EventObject} e * @param {HTMLElement} t */ 'headercontextmenu', /** * @event headertriggerclick * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition * @param {Ext.EventObject} e * @param {HTMLElement} t */ 'headertriggerclick', /** * @event columnmove * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition * @param {Number} fromIdx * @param {Number} toIdx */ 'columnmove', /** * @event columnhide * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition */ 'columnhide', /** * @event columnshow * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition */ 'columnshow', /** * @event columnschanged * Fired after the columns change in any way, when a column has been hidden or shown, or when a column * is added to or removed from this header container. * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. */ 'columnschanged', /** * @event sortchange * @param {Ext.grid.header.Container} ct The grid's header Container which encapsulates all column headers. * @param {Ext.grid.column.Column} column The Column header Component which provides the column definition * @param {String} direction */ 'sortchange', /** * @event menucreate * Fired immediately after the column header menu is created. * @param {Ext.grid.header.Container} ct This instance * @param {Ext.menu.Menu} menu The Menu that was created */ 'menucreate' ); }, isLayoutRoot: function(){ // Since we're docked, the width is always calculated // If we're hidden, the height is explicitly 0, which // means we'll be considered a layout root. However, we // still need the view to layout to update the underlying // table to match the size. if (this.hiddenHeaders) { return false; } return this.callParent(); }, // Find the topmost HeaderContainer getOwnerHeaderCt: function() { var me = this; return me.isRootHeader ? me : me.up('[isRootHeader]'); }, onDestroy: function() { var me = this; if (me.menu) { me.menu.un('hide', me.onMenuHide, me); } me.menuTask.cancel(); me.callParent(); Ext.destroy(me.resizer, me.reorderer, me.visibleColumnManager, me.columnManager, me.menu); me.columnManager = me.visibleColumnManager = null; }, applyColumnsState: function(columns) { if (!columns || !columns.length) { return; } var me = this, items = me.items.items, count = items.length, i = 0, length = columns.length, c, col, columnState, index; for (c = 0; c < length; c++) { columnState = columns[c]; for (index = count; index--; ) { col = items[index]; if (col.getStateId && col.getStateId() == columnState.id) { // If a column in the new grid matches up with a saved state... // Ensure that the column is restored to the state order. // i is incremented upon every column match, so all persistent // columns are ordered before any new columns. if (i !== index) { me.moveHeader(index, i); } if (col.applyColumnState) { col.applyColumnState(columnState); } ++i; break; } } } }, getColumnsState: function () { var me = this, columns = [], state; me.items.each(function (col) { state = col.getColumnState && col.getColumnState(); if (state) { columns.push(state); } }); return columns; }, // Invalidate column cache on add // We cannot refresh the View on every add because this method is called // when the HeaderDropZone moves Headers around, that will also refresh the view onAdd: function(c) { var me = this; if (!c.headerId) { c.headerId = c.initialConfig.id || Ext.id(null, 'header-'); } // Only generate a stateId if it really needs one - ie, it cannot yield a stateId if (!c.getStateId()) { // This was the headerId generated in 4.0, so to preserve saved state, we now // assign a default stateId in that same manner. The stateId's of a column are // not global at the stateProvider, but are local to the grid state data. The // headerId should still follow our standard naming convention. c.stateId = c.initialConfig.id || ('h' + (++me.headerCounter)); } me.callParent(arguments); me.onColumnsChanged(); me.checkMoveNotify(c); }, onMove: function(c, fromIdx, toIdx) { var me = this; me.callParent(arguments); me.onColumnsChanged(); if (!c.dropMoving) { // The drop code will take care of updating the view me.checkMoveNotify(c); me.fireEvent('columnmove', me, c, fromIdx, toIdx); } }, // Invalidate column cache on remove // We cannot refresh the View on every remove because this method is called // when the HeaderDropZone moves Headers around, that will also refresh the view onRemove: function(c) { var me = this, ownerCt = me.ownerCt; me.callParent(arguments); if (!me.destroying) { me.onColumnsChanged(); me.checkMoveNotify(c); if (me.isGroupHeader && !me.items.getCount() && ownerCt) { // Detach the header from the DOM here. Since we're removing and destroying the container, // the inner DOM may get overwritten, since Container::deatchOnRemove gets processed after // onRemove. me.detachComponent(c); // If we don't have any items left and we're a group, remove ourselves. // This will cascade up if necessary Ext.suspendLayouts(); ownerCt.remove(me); Ext.resumeLayouts(true); } } }, checkMoveNotify: function(c) { var owner, root; if (!c.isGroupHeader) { // Get the root header root = this.getOwnerHeaderCt(); if (root) { // Reference the panel.Table owner = root.ownerCt; if (owner) { owner.onHeadersChanged(root, c); } } } }, onShow: function() { this.callParent(arguments); this.onColumnsChanged(); }, // Private // Called whenever a column is added or removed or moved. // Ensures that the gridColumns caches are cleared. onColumnsChanged: function() { var headerCt = this; // Each HeaderContainer up the chain must have its cache purged so that its getGridColumns method will return correct results. this.purgeHeaderCtCache(headerCt); if (headerCt && headerCt.rendered) { headerCt.fireEvent('columnschanged', headerCt); } }, // @private applyDefaults: function(config) { var ret; /* * Ensure header.Container defaults don't get applied to a RowNumberer * if an xtype is supplied. This isn't an ideal solution however it's * much more likely that a RowNumberer with no options will be created, * wanting to use the defaults specified on the class as opposed to * those setup on the Container. */ if (config && !config.isComponent && config.xtype == 'rownumberer') { ret = config; } else { ret = this.callParent(arguments); // Apply default width unless it's a group header (in which case it must be left to shrinkwrap), or it's flexed if (!config.isGroupHeader && !('width' in ret) && !ret.flex) { ret.width = this.defaultWidth; } } return ret; }, setSortState: function(){ var store = this.up('[store]').store, // grab the first sorter, since there may also be groupers // in this collection first = store.getFirstSorter(), hd; if (first) { hd = this.down('gridcolumn[dataIndex=' + first.property +']'); if (hd) { hd.setSortState(first.direction, false, true); } } else { this.clearOtherSortStates(null); } }, getHeaderMenu: function(){ var menu = this.getMenu(), item; if (menu) { item = menu.child('#columnItem'); if (item) { return item.menu; } } return null; }, onHeaderVisibilityChange: function(header, visible){ var me = this, menu = me.getHeaderMenu(), item; // Invalidate column collections upon column hide/show me.purgeHeaderCtCache(header.ownerCt); if (menu) { // If the header was hidden programmatically, sync the Menu state item = me.getMenuItemForHeader(menu, header); if (item) { item.setChecked(visible, true); } // delay this since the headers may fire a number of times if we're hiding/showing groups if (menu.isVisible()) { me.menuTask.delay(50); } } }, updateMenuDisabledState: function(menu) { var me = this, columns = me.query(':not([hidden])'), i, len = columns.length, item, checkItem, method; // If called from menu creation, it will be passed to avoid infinite recursion if (!menu) { menu = me.getMenu(); } for (i = 0; i < len; ++i) { item = columns[i]; checkItem = me.getMenuItemForHeader(menu, item); if (checkItem) { method = item.isHideable() ? 'enable' : 'disable'; if (checkItem.menu) { method += 'CheckChange'; } checkItem[method](); } } }, getMenuItemForHeader: function(menu, header) { return header ? menu.down('menucheckitem[headerId=' + header.id + ']') : null; }, onHeaderShow: function(header) { // Pass up to the GridSection var me = this, gridSection = me.ownerCt; if (me.forceFit) { delete me.flex; } me.onHeaderVisibilityChange(header, true); // Only update the grid UI when we are notified about base level Header shows; // Group header shows just cause a layout of the HeaderContainer if (!header.isGroupHeader) { if (gridSection) { gridSection.onHeaderShow(me, header); } } me.fireEvent('columnshow', me, header); me.fireEvent('columnschanged', this); }, onHeaderHide: function(header) { // Pass up to the GridSection var me = this, gridSection = me.ownerCt; me.onHeaderVisibilityChange(header, false); // Only update the UI when we are notified about base level Header hides; if (!header.isGroupHeader) { if (gridSection) { gridSection.onHeaderHide(me, header); } } me.fireEvent('columnhide', me, header); me.fireEvent('columnschanged', this); }, /** * Temporarily lock the headerCt. This makes it so that clicking on headers * don't trigger actions like sorting or opening of the header menu. This is * done because extraneous events may be fired on the headers after interacting * with a drag drop operation. * @private */ tempLock: function() { this.ddLock = true; Ext.Function.defer(function() { this.ddLock = false; }, 200, this); }, onHeaderResize: function(header, w, suppressFocus) { var me = this, view = me.view, gridSection = me.ownerCt; // Do not react to header sizing during initial Panel layout when there is no view content to size. if (view && view.body.dom) { me.tempLock(); if (gridSection) { gridSection.onHeaderResize(me, header, w); } } me.fireEvent('columnresize', this, header, w); }, onHeaderClick: function(header, e, t) { header.fireEvent('headerclick', this, header, e, t); this.fireEvent('headerclick', this, header, e, t); }, onHeaderContextMenu: function(header, e, t) { header.fireEvent('headercontextmenu', this, header, e, t); this.fireEvent('headercontextmenu', this, header, e, t); }, onHeaderTriggerClick: function(header, e, t) { // generate and cache menu, provide ability to cancel/etc var me = this; if (header.fireEvent('headertriggerclick', me, header, e, t) !== false && me.fireEvent('headertriggerclick', me, header, e, t) !== false) { me.showMenuBy(t, header); } }, showMenuBy: function(t, header) { var menu = this.getMenu(), ascItem = menu.down('#ascItem'), descItem = menu.down('#descItem'), sortableMth; // Use ownerButton as the upward link. Menus *must have no ownerCt* - they are global floaters. // Upward navigation is done using the up() method. menu.activeHeader = menu.ownerButton = header; header.setMenuActive(true); // enable or disable asc & desc menu items based on header being sortable sortableMth = header.sortable ? 'enable' : 'disable'; if (ascItem) { ascItem[sortableMth](); } if (descItem) { descItem[sortableMth](); } menu.showBy(t); }, // remove the trigger open class when the menu is hidden onMenuHide: function(menu) { menu.activeHeader.setMenuActive(false); }, moveHeader: function(fromIdx, toIdx) { // An automatically expiring lock this.tempLock(); this.onHeaderMoved(this.move(fromIdx, toIdx), 1, fromIdx, toIdx); }, purgeHeaderCtCache: function (headerCt) { while (headerCt) { headerCt.purgeCache(); if (headerCt.isRootHeader) { return; } headerCt = headerCt.ownerCt; } }, purgeCache: function() { var me = this, menu = me.menu, visibleColumnManager = me.visibleColumnManager, columnManager = me.columnManager; // Delete column cache - column order has changed. me.gridVisibleColumns = me.gridDataColumns = me.hideableColumns = null; // ColumnManager. Only the top if (visibleColumnManager) { visibleColumnManager.invalidate(); columnManager.invalidate(); } // Menu changes when columns are moved. It will be recreated. // Menu does not change when columns are hidden or shown (which is all that happens when menu is visible) if (menu && menu.hidden) { // Must hide before destroy so that trigger el is deactivated menu.hide(); menu.destroy(); me.menu = null; } }, onHeaderMoved: function (header, colsToMove, fromIdx, toIdx) { var me = this, gridSection = me.ownerCt; if (me.rendered) { if (gridSection && gridSection.onHeaderMove) { gridSection.onHeaderMove(me, header, colsToMove, fromIdx, toIdx); } me.fireEvent('columnmove', me, header, fromIdx, toIdx); } }, /** * Gets the menu (and will create it if it doesn't already exist) * @private */ getMenu: function() { var me = this; if (!me.menu) { me.menu = new Ext.menu.Menu({ hideOnParentHide: false, // Persists when owning ColumnHeader is hidden items: me.getMenuItems(), listeners: { hide: me.onMenuHide, scope: me } }); me.fireEvent('menucreate', me, me.menu); } me.updateMenuDisabledState(me.menu); return me.menu; }, /** * Returns an array of menu items to be placed into the shared menu * across all headers in this header container. * @returns {Array} menuItems */ getMenuItems: function() { var me = this, menuItems = [], hideableColumns = me.enableColumnHide ? me.getColumnMenu(me) : null; if (me.sortable) { menuItems = [{ itemId: 'ascItem', text: me.sortAscText, iconCls: me.menuSortAscCls, handler: me.onSortAscClick, scope: me },{ itemId: 'descItem', text: me.sortDescText, iconCls: me.menuSortDescCls, handler: me.onSortDescClick, scope: me }]; } if (hideableColumns && hideableColumns.length) { if (me.sortable) { menuItems.push('-'); } menuItems.push({ itemId: 'columnItem', text: me.columnsText, iconCls: me.menuColsIcon, menu: hideableColumns, hideOnClick: false }); } return menuItems; }, // sort asc when clicking on item in menu onSortAscClick: function() { var menu = this.getMenu(), activeHeader = menu.activeHeader; activeHeader.setSortState('ASC'); }, // sort desc when clicking on item in menu onSortDescClick: function() { var menu = this.getMenu(), activeHeader = menu.activeHeader; activeHeader.setSortState('DESC'); }, /** * Returns an array of menu CheckItems corresponding to all immediate children * of the passed Container which have been configured as hideable. */ getColumnMenu: function(headerContainer) { var menuItems = [], i = 0, item, items = headerContainer.query('>gridcolumn[hideable]'), itemsLn = items.length, menuItem; for (; i < itemsLn; i++) { item = items[i]; menuItem = new Ext.menu.CheckItem({ text: item.menuText || item.text, checked: !item.hidden, hideOnClick: false, headerId: item.id, menu: item.isGroupHeader ? this.getColumnMenu(item) : undefined, checkHandler: this.onColumnCheckChange, scope: this }); menuItems.push(menuItem); // If the header is ever destroyed - for instance by dragging out the last remaining sub header, // then the associated menu item must also be destroyed. item.on({ destroy: Ext.Function.bind(menuItem.destroy, menuItem) }); } return menuItems; }, onColumnCheckChange: function(checkItem, checked) { var header = Ext.getCmp(checkItem.headerId); header[checked ? 'show' : 'hide'](); }, /** * Returns the number of grid columns descended from this HeaderContainer. * Group Columns are HeaderContainers. All grid columns are returned, including hidden ones. */ getColumnCount: function() { return this.getGridColumns().length; }, /** * Gets the full width of all columns that are visible. */ getFullWidth: function() { var fullWidth = 0, headers = this.getVisibleGridColumns(), headersLn = headers.length, i = 0, header; for (; i < headersLn; i++) { header = headers[i]; // use headers getDesiredWidth if its there if (header.getDesiredWidth) { fullWidth += header.getDesiredWidth() || 0; // if injected a diff cmp use getWidth } else { fullWidth += header.getWidth(); } } return fullWidth; }, // invoked internally by a header when not using triStateSorting clearOtherSortStates: function(activeHeader) { var headers = this.getGridColumns(), headersLn = headers.length, i = 0; for (; i < headersLn; i++) { if (headers[i] !== activeHeader) { // unset the sortstate and dont recurse headers[i].setSortState(null, true); } } }, /** * Returns an array of the **visible** columns in the grid. This goes down to the lowest column header * level, and does not return **grouped** headers which contain sub headers. * @returns {Array} */ getVisibleGridColumns: function() { if (this.gridVisibleColumns) { return this.gridVisibleColumns; } var allColumns = this.getGridColumns(), result = [], len = allColumns.length, i; // Use an inline check instead of ComponentQuery filtering for better performance for // repeated grid row rendering - as in buffered rendering. for (i = 0; i < len; i++) { if (!allColumns[i].hidden) { result[result.length] = allColumns[i]; } } this.gridVisibleColumns = result; return result; }, /** * Returns an array of all columns which appear in the grid's View. This goes down to the leaf column header * level, and does not return **grouped** headers which contain sub headers. * * It includes hidden headers even though they are not rendered. This is for collection of menu items for the column hide/show menu. * * Headers which have a hidden ancestor have a `hiddenAncestor: true` property injected so that they can also be rendered at zero width without interrogating * that header's ownerCt axis for a hidden ancestor. * @returns {Array} */ getGridColumns: function(/* private - used in recursion*/inResult, hiddenAncestor) { if (!inResult && this.gridDataColumns) { return this.gridDataColumns; } var me = this, result = inResult || [], items, i, len, item, lastVisibleColumn; hiddenAncestor = hiddenAncestor || me.hidden; if (me.items) { items = me.items.items; for (i = 0, len = items.length; i < len; i++) { item = items[i]; if (item.isGroupHeader) { item.getGridColumns(result, hiddenAncestor); } else { item.hiddenAncestor = hiddenAncestor; result.push(item); } } } if (!inResult) { me.gridDataColumns = result; } // If top level, correct first and last visible column flags if (!inResult && len) { // Set firstVisible and lastVisible flags for (i = 0, len = result.length; i < len; i++) { item = result[i]; item.isFirstVisible = item.isLastVisible = false; if (!(item.hidden || item.hiddenAncestor)) { if (!lastVisibleColumn) { item.isFirstVisible = true; } lastVisibleColumn = item; } } // If we haven't hidden all columns, tag the last visible one encountered if (lastVisibleColumn) { lastVisibleColumn.isLastVisible = true; } } return result; }, /** * @private * For use by column headers in determining whether there are any hideable columns when deciding whether or not * the header menu should be disabled. */ getHideableColumns: function() { var me = this, result = me.hideableColumns; if (!result) { result = me.hideableColumns = me.query('[hideable]'); } return result; }, /** * Returns the index of a leaf level header regardless of what the nesting * structure is. * * If a group header is passed, the index of the first leaf level header within it is returned. * * @param {Ext.grid.column.Column} header The header to find the index of * @return {Number} The index of the specified column header */ getHeaderIndex: function (header) { // Binding the columnManager to a column makes it backwards-compatible with versions // that only bind the columnManager to a root header. if (!this.columnManager) { this.columnManager = this.getOwnerHeaderCt().columnManager; } return this.columnManager.getHeaderIndex(header); }, /** * Get a leaf level header by index regardless of what the nesting * structure is. * * @param {Number} index The column index for which to retrieve the column. */ getHeaderAtIndex: function (index) { // Binding the columnManager to a column makes it backwards-compatible with versions // that only bind the columnManager to a root header. if (!this.columnManager) { this.columnManager = this.getOwnerHeaderCt().columnManager; } return this.columnManager.getHeaderAtIndex(index); }, /** * When passed a column index, returns the closet *visible* column to that. If the column at the passed index is visible, * that is returned. If it is hidden, either the next visible, or the previous visible column is returned. * * @param {Number} index Position at which to find the closest visible column. */ getVisibleHeaderClosestToIndex: function (index) { // Binding the columnManager to a column makes it backwards-compatible with versions // that only bind the columnManager to a root header. if (!this.visibleColumnManager) { this.visibleColumnManager = this.getOwnerHeaderCt().visibleColumnManager; } return this.visibleColumnManager.getVisibleHeaderClosestToIndex(index); }, applyForceFit: function (header) { var me = this, view = me.view, minWidth = Ext.grid.plugin.HeaderResizer.prototype.minColWidth, // Used when a column's max contents are larger than the available view width. useMinWidthForFlex = false, defaultWidth = Ext.grid.header.Container.prototype.defaultWidth, availFlex = me.el.getViewSize().width - (view.el.dom.scrollHeight > view.el.dom.clientHeight ? Ext.getScrollbarSize().width : 0), totalFlex = 0, items = me.getVisibleGridColumns(), hidden = header.hidden, len, i, item, maxAvailFlexOneColumn, myWidth; function getTotalFlex() { for (i = 0, len = items.length; i < len; i++) { item = items[i]; // Skip the current header. if (item === header) { continue; } item.flex = item.flex || item.width || item.getWidth(); totalFlex += item.flex; item.width = null; } } function applyWidth() { // The currently-sized column (whether resized or reshown) will already // have a width, so all other columns will need to be flexed. var isCurrentHeader; for (i = 0, len = items.length; i < len; i++) { item = items[i]; isCurrentHeader = (item === header); if (useMinWidthForFlex && !isCurrentHeader) { // The selected column is extremely large so set all the others as flex minWidth. item.flex = minWidth; item.width = null; } else if (!isCurrentHeader) { // Note that any widths MUST be converted to flex. Imagine that all but one columns // are hidden. The widths of each column very easily could be greater than the total // available width (think about the how visible header widths increase as sibling // columns are hidden), so they cannot be reliably used to size the header, and the only // safe approach is to convert any all widths to flex (except for the current header). myWidth = item.flex || defaultWidth; item.flex = Math.max(Math.ceil((myWidth / totalFlex) * availFlex), minWidth); item.width = null; } item.setWidth(item.width || item.flex); } } Ext.suspendLayouts(); // Determine the max amount of flex that a single column can have. maxAvailFlexOneColumn = (availFlex - ((items.length + 1) * minWidth)); // First, remove the header's flex as it should always receive a set width // since it is the header being operated on. header.flex = null; if (hidden) { myWidth = header.width || header.savedWidth; header.savedWidth = null; } else { myWidth = view.getMaxContentWidth(header); } // We need to know if the max content width of the selected column would blow out the // grid. If so, all the other visible columns will be flexed to minWidth. if (myWidth > maxAvailFlexOneColumn) { header.width = maxAvailFlexOneColumn; useMinWidthForFlex = true; } else { header.width = myWidth; // Substract the current header's width from the available flex + some padding // to ensure that the last column doesn't get nudged out of the view. availFlex -= myWidth + defaultWidth; getTotalFlex(); } applyWidth(); Ext.resumeLayouts(true); }, autoSizeColumn: function (header) { var view = this.view; if (view) { view.autoSizeColumn(header); if (this.forceFit) { this.applyForceFit(header); } } } }); /** * This class specifies the definition for a column inside a {@link Ext.grid.Panel}. It encompasses * both the grid header configuration as well as displaying data within the grid itself. If the * {@link #columns} configuration is specified, this column will become a column group and can * contain other columns inside. In general, this class will not be created directly, rather * an array of column configurations will be passed to the grid: * * @example * Ext.create('Ext.data.Store', { * storeId:'employeeStore', * fields:['firstname', 'lastname', 'seniority', 'dep', 'hired'], * data:[ * {firstname:"Michael", lastname:"Scott", seniority:7, dep:"Management", hired:"01/10/2004"}, * {firstname:"Dwight", lastname:"Schrute", seniority:2, dep:"Sales", hired:"04/01/2004"}, * {firstname:"Jim", lastname:"Halpert", seniority:3, dep:"Sales", hired:"02/22/2006"}, * {firstname:"Kevin", lastname:"Malone", seniority:4, dep:"Accounting", hired:"06/10/2007"}, * {firstname:"Angela", lastname:"Martin", seniority:5, dep:"Accounting", hired:"10/21/2008"} * ] * }); * * Ext.create('Ext.grid.Panel', { * title: 'Column Demo', * store: Ext.data.StoreManager.lookup('employeeStore'), * columns: [ * {text: 'First Name', dataIndex:'firstname'}, * {text: 'Last Name', dataIndex:'lastname'}, * {text: 'Hired Month', dataIndex:'hired', xtype:'datecolumn', format:'M'}, * {text: 'Department (Yrs)', xtype:'templatecolumn', tpl:'{dep} ({seniority})'} * ], * width: 400, * forceFit: true, * renderTo: Ext.getBody() * }); * * # Convenience Subclasses * * There are several column subclasses that provide default rendering for various data types * * - {@link Ext.grid.column.Action}: Renders icons that can respond to click events inline * - {@link Ext.grid.column.Boolean}: Renders for boolean values * - {@link Ext.grid.column.Date}: Renders for date values * - {@link Ext.grid.column.Number}: Renders for numeric values * - {@link Ext.grid.column.Template}: Renders a value using an {@link Ext.XTemplate} using the record data * * # Setting Sizes * * The columns are laid out by a {@link Ext.layout.container.HBox} layout, so a column can either * be given an explicit width value or a flex configuration. If no width is specified the grid will * automatically the size the column to 100px. For column groups, the size is calculated by measuring * the width of the child columns, so a width option should not be specified in that case. * * # Header Options * * - {@link #text}: Sets the header text for the column * - {@link #sortable}: Specifies whether the column can be sorted by clicking the header or using the column menu * - {@link #hideable}: Specifies whether the column can be hidden using the column menu * - {@link #menuDisabled}: Disables the column header menu * - {@link #cfg-draggable}: Specifies whether the column header can be reordered by dragging * - {@link #groupable}: Specifies whether the grid can be grouped by the column dataIndex. See also {@link Ext.grid.feature.Grouping} * * # Data Options * * - {@link #dataIndex}: The dataIndex is the field in the underlying {@link Ext.data.Store} to use as the value for the column. * - {@link #renderer}: Allows the underlying store value to be transformed before being displayed in the grid */ Ext.define('Ext.grid.column.Column', { extend: Ext.grid.header.Container , alias: 'widget.gridcolumn', alternateClassName: 'Ext.grid.Column', baseCls: Ext.baseCSSPrefix + 'column-header', // Not the standard, automatically applied overCls because we must filter out overs of child headers. hoverCls: Ext.baseCSSPrefix + 'column-header-over', handleWidth: 4, ariaRole: 'columnheader', sortState: null, possibleSortStates: ['ASC', 'DESC'], childEls: [ 'titleEl', 'triggerEl', 'textEl' ], /** * @private * @cfg {Boolean} [noWrap=true] * The default setting indicates that external CSS rules dictate that the title is `white-space: nowrap` and * therefore, width cannot affect the measured height by causing text wrapping. This is what the Sencha-supplied * styles set. If you change those styles to allow text wrapping, you must set this to `false`. */ noWrap: true, renderTpl: [ '', '{%this.renderContainer(out,values)%}' ], /** * @cfg {Object[]} columns * An optional array of sub-column definitions. This column becomes a group, and houses the columns defined in the * `columns` config. * * Group columns may not be sortable. But they may be hideable and moveable. And you may move headers into and out * of a group. Note that if all sub columns are dragged out of a group, the group is destroyed. */ /** * @cfg {String} stateId * An identifier which identifies this column uniquely within the owning grid's {@link #stateful state}. * * This does not have to be *globally* unique. A column's state is not saved standalone. It is encapsulated within * the owning grid's state. */ /** * @cfg {String} dataIndex * The name of the field in the grid's {@link Ext.data.Store}'s {@link Ext.data.Model} definition from * which to draw the column's value. **Required.** */ dataIndex: null, /** * @cfg {String} text * The header text to be used as innerHTML (html tags are accepted) to display in the Grid. * **Note**: to have a clickable header with no text displayed you can use the default of ` ` aka ` `. */ text: ' ', /** * @cfg {String} header * The header text. * @deprecated 4.0 Use {@link #text} instead. */ /** * @cfg {String} menuText * The text to render in the column visibility selection menu for this column. If not * specified, will default to the text value. */ menuText: null, /** * @cfg {String} [emptyCellText=undefined] * The text to diplay in empty cells (cells with a value of `undefined`, `null`, or `''`). * * Defaults to ` ` aka ` `. */ emptyCellText: ' ', /** * @cfg {Boolean} sortable * False to disable sorting of this column. Whether local/remote sorting is used is specified in * `{@link Ext.data.Store#remoteSort}`. */ sortable: true, /** * @cfg {Boolean} lockable * If the grid is configured with {@link Ext.panel.Table#enableLocking enableLocking}, or has columns which are * configured with a {@link #locked} value, this option may be used to disable user-driven locking or unlocking * of this column. This column will remain in the side into which its own {@link #locked} configuration placed it. */ /** * @cfg {Boolean} groupable * If the grid uses a {@link Ext.grid.feature.Grouping}, this option may be used to disable the header menu * item to group by the column selected. By default, the header menu group option is enabled. Set to false to * disable (but still show) the group option in the header menu for the column. */ /** * @cfg {Boolean} fixed * True to prevent the column from being resizable. * @deprecated 4.0 Use {@link #resizable} instead. */ /** * @cfg {Boolean} [locked=false] * True to lock this column in place. Implicitly enables locking on the grid. * See also {@link Ext.grid.Panel#enableLocking}. */ /** * @cfg {Boolean} resizable * False to prevent the column from being resizable. */ resizable: true, /** * @cfg {Boolean} hideable * False to prevent the user from hiding this column. */ hideable: true, /** * @cfg {Boolean} menuDisabled * True to disable the column header menu containing sort/hide options. */ menuDisabled: false, /** * @cfg {Function/String} renderer * A renderer is an 'interceptor' method which can be used to transform data (value, appearance, etc.) * before it is rendered. Example: * * { * renderer: function(value){ * if (value === 1) { * return '1 person'; * } * return value + ' people'; * } * } * * Additionally a string naming an {@link Ext.util.Format} method can be passed: * * { * renderer: 'uppercase' * } * * @cfg {Object} renderer.value The data value for the current cell * @cfg {Object} renderer.metaData A collection of metadata about the current cell; can be used or modified * by the renderer. Recognized properties are: tdCls, tdAttr, and style. * @cfg {Ext.data.Model} renderer.record The record for the current row * @cfg {Number} renderer.rowIndex The index of the current row * @cfg {Number} renderer.colIndex The index of the current column * @cfg {Ext.data.Store} renderer.store The data store * @cfg {Ext.view.View} renderer.view The current view * @cfg {String} renderer.return The HTML string to be rendered. */ renderer: false, /** * @cfg {Object} scope * The scope to use when calling the {@link #renderer} function. */ /** * @method defaultRenderer * When defined this will take precedence over the {@link Ext.grid.column.Column#renderer renderer} config. * This is meant to be defined in subclasses that wish to supply their own renderer. * @protected * @template */ /** * @cfg {Function} editRenderer * A renderer to be used in conjunction with {@link Ext.grid.plugin.RowEditing RowEditing}. This renderer is used to * display a custom value for non-editable fields. */ editRenderer: false, /** * @cfg {String} align * Sets the alignment of the header and rendered columns. * Possible values are: `'left'`, `'center'`, and `'right'`. */ align: 'left', /** * @cfg {Boolean} draggable * False to disable drag-drop reordering of this column. */ draggable: true, /** * @cfg {String} tooltip * A tooltip to display for this column header */ /** * @cfg {String} [tooltipType="qtip"] * The type of {@link #tooltip} to use. Either 'qtip' for QuickTips or 'title' for title attribute. */ tooltipType: 'qtip', // Header does not use the typical ComponentDraggable class and therefore we // override this with an emptyFn. It is controlled at the HeaderDragZone. initDraggable: Ext.emptyFn, /** * @cfg {String} tdCls * A CSS class names to apply to the table cells for this column. */ tdCls: '', /** * @cfg {Object/String} editor * An optional xtype or config object for a {@link Ext.form.field.Field Field} to use for editing. * Only applicable if the grid is using an {@link Ext.grid.plugin.Editing Editing} plugin. */ /** * @cfg {Object/String} field * Alias for {@link #editor}. * @deprecated 4.0.5 Use {@link #editor} instead. */ /** * @property {Ext.Element} triggerEl * Element that acts as button for column header dropdown menu. */ /** * @property {Ext.Element} textEl * Element that contains the text in column header. */ /** * @property {Boolean} isHeader * @deprecated see isColumn * Set in this class to identify, at runtime, instances which are not instances of the * HeaderContainer base class, but are in fact, the subclass: Header. */ isHeader: true, /** * @property {Boolean} isColumn * @readonly * Set in this class to identify, at runtime, instances which are not instances of the * HeaderContainer base class, but are in fact simple column headers. */ isColumn: true, ascSortCls: Ext.baseCSSPrefix + 'column-header-sort-ASC', descSortCls: Ext.baseCSSPrefix + 'column-header-sort-DESC', componentLayout: 'columncomponent', groupSubHeaderCls: Ext.baseCSSPrefix + 'group-sub-header', groupHeaderCls: Ext.baseCSSPrefix + 'group-header', clickTargetName: 'titleEl', // So that when removing from group headers which are then empty and then get destroyed, there's no child DOM left detachOnRemove : true, // We need to override the default component resizable behaviour here initResizable: Ext.emptyFn, initComponent: function() { var me = this, renderer, listeners; if (me.header != null) { me.text = me.header; me.header = null; } if (!me.triStateSort) { me.possibleSortStates.length = 2; } // A group header; It contains items which are themselves Headers if (me.columns != null) { me.isGroupHeader = true; // The headers become child items me.items = me.columns; me.columns = me.flex = me.width = null; me.cls = (me.cls||'') + ' ' + me.groupHeaderCls; // A group cannot be sorted, or resized - it shrinkwraps its children me.sortable = me.resizable = false; me.align = 'center'; } else { // Flexed Headers need to have a minWidth defined so that they can never be squeezed out of existence by the // HeaderContainer's specialized Box layout, the ColumnLayout. The ColumnLayout's overridden calculateChildboxes // method extends the available layout space to accommodate the "desiredWidth" of all the columns. if (me.flex) { me.minWidth = me.minWidth || Ext.grid.plugin.HeaderResizer.prototype.minColWidth; } } me.addCls(Ext.baseCSSPrefix + 'column-header-align-' + me.align); renderer = me.renderer; if (renderer) { // When specifying a renderer as a string, it always resolves // to Ext.util.Format if (typeof renderer == 'string') { me.renderer = Ext.util.Format[renderer]; } me.hasCustomRenderer = true; } else if (me.defaultRenderer) { me.scope = me; me.renderer = me.defaultRenderer; } // Initialize as a HeaderContainer me.callParent(arguments); listeners = { element: me.clickTargetName, click: me.onTitleElClick, contextmenu: me.onTitleElContextMenu, mouseenter: me.onTitleMouseOver, mouseleave: me.onTitleMouseOut, scope: me }; if (me.resizable) { listeners.dblclick = me.onTitleElDblClick; } me.on(listeners); }, initItems: function() { var me = this; me.callParent(arguments); if (me.isGroupHeader) { if (!me.hasVisibleChildren()) { me.hide(); } } }, hasVisibleChildren: function() { var items = this.items.items, len = items.length, i; for (i = 0; i < len; ++i) { if (!items[i].hidden) { return true; } } return false; }, onAdd: function(child) { var me = this, ownerHeaderCt = me.getOwnerHeaderCt(); if (child.isColumn) { child.isSubHeader = true; child.addCls(this.groupSubHeaderCls); } if (me.hidden) { // Only hide automatically during construction time (no header) if (!ownerHeaderCt) { child.hide(); } else if (!child.hidden) { me.show(); } } me.callParent(arguments); }, onRemove: function(child) { var me = this; if (child.isSubHeader) { child.isSubHeader = false; child.removeCls(me.groupSubHeaderCls); } me.callParent(arguments); // By this point, the component will be removed from the items collection if (me.isGroupHeader && !me.hasVisibleChildren()) { me.hide(); } }, initRenderData: function() { var me = this, tipMarkup = '', tip = me.tooltip, text = me.text, attr = me.tooltipType == 'qtip' ? 'data-qtip' : 'title'; if (!Ext.isEmpty(tip)) { tipMarkup = attr + '="' + tip + '" '; } return Ext.applyIf(me.callParent(arguments), { text: text, empty: text === ' ' || text === ' ' || text === '', menuDisabled: me.menuDisabled, tipMarkup: tipMarkup }); }, applyColumnState: function (state) { var me = this; // apply any columns me.applyColumnsState(state.columns); // Only state properties which were saved should be restored. // (Only user-changed properties were saved by getState) if (state.hidden != null) { me.hidden = state.hidden; } if (state.locked != null) { me.locked = state.locked; } if (state.sortable != null) { me.sortable = state.sortable; } if (state.width != null) { me.flex = null; me.width = state.width; } else if (state.flex != null) { me.width = null; me.flex = state.flex; } }, getColumnState: function () { var me = this, items = me.items.items, // Check for the existence of items, since column.Action won't have them iLen = items ? items.length : 0, i, columns = [], state = { id: me.getStateId() }; me.savePropsToState(['hidden', 'sortable', 'locked', 'flex', 'width'], state); if (me.isGroupHeader) { for (i = 0; i < iLen; i++) { columns.push(items[i].getColumnState()); } if (columns.length) { state.columns = columns; } } else if (me.isSubHeader && me.ownerCt.hidden) { // don't set hidden on the children so they can auto height delete me.hidden; } if ('width' in state) { delete state.flex; // width wins } return state; }, getStateId: function () { return this.stateId || this.headerId; }, /** * Sets the header text for this Column. * @param {String} text The header to display on this Column. */ setText: function(text) { this.text = text; if (this.rendered) { this.textEl.update(text); } }, /** * Returns the index of this column only if this column is a base level Column. If it * is a group column, it returns `false`. * @return {Number} */ getIndex: function() { return this.isGroupColumn ? false : this.getOwnerHeaderCt().getHeaderIndex(this); }, /** * Returns the index of this column in the list of *visible* columns only if this column is a base level Column. If it * is a group column, it returns `false`. * @return {Number} */ getVisibleIndex: function() { return this.isGroupColumn ? false : Ext.Array.indexOf(this.getOwnerHeaderCt().getVisibleGridColumns(), this); }, beforeRender: function() { var me = this, grid = me.up('tablepanel'); me.callParent(); // Disable the menu if there's nothing to show in the menu, ie: // Column cannot be sorted, grouped or locked, and there are no grid columns which may be hidden if (grid && (!me.sortable || grid.sortableColumns === false) && !me.groupable && !me.lockable && (grid.enableColumnHide === false || !me.getOwnerHeaderCt().getHideableColumns().length)) { me.menuDisabled = true; } me.protoEl.unselectable(); }, afterRender: function() { var me = this, triggerEl = me.triggerEl; me.callParent(arguments); // BrowserBug: Ie8 Strict Mode, this will break the focus for this browser, // must be fixed when focus management will be implemented. if (!Ext.isIE8 || !Ext.isStrict) { me.mon(me.getFocusEl(), { focus: me.onTitleMouseOver, blur: me.onTitleMouseOut, scope: me }); } if (triggerEl && me.self.triggerElWidth === undefined) { triggerEl.setStyle('display', 'block'); me.self.triggerElWidth = triggerEl.getWidth(); triggerEl.setStyle('display', ''); } me.keyNav = new Ext.util.KeyNav(me.el, { enter: me.onEnterKey, down: me.onDownKey, scope: me }); }, // private // Inform the header container about the resize afterComponentLayout: function(width, height, oldWidth, oldHeight) { var me = this, ownerHeaderCt = me.getOwnerHeaderCt(); me.callParent(arguments); if (ownerHeaderCt && (oldWidth != null || me.flex) && width !== oldWidth) { ownerHeaderCt.onHeaderResize(me, width, true); } }, onDestroy: function() { var me = this; // force destroy on the textEl, IE reports a leak Ext.destroy(me.textEl, me.keyNav, me.field); me.keyNav = null; me.callParent(arguments); }, onTitleMouseOver: function() { this.titleEl.addCls(this.hoverCls); }, onTitleMouseOut: function() { this.titleEl.removeCls(this.hoverCls); }, onDownKey: function(e) { if (this.triggerEl) { this.onTitleElClick(e, this.triggerEl.dom || this.el.dom); } }, onEnterKey: function(e) { this.onTitleElClick(e, this.el.dom); }, /** * @private * Double click handler which, if on left or right edges, auto-sizes the column to the left. * @param e The dblclick event */ onTitleElDblClick: function(e, t) { var me = this, prev, leafColumns; // On left edge, resize previous *leaf* column in the grid if (me.isOnLeftEdge(e)) { // Look for the previous visible column header which is a leaf // Note: previousNode can walk out of the container (this may be first child of a group) prev = me.previousNode('gridcolumn:not([hidden]):not([isGroupHeader])'); // If found in the same grid, autosize it if (prev && prev.getOwnerHeaderCt() === me.getOwnerHeaderCt()) { prev.autoSize(); } } // On right edge, resize this column, or last sub-column within it else if (me.isOnRightEdge(e)) { // Click on right but in child container - autosize last leaf column if (me.isGroupHeader && e.getPoint().isContainedBy(me.layout.innerCt)) { leafColumns = me.query('gridcolumn:not([hidden]):not([isGroupHeader])'); this.getOwnerHeaderCt().autoSizeColumn(leafColumns[leafColumns.length - 1]); return; } me.autoSize(); } }, /** * Sizes this Column to fit the max content width. * *Note that group columns shrinkwrap around the size of leaf columns. Auto sizing a group column * autosizes descendant leaf columns.* * @param {Ext.grid.column.Column/Number} The header (or index of header) to auto size. */ autoSize: function() { var me = this, leafColumns, numLeaves, i, headerCt; // Group headers are shrinkwrap width, so autosizing one means autosizing leaf descendants. if (me.isGroupHeader) { leafColumns = me.query('gridcolumn:not([hidden]):not([isGroupHeader])'); numLeaves = leafColumns.length; headerCt = this.getOwnerHeaderCt(); Ext.suspendLayouts(); for (i = 0; i < numLeaves; i++) { headerCt.autoSizeColumn(leafColumns[i]); } Ext.resumeLayouts(true); return; } this.getOwnerHeaderCt().autoSizeColumn(this); }, onTitleElClick: function(e, t) { // The grid's docked HeaderContainer. var me = this, ownerHeaderCt = me.getOwnerHeaderCt(); if (ownerHeaderCt && !ownerHeaderCt.ddLock) { // Firefox doesn't check the current target in a within check. // Therefore we check the target directly and then within (ancestors) if (me.triggerEl && (e.target === me.triggerEl.dom || t === me.triggerEl.dom || e.within(me.triggerEl))) { ownerHeaderCt.onHeaderTriggerClick(me, e, t); // if its not on the left hand edge, sort } else if (e.getKey() || (!me.isOnLeftEdge(e) && !me.isOnRightEdge(e))) { me.toggleSortState(); ownerHeaderCt.onHeaderClick(me, e, t); } } }, onTitleElContextMenu: function(e, t) { // The grid's docked HeaderContainer. var me = this, ownerHeaderCt = me.getOwnerHeaderCt(); if (ownerHeaderCt && !ownerHeaderCt.ddLock) { ownerHeaderCt.onHeaderContextMenu(me, e, t); } }, /** * @private * Process UI events from the view. The owning TablePanel calls this method, relaying events from the TableView * @param {String} type Event type, eg 'click' * @param {Ext.view.Table} view TableView Component * @param {HTMLElement} cell Cell HtmlElement the event took place within * @param {Number} recordIndex Index of the associated Store Model (-1 if none) * @param {Number} cellIndex Cell index within the row * @param {Ext.EventObject} e Original event */ processEvent: function(type, view, cell, recordIndex, cellIndex, e) { return this.fireEvent.apply(this, arguments); }, toggleSortState: function() { var me = this, idx, nextIdx; if (me.sortable) { idx = Ext.Array.indexOf(me.possibleSortStates, me.sortState); nextIdx = (idx + 1) % me.possibleSortStates.length; me.setSortState(me.possibleSortStates[nextIdx]); } }, doSort: function(state) { var tablePanel = this.up('tablepanel'), store = tablePanel.store; // If the owning Panel's store is a NodeStore, this means that we are the unlocked side // of a locked TreeGrid. We must use the TreeStore's sort method because we cannot // reorder the NodeStore - that would break the tree. if (tablePanel.ownerLockable && store.isNodeStore) { store = tablePanel.ownerLockable.lockedGrid.store; } store.sort({ property: this.getSortParam(), direction: state }); }, /** * Returns the parameter to sort upon when sorting this header. By default this returns the dataIndex and will not * need to be overriden in most cases. * @return {String} */ getSortParam: function() { return this.dataIndex; }, setSortState: function(state, skipClear, initial) { var me = this, ascCls = me.ascSortCls, descCls = me.descSortCls, ownerHeaderCt = me.getOwnerHeaderCt(), oldSortState = me.sortState; state = state || null; if (!me.sorting && oldSortState !== state && (me.getSortParam() != null)) { // don't trigger a sort on the first time, we just want to update the UI if (state && !initial) { // when sorting, it will call setSortState on the header again once // refresh is called me.sorting = true; me.doSort(state); me.sorting = false; } switch (state) { case 'DESC': me.addCls(descCls); me.removeCls(ascCls); break; case 'ASC': me.addCls(ascCls); me.removeCls(descCls); break; default: me.removeCls([ascCls, descCls]); } if (ownerHeaderCt && !me.triStateSort && !skipClear) { ownerHeaderCt.clearOtherSortStates(me); } me.sortState = state; // we only want to fire the event if we have a null state when using triStateSort if (me.triStateSort || state != null) { ownerHeaderCt.fireEvent('sortchange', ownerHeaderCt, me, state); } } }, /** * Determines whether the UI should be allowed to offer an option to hide this column. * * A column may *not* be hidden if to do so would leave the grid with no visible columns. * * This is used to determine the enabled/disabled state of header hide menu items. */ isHideable: function() { var result = { hideCandidate: this, result: this.hideable }; if (result.result) { this.ownerCt.bubble(this.hasOtherMenuEnabledChildren, null, [result]); } return result.result; }, // Private bubble function used in determining whether this column is hideable. // Executes in the scope of each component in the bubble sequence hasOtherMenuEnabledChildren: function(result) { var visibleChildren, count; // If we've bubbled out the top of the topmost HeaderContainer without finding a level with at least one visible, // menu-enabled child *which is not the hideCandidate*, no hide! if (!this.isXType('headercontainer')) { result.result = false; return false; } // If we find an ancestor level with at leat one visible, menu-enabled child *which is not the hideCandidate*, // then the hideCandidate is hideable. // Note that we are not using CQ #id matchers - ':not(#' + result.hideCandidate.id + ')' - to exclude // the hideCandidate because CQ queries are cached for the document's lifetime. visibleChildren = this.query('>:not([hidden]):not([menuDisabled])'); count = visibleChildren.length; if (Ext.Array.contains(visibleChildren, result.hideCandidate)) { count--; } if (count) { return false; } // If we go up, it's because the hideCandidate was the only hideable child, so *this* becomes the hide candidate. result.hideCandidate = this; }, /** * Determines whether the UI should be allowed to offer an option to lock or unlock this column. Note * that this includes dragging a column into the opposite side of a {@link Ext.panel.Table#enableLocking lockable} grid. * * A column may *not* be moved from one side to the other of a {@link Ext.panel.Table#enableLocking lockable} grid * if to do so would leave one side with no visible columns. * * This is used to determine the enabled/disabled state of the lock/unlock * menu item used in {@link Ext.panel.Table#enableLocking lockable} grids, and to determine dropppabilty when dragging a header. */ isLockable: function() { var result = { result: this.lockable !== false }; if (result.result) { this.ownerCt.bubble(this.hasMultipleVisibleChildren, null, [result]); } return result.result; }, /* * Determines whether this column is in the locked side of a grid. It may be a descendant node of a locked column * and as such will *not* have the {@link #locked} flag set. */ isLocked: function() { return this.locked || !!this.up('[isColumn][locked]', '[isRootHeader]'); }, // Private bubble function used in determining whether this column is lockable. // Executes in the scope of each component in the bubble sequence hasMultipleVisibleChildren: function(result) { // If we've bubbled out the top of the topmost HeaderContainer without finding a level with more than one visible child, no hide! if (!this.isXType('headercontainer')) { result.result = false; return false; } // If we find an ancestor level with more than one visible child, it's fine to hide if (this.query('>:not([hidden])').length > 1) { return false; } }, hide: function(fromOwner) { var me = this, ownerHeaderCt = me.getOwnerHeaderCt(), owner = me.ownerCt, ownerIsGroup, item, items, len, i; // If we have no ownerHeaderCt, it's during object construction, so // just set the hidden flag and jump out if (!ownerHeaderCt) { me.callParent(); return me; } if (me.rendered && !me.isVisible()) { // Already hidden return me; } // Save our last shown width so we can gain space when shown back into fully flexed HeaderContainer. // If we are, say, flex: 1 and all others are fixed width, then removing will do a layout which will // convert all widths to flexes which will mean this flex value is too small. if (ownerHeaderCt.forceFit) { me.visibleSiblingCount = ownerHeaderCt.getVisibleGridColumns().length - 1; if (me.flex) { me.savedWidth = me.getWidth(); me.flex = null; } } ownerIsGroup = owner.isGroupHeader; // owner is a group, hide call didn't come from the owner if (ownerIsGroup && !fromOwner) { items = owner.query('>:not([hidden])'); // The owner only has one item that isn't hidden and it's me; hide the owner. if (items.length === 1 && items[0] == me) { me.ownerCt.hide(); return; } } Ext.suspendLayouts(); if (me.isGroupHeader) { items = me.items.items; for (i = 0, len = items.length; i < len; i++) { item = items[i]; if (!item.hidden) { item.hide(true); } } } me.callParent(); // Notify owning HeaderContainer ownerHeaderCt.onHeaderHide(me); Ext.resumeLayouts(true); return me; }, show: function(fromOwner, fromChild) { var me = this, ownerHeaderCt = me.getOwnerHeaderCt(), ownerCt = me.ownerCt, items, len, i, item; if (me.isVisible()) { return me; } if (me.rendered) { // Size all other columns to accommodate re-shown column. if (ownerHeaderCt.forceFit) { ownerHeaderCt.applyForceFit(me); } } Ext.suspendLayouts(); // If a sub header, ensure that the group header is visible if (me.isSubHeader && ownerCt.hidden) { ownerCt.show(false, true); } me.callParent(arguments); // If we've just shown a group with all its sub headers hidden, then show all its sub headers if (me.isGroupHeader && fromChild !== true && !me.query(':not([hidden])').length) { items = me.items.items; for (i = 0, len = items.length; i < len; i++) { item = items[i]; if (item.hidden) { item.show(true); } } } Ext.resumeLayouts(true); // Notify owning HeaderContainer AFTER layout has been flushed so that header and headerCt widths are all correct ownerCt = me.getOwnerHeaderCt(); if (ownerCt) { ownerCt.onHeaderShow(me); } }, getDesiredWidth: function() { var me = this; if (me.rendered && me.componentLayout && me.componentLayout.lastComponentSize) { // headers always have either a width or a flex // because HeaderContainer sets a defaults width // therefore we can ignore the natural width // we use the componentLayout's tracked width so that // we can calculate the desired width when rendered // but not visible because its being obscured by a layout return me.componentLayout.lastComponentSize.width; // Flexed but yet to be rendered this could be the case // where a HeaderContainer and Headers are simply used as data // structures and not rendered. } else if (me.flex) { // this is going to be wrong, the defaultWidth return me.width; } else { return me.width; } }, getCellId: function() { return Ext.baseCSSPrefix + 'grid-cell-headerId-' + this.getItemId(); }, getCellSelector: function() { return '.' + this.getCellId(); }, getCellInnerSelector: function() { return this.getCellSelector() + ' .' + Ext.baseCSSPrefix + 'grid-cell-inner'; }, isOnLeftEdge: function(e) { return (e.getXY()[0] - this.getX() <= this.handleWidth); }, isOnRightEdge: function(e) { return (this.getX() + this.getWidth() - e.getXY()[0] <= this.handleWidth); }, // Called when the column menu is activated/deactivated. // Change the UI to indicate active/inactive menu setMenuActive: function(isMenuOpen) { this.titleEl[isMenuOpen ? 'addCls' : 'removeCls'](this.headerOpenCls); } // intentionally omit getEditor and setEditor definitions bc we applyIf into columns // when the editing plugin is injected /** * @method getEditor * Retrieves the editing field for editing associated with this header. Returns false if there is no field * associated with the Header the method will return false. If the field has not been instantiated it will be * created. Note: These methods only have an implementation if an Editing plugin has been enabled on the grid. * @param {Object} record The {@link Ext.data.Model Model} instance being edited. * @param {Object} defaultField An object representing a default field to be created * @return {Ext.form.field.Field} field */ /** * @method setEditor * Sets the form field to be used for editing. Note: This method only has an implementation if an Editing plugin has * been enabled on the grid. * @param {Object} field An object representing a field to be created. If no xtype is specified a 'textfield' is * assumed. */ }); /** * A Grid header type which renders an icon, or a series of icons in a grid cell, and offers a scoped click * handler for each icon. * * @example * Ext.create('Ext.data.Store', { * storeId:'employeeStore', * fields:['firstname', 'lastname', 'seniority', 'dep', 'hired'], * data:[ * {firstname:"Michael", lastname:"Scott"}, * {firstname:"Dwight", lastname:"Schrute"}, * {firstname:"Jim", lastname:"Halpert"}, * {firstname:"Kevin", lastname:"Malone"}, * {firstname:"Angela", lastname:"Martin"} * ] * }); * * Ext.create('Ext.grid.Panel', { * title: 'Action Column Demo', * store: Ext.data.StoreManager.lookup('employeeStore'), * columns: [ * {text: 'First Name', dataIndex:'firstname'}, * {text: 'Last Name', dataIndex:'lastname'}, * { * xtype:'actioncolumn', * width:50, * items: [{ * icon: 'extjs/examples/shared/icons/fam/cog_edit.png', // Use a URL in the icon config * tooltip: 'Edit', * handler: function(grid, rowIndex, colIndex) { * var rec = grid.getStore().getAt(rowIndex); * alert("Edit " + rec.get('firstname')); * } * },{ * icon: 'extjs/examples/restful/images/delete.png', * tooltip: 'Delete', * handler: function(grid, rowIndex, colIndex) { * var rec = grid.getStore().getAt(rowIndex); * alert("Terminate " + rec.get('firstname')); * } * }] * } * ], * width: 250, * renderTo: Ext.getBody() * }); * * The action column can be at any index in the columns array, and a grid can have any number of * action columns. */ Ext.define('Ext.grid.column.Action', { extend: Ext.grid.column.Column , alias: ['widget.actioncolumn'], alternateClassName: 'Ext.grid.ActionColumn', /** * @cfg {String} icon * The URL of an image to display as the clickable element in the column. * * Defaults to `{@link Ext#BLANK_IMAGE_URL}`. */ /** * @cfg {String} iconCls * A CSS class to apply to the icon image. To determine the class dynamically, configure the Column with * a `{@link #getClass}` function. */ /** * @cfg {Function} handler * A function called when the icon is clicked. * @cfg {Ext.view.Table} handler.view The owning TableView. * @cfg {Number} handler.rowIndex The row index clicked on. * @cfg {Number} handler.colIndex The column index clicked on. * @cfg {Object} handler.item The clicked item (or this Column if multiple {@link #cfg-items} were not configured). * @cfg {Event} handler.e The click event. * @cfg {Ext.data.Model} handler.record The Record underlying the clicked row. * @cfg {HTMLElement} handler.row The table row clicked upon. */ /** * @cfg {Object} scope * The scope (`this` reference) in which the `{@link #handler}`, `{@link #getClass}`, `{@link #cfg-isDisabled}` and `{@link #getTip}` fuctions are executed. * Defaults to this Column. */ /** * @cfg {String} tooltip * A tooltip message to be displayed on hover. {@link Ext.tip.QuickTipManager#init Ext.tip.QuickTipManager} must * have been initialized. * * The tooltip may also be determined on a row by row basis by configuring a {@link #getTip} method. */ /** * @cfg {Boolean} disabled * If true, the action will not respond to click events, and will be displayed semi-opaque. * * This Column may also be disabled on a row by row basis by configuring a {@link #cfg-isDisabled} method. */ /** * @cfg {Boolean} [stopSelection=true] * Prevent grid selection upon mousedown. */ /** * @cfg {Function} getClass * A function which returns the CSS class to apply to the icon image. * @cfg {Object} getClass.v The value of the column's configured field (if any). * @cfg {Object} getClass.metadata An object in which you may set the following attributes: * @cfg {String} getClass.metadata.css A CSS class name to add to the cell's TD element. * @cfg {String} getClass.metadata.attr An HTML attribute definition string to apply to the data container * element *within* the table cell (e.g. 'style="color:red;"'). * @cfg {Ext.data.Model} getClass.r The Record providing the data. * @cfg {Number} getClass.rowIndex The row index. * @cfg {Number} getClass.colIndex The column index. * @cfg {Ext.data.Store} getClass.store The Store which is providing the data Model. */ /** * @cfg {Function} isDisabled A function which determines whether the action item for any row is disabled and returns `true` or `false`. * @cfg {Ext.view.Table} isDisabled.view The owning TableView. * @cfg {Number} isDisabled.rowIndex The row index. * @cfg {Number} isDisabled.colIndex The column index. * @cfg {Object} isDisabled.item The clicked item (or this Column if multiple {@link #cfg-items} were not configured). * @cfg {Ext.data.Model} isDisabled.record The Record underlying the row. */ /** * @cfg {Function} getTip A function which returns the tooltip string for any row. * @cfg {Object} getTip.v The value of the column's configured field (if any). * @cfg {Object} getTip.metadata An object in which you may set the following attributes: * @cfg {String} getTip.metadata.css A CSS class name to add to the cell's TD element. * @cfg {String} getTip.metadata.attr An HTML attribute definition string to apply to the data * container element _within_ the table cell (e.g. 'style="color:red;"'). * @cfg {Ext.data.Model} getTip.r The Record providing the data. * @cfg {Number} getTip.rowIndex The row index. * @cfg {Number} getTip.colIndex The column index. * @cfg {Ext.data.Store} getTip.store The Store which is providing the data Model. * */ /** * @cfg {Object[]} items * An Array which may contain multiple icon definitions, each element of which may contain: * * @cfg {String} items.icon The url of an image to display as the clickable element in the column. * * @cfg {String} items.iconCls A CSS class to apply to the icon image. To determine the class dynamically, * configure the item with a `getClass` function. * * @cfg {Function} items.getClass A function which returns the CSS class to apply to the icon image. * @cfg {Object} items.getClass.v The value of the column's configured field (if any). * @cfg {Object} items.getClass.metadata An object in which you may set the following attributes: * @cfg {String} items.getClass.metadata.css A CSS class name to add to the cell's TD element. * @cfg {String} items.getClass.metadata.attr An HTML attribute definition string to apply to the data * container element _within_ the table cell (e.g. 'style="color:red;"'). * @cfg {Ext.data.Model} items.getClass.r The Record providing the data. * @cfg {Number} items.getClass.rowIndex The row index. * @cfg {Number} items.getClass.colIndex The column index. * @cfg {Ext.data.Store} items.getClass.store The Store which is providing the data Model. * * @cfg {Function} items.handler A function called when the icon is clicked. * @cfg {Ext.view.Table} items.handler.view The owning TableView. * @cfg {Number} items.handler.rowIndex The row index clicked on. * @cfg {Number} items.handler.colIndex The column index clicked on. * @cfg {Object} items.handler.item The clicked item (or this Column if multiple {@link #cfg-items} were not configured). * @cfg {Event} items.handler.e The click event. * @cfg {Ext.data.Model} items.handler.record The Record underlying the clicked row. * @cfg {HTMLElement} items.row The table row clicked upon. * * @cfg {Function} items.isDisabled A function which determines whether the action item for any row is disabled and returns `true` or `false`. * @cfg {Ext.view.Table} items.isDisabled.view The owning TableView. * @cfg {Number} items.isDisabled.rowIndex The row index. * @cfg {Number} items.isDisabled.colIndex The column index. * @cfg {Object} items.isDisabled.item The clicked item (or this Column if multiple {@link #cfg-items} were not configured). * @cfg {Ext.data.Model} items.isDisabled.record The Record underlying the row. * * @cfg {Function} items.getTip A function which returns the tooltip string for any row. * @cfg {Object} items.getTip.v The value of the column's configured field (if any). * @cfg {Object} items.getTip.metadata An object in which you may set the following attributes: * @cfg {String} items.getTip.metadata.css A CSS class name to add to the cell's TD element. * @cfg {String} items.getTip.metadata.attr An HTML attribute definition string to apply to the data * container element _within_ the table cell (e.g. 'style="color:red;"'). * @cfg {Ext.data.Model} items.getTip.r The Record providing the data. * @cfg {Number} items.getTip.rowIndex The row index. * @cfg {Number} items.getTip.colIndex The column index. * @cfg {Ext.data.Store} items.getTip.store The Store which is providing the data Model. * * @cfg {Object} items.scope The scope (`this` reference) in which the `handler`, `getClass`, `isDisabled` and `getTip` functions * are executed. Fallback defaults are this Column's configured scope, then this Column. * * @cfg {String} items.tooltip A tooltip message to be displayed on hover. * {@link Ext.tip.QuickTipManager#init Ext.tip.QuickTipManager} must have been initialized. * * The tooltip may also be determined on a row by row basis by configuring a `getTip` method. * * @cfg {Boolean} items.disabled If true, the action will not respond to click events, and will be displayed semi-opaque. * * This item may also be disabled on a row by row basis by configuring an `isDisabled` method. */ /** * @property {Array} items * An array of action items copied from the configured {@link #cfg-items items} configuration. Each will have * an `enable` and `disable` method added which will enable and disable the associated action, and * update the displayed icon accordingly. */ actionIdRe: new RegExp(Ext.baseCSSPrefix + 'action-col-(\\d+)'), /** * @cfg {String} altText * The alt text to use for the image element. */ altText: '', /** * @cfg {String} [menuText=Actions] * Text to display in this column's menu item if no {@link #text} was specified as a header. */ menuText: 'Actions', sortable: false, innerCls: Ext.baseCSSPrefix + 'grid-cell-inner-action-col', constructor: function(config) { var me = this, cfg = Ext.apply({}, config), // Items may be defined on the prototype items = cfg.items || me.items || [me], hasGetClass, i, len; me.origRenderer = cfg.renderer || me.renderer; me.origScope = cfg.scope || me.scope; me.renderer = me.scope = cfg.renderer = cfg.scope = null; // This is a Container. Delete the items config to be reinstated after construction. cfg.items = null; me.callParent([cfg]); // Items is an array property of ActionColumns me.items = items; for (i = 0, len = items.length; i < len; ++i) { if (items[i].getClass) { hasGetClass = true; break; } } // Also need to check for getClass, since it changes how the cell renders if (me.origRenderer || hasGetClass) { me.hasCustomRenderer = true; } }, // Renderer closure iterates through items creating an element for each and tagging with an identifying // class name x-action-col-{n} defaultRenderer: function(v, meta, record, rowIdx, colIdx, store, view){ var me = this, prefix = Ext.baseCSSPrefix, scope = me.origScope || me, items = me.items, len = items.length, i = 0, item, ret, disabled, tooltip; // Allow a configured renderer to create initial value (And set the other values in the "metadata" argument!) // Assign a new variable here, since if we modify "v" it will also modify the arguments collection, meaning // we will pass an incorrect value to getClass/getTip ret = Ext.isFunction(me.origRenderer) ? me.origRenderer.apply(scope, arguments) || '' : ''; meta.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell'; for (; i < len; i++) { item = items[i]; disabled = item.disabled || (item.isDisabled ? item.isDisabled.call(item.scope || scope, view, rowIdx, colIdx, item, record) : false); tooltip = disabled ? null : (item.tooltip || (item.getTip ? item.getTip.apply(item.scope || scope, arguments) : null)); // Only process the item action setup once. if (!item.hasActionConfiguration) { // Apply our documented default to all items item.stopSelection = me.stopSelection; item.disable = Ext.Function.bind(me.disableAction, me, [i], 0); item.enable = Ext.Function.bind(me.enableAction, me, [i], 0); item.hasActionConfiguration = true; } ret += '' + (item.altText || me.altText) + ''; } return ret; }, /** * Enables this ActionColumn's action at the specified index. * @param {Number/Ext.grid.column.Action} index * @param {Boolean} [silent=false] */ enableAction: function(index, silent) { var me = this; if (!index) { index = 0; } else if (!Ext.isNumber(index)) { index = Ext.Array.indexOf(me.items, index); } me.items[index].disabled = false; me.up('tablepanel').el.select('.' + Ext.baseCSSPrefix + 'action-col-' + index).removeCls(me.disabledCls); if (!silent) { me.fireEvent('enable', me); } }, /** * Disables this ActionColumn's action at the specified index. * @param {Number/Ext.grid.column.Action} index * @param {Boolean} [silent=false] */ disableAction: function(index, silent) { var me = this; if (!index) { index = 0; } else if (!Ext.isNumber(index)) { index = Ext.Array.indexOf(me.items, index); } me.items[index].disabled = true; me.up('tablepanel').el.select('.' + Ext.baseCSSPrefix + 'action-col-' + index).addCls(me.disabledCls); if (!silent) { me.fireEvent('disable', me); } }, destroy: function() { delete this.items; delete this.renderer; return this.callParent(arguments); }, /** * @private * Process and refire events routed from the GridView's processEvent method. * Also fires any configured click handlers. By default, cancels the mousedown event to prevent selection. * Returns the event handler's status to allow canceling of GridView's bubbling process. */ processEvent : function(type, view, cell, recordIndex, cellIndex, e, record, row){ var me = this, target = e.getTarget(), match, item, fn, key = type == 'keydown' && e.getKey(), disabled; // If the target was not within a cell (ie it's a keydown event from the View), then // rely on the selection data injected by View.processUIEvent to grab the // first action icon from the selected cell. if (key && !Ext.fly(target).findParent(view.getCellSelector())) { target = Ext.fly(cell).down('.' + Ext.baseCSSPrefix + 'action-col-icon', true); } // NOTE: The statement below tests the truthiness of an assignment. if (target && (match = target.className.match(me.actionIdRe))) { item = me.items[parseInt(match[1], 10)]; disabled = item.disabled || (item.isDisabled ? item.isDisabled.call(item.scope || me.origScope || me, view, recordIndex, cellIndex, item, record) : false); if (item && !disabled) { if (type == 'click' || (key == e.ENTER || key == e.SPACE)) { fn = item.handler || me.handler; if (fn) { fn.call(item.scope || me.origScope || me, view, recordIndex, cellIndex, item, e, record, row); } } else if (type == 'mousedown' && item.stopSelection !== false) { return false; } } } return me.callParent(arguments); }, cascade: function(fn, scope) { fn.call(scope||this, this); }, // Private override because this cannot function as a Container, and it has an items property which is an Array, NOT a MixedCollection. getRefItems: function() { return []; } }); /** * A Column definition class which renders boolean data fields. See the {@link Ext.grid.column.Column#xtype xtype} * config option of {@link Ext.grid.column.Column} for more details. * * @example * Ext.create('Ext.data.Store', { * storeId:'sampleStore', * fields:[ * {name: 'framework', type: 'string'}, * {name: 'rocks', type: 'boolean'} * ], * data:{'items':[ * { 'framework': "Ext JS 4", 'rocks': true }, * { 'framework': "Sencha Touch", 'rocks': true }, * { 'framework': "Ext GWT", 'rocks': true }, * { 'framework': "Other Guys", 'rocks': false } * ]}, * proxy: { * type: 'memory', * reader: { * type: 'json', * root: 'items' * } * } * }); * * Ext.create('Ext.grid.Panel', { * title: 'Boolean Column Demo', * store: Ext.data.StoreManager.lookup('sampleStore'), * columns: [ * { text: 'Framework', dataIndex: 'framework', flex: 1 }, * { * xtype: 'booleancolumn', * text: 'Rocks', * trueText: 'Yes', * falseText: 'No', * dataIndex: 'rocks' * } * ], * height: 200, * width: 400, * renderTo: Ext.getBody() * }); */ Ext.define('Ext.grid.column.Boolean', { extend: Ext.grid.column.Column , alias: ['widget.booleancolumn'], alternateClassName: 'Ext.grid.BooleanColumn', // /** * @cfg {String} trueText * The string returned by the renderer when the column value is not falsey. */ trueText: 'true', // // /** * @cfg {String} falseText * The string returned by the renderer when the column value is falsey (but not undefined). */ falseText: 'false', // /** * @cfg {String} undefinedText * The string returned by the renderer when the column value is undefined. */ undefinedText: ' ', /** * @cfg {Object} renderer * @hide */ /** * @cfg {Object} scope * @hide */ defaultRenderer: function(value){ if (value === undefined) { return this.undefinedText; } if (!value || value === 'false') { return this.falseText; } return this.trueText; } }); /** * A Column subclass which renders a checkbox in each column cell which toggles the truthiness of the associated data field on click. * * Example usage: * * @example * var store = Ext.create('Ext.data.Store', { * fields : ['name', 'email', 'phone', 'active'], * data : { * items : [ * { name : 'Lisa', email : '[email protected]', phone : '555-111-1224', active : true }, * { name : 'Bart', email : '[email protected]', phone : '555-222-1234', active : true }, * { name : 'Homer', email : '[email protected]', phone : '555-222-1244', active : false }, * { name : 'Marge', email : '[email protected]', phone : '555-222-1254', active : true } * ] * }, * proxy : { * type : 'memory', * reader : { * type : 'json', * root : 'items' * } * } * }); * * Ext.create('Ext.grid.Panel', { * title : 'Simpsons', * height : 200, * width : 400, * renderTo : Ext.getBody(), * store : store, * columns : [ * { text : 'Name', dataIndex : 'name' }, * { text : 'Email', dataIndex : 'email', flex : 1 }, * { text : 'Phone', dataIndex : 'phone' }, * { xtype : 'checkcolumn', text : 'Active', dataIndex : 'active' } * ] * }); * * The check column can be at any index in the columns array. */ Ext.define('Ext.grid.column.Check', { extend: Ext.grid.column.Column , alternateClassName: ['Ext.ux.CheckColumn', 'Ext.grid.column.CheckColumn'], alias: 'widget.checkcolumn', /** * @cfg * @hide * Overridden from base class. Must center to line up with editor. */ align: 'center', /** * @cfg {Boolean} [stopSelection=true] * Prevent grid selection upon mousedown. */ stopSelection: true, tdCls: Ext.baseCSSPrefix + 'grid-cell-checkcolumn', innerCls: Ext.baseCSSPrefix + 'grid-cell-inner-checkcolumn', clickTargetName: 'el', constructor: function() { this.addEvents( /** * @event beforecheckchange * Fires when before checked state of a row changes. * The change may be vetoed by returning `false` from a listener. * @param {Ext.ux.CheckColumn} this CheckColumn * @param {Number} rowIndex The row index * @param {Boolean} checked True if the box is to be checked */ 'beforecheckchange', /** * @event checkchange * Fires when the checked state of a row changes * @param {Ext.ux.CheckColumn} this CheckColumn * @param {Number} rowIndex The row index * @param {Boolean} checked True if the box is now checked */ 'checkchange' ); this.scope = this; this.callParent(arguments); }, /** * @private * Process and refire events routed from the GridView's processEvent method. */ processEvent: function(type, view, cell, recordIndex, cellIndex, e, record, row) { var me = this, key = type === 'keydown' && e.getKey(), mousedown = type == 'mousedown'; if (!me.disabled && (mousedown || (key == e.ENTER || key == e.SPACE))) { var dataIndex = me.dataIndex, checked = !record.get(dataIndex); // Allow apps to hook beforecheckchange if (me.fireEvent('beforecheckchange', me, recordIndex, checked) !== false) { record.set(dataIndex, checked); me.fireEvent('checkchange', me, recordIndex, checked); // Mousedown on the now nonexistent cell causes the view to blur, so stop it continuing. if (mousedown) { e.stopEvent(); } // Selection will not proceed after this because of the DOM update caused by the record modification // Invoke the SelectionModel unless configured not to do so if (!me.stopSelection) { view.selModel.selectByPosition({ row: recordIndex, column: cellIndex }); } // Prevent the view from propagating the event to the selection model - we have done that job. return false; } else { // Prevent the view from propagating the event to the selection model if configured to do so. return !me.stopSelection; } } else { return me.callParent(arguments); } }, /** * Enables this CheckColumn. */ onEnable: function() { this.callParent(arguments); this._setDisabled(false); }, /** * Disables this CheckColumn. */ onDisable: function() { this._setDisabled(true); }, // Don't want to conflict with the Component method _setDisabled: function(disabled) { var me = this, cls = me.disabledCls, items; items = me.up('tablepanel').el.select(me.getCellSelector()); if (disabled) { items.addCls(cls); } else { items.removeCls(cls); } }, // Note: class names are not placed on the prototype bc renderer scope // is not in the header. renderer : function(value, meta) { var cssPrefix = Ext.baseCSSPrefix, cls = cssPrefix + 'grid-checkcolumn'; if (this.disabled) { meta.tdCls += ' ' + this.disabledCls; } if (value) { cls += ' ' + cssPrefix + 'grid-checkcolumn-checked'; } return ''; } }); /** * A Column definition class which renders a passed date according to the default locale, or a configured * {@link #format}. * * @example * Ext.create('Ext.data.Store', { * storeId:'sampleStore', * fields:[ * { name: 'symbol', type: 'string' }, * { name: 'date', type: 'date' }, * { name: 'change', type: 'number' }, * { name: 'volume', type: 'number' }, * { name: 'topday', type: 'date' } * ], * data:[ * { symbol: "msft", date: '2011/04/22', change: 2.43, volume: 61606325, topday: '04/01/2010' }, * { symbol: "goog", date: '2011/04/22', change: 0.81, volume: 3053782, topday: '04/11/2010' }, * { symbol: "apple", date: '2011/04/22', change: 1.35, volume: 24484858, topday: '04/28/2010' }, * { symbol: "sencha", date: '2011/04/22', change: 8.85, volume: 5556351, topday: '04/22/2010' } * ] * }); * * Ext.create('Ext.grid.Panel', { * title: 'Date Column Demo', * store: Ext.data.StoreManager.lookup('sampleStore'), * columns: [ * { text: 'Symbol', dataIndex: 'symbol', flex: 1 }, * { text: 'Date', dataIndex: 'date', xtype: 'datecolumn', format:'Y-m-d' }, * { text: 'Change', dataIndex: 'change', xtype: 'numbercolumn', format:'0.00' }, * { text: 'Volume', dataIndex: 'volume', xtype: 'numbercolumn', format:'0,000' }, * { text: 'Top Day', dataIndex: 'topday', xtype: 'datecolumn', format:'l' } * ], * height: 200, * width: 450, * renderTo: Ext.getBody() * }); */ Ext.define('Ext.grid.column.Date', { extend: Ext.grid.column.Column , alias: ['widget.datecolumn'], alternateClassName: 'Ext.grid.DateColumn', /** * @cfg {String} format * A formatting string as used by {@link Ext.Date#format} to format a Date for this Column. * * Defaults to the default date from {@link Ext.Date#defaultFormat} which itself my be overridden * in a locale file. */ /** * @cfg {Object} renderer * @hide */ /** * @cfg {Object} scope * @hide */ initComponent: function(){ if (!this.format) { this.format = Ext.Date.defaultFormat; } this.callParent(arguments); }, defaultRenderer: function(value){ return Ext.util.Format.date(value, this.format); } }); /** * A Column definition class which renders a numeric data field according to a {@link #format} string. * * @example * Ext.create('Ext.data.Store', { * storeId:'sampleStore', * fields:[ * { name: 'symbol', type: 'string' }, * { name: 'price', type: 'number' }, * { name: 'change', type: 'number' }, * { name: 'volume', type: 'number' } * ], * data:[ * { symbol: "msft", price: 25.76, change: 2.43, volume: 61606325 }, * { symbol: "goog", price: 525.73, change: 0.81, volume: 3053782 }, * { symbol: "apple", price: 342.41, change: 1.35, volume: 24484858 }, * { symbol: "sencha", price: 142.08, change: 8.85, volume: 5556351 } * ] * }); * * Ext.create('Ext.grid.Panel', { * title: 'Number Column Demo', * store: Ext.data.StoreManager.lookup('sampleStore'), * columns: [ * { text: 'Symbol', dataIndex: 'symbol', flex: 1 }, * { text: 'Current Price', dataIndex: 'price', renderer: Ext.util.Format.usMoney }, * { text: 'Change', dataIndex: 'change', xtype: 'numbercolumn', format:'0.00' }, * { text: 'Volume', dataIndex: 'volume', xtype: 'numbercolumn', format:'0,000' } * ], * height: 200, * width: 400, * renderTo: Ext.getBody() * }); */ Ext.define('Ext.grid.column.Number', { extend: Ext.grid.column.Column , alias: ['widget.numbercolumn'], alternateClassName: 'Ext.grid.NumberColumn', // /** * @cfg {String} format * A formatting string as used by {@link Ext.util.Format#number} to format a numeric value for this Column. */ format : '0,000.00', // /** * @cfg {Object} renderer * @hide */ /** * @cfg {Object} scope * @hide */ defaultRenderer: function(value){ return Ext.util.Format.number(value, this.format); } }); /** * A special type of Grid {@link Ext.grid.column.Column} that provides automatic * row numbering. * * Usage: * * columns: [ * {xtype: 'rownumberer'}, * {text: "Company", flex: 1, sortable: true, dataIndex: 'company'}, * {text: "Price", width: 120, sortable: true, renderer: Ext.util.Format.usMoney, dataIndex: 'price'}, * {text: "Change", width: 120, sortable: true, dataIndex: 'change'}, * {text: "% Change", width: 120, sortable: true, dataIndex: 'pctChange'}, * {text: "Last Updated", width: 120, sortable: true, renderer: Ext.util.Format.dateRenderer('m/d/Y'), dataIndex: 'lastChange'} * ] * */ Ext.define('Ext.grid.column.RowNumberer', { extend: Ext.grid.column.Column , alternateClassName: 'Ext.grid.RowNumberer', alias: 'widget.rownumberer', /** * @cfg {String} text * Any valid text or HTML fragment to display in the header cell for the row number column. */ text: " ", /** * @cfg {Number} width * The default width in pixels of the row number column. */ width: 23, /** * @cfg {Boolean} sortable * @hide */ sortable: false, /** * @cfg {Boolean} [draggable=false] * False to disable drag-drop reordering of this column. */ draggable: false, // Flag to Lockable to move instances of this column to the locked side. autoLock: true, // May not be moved from its preferred locked side when grid is enableLocking:true lockable: false, align: 'right', constructor : function(config){ var me = this; // Copy the prototype's default width setting into an instance property to provide // a default width which will not be overridden by AbstractContainer.applyDefaults use of Ext.applyIf me.width = me.width; me.callParent(arguments); me.scope = me; }, beforeRender: function() { var rowBody = this.up('gridpanel').view.findFeature('rowbody'); this.callParent(arguments); // If there is a RowBody Feature, and this coliumn is index 1 (immediately after the expander)... // the RowBody cell must not span this column, and this column must span into the expander row. if (rowBody && this.ownerCt.items.indexOf(this) === 1) { rowBody.colSpanDecrement = rowBody.colSpanDecrement + 1; this.rowspan = 2; } }, // private resizable: false, hideable: false, menuDisabled: true, dataIndex: '', cls: Ext.baseCSSPrefix + 'row-numberer', tdCls: Ext.baseCSSPrefix + 'grid-cell-row-numberer ' + Ext.baseCSSPrefix + 'grid-cell-special', innerCls: Ext.baseCSSPrefix + 'grid-cell-inner-row-numberer', rowspan: undefined, // private renderer: function(value, metaData, record, rowIdx, colIdx, dataSource, view) { var rowspan = this.rowspan, page = dataSource.currentPage, result = view.store.indexOf(record); if (rowspan) { metaData.tdAttr = 'rowspan="' + rowspan + '"'; } if (page > 1) { result += (page - 1) * dataSource.pageSize; } return result + 1; } }); /** * A Column definition class which renders a value by processing a {@link Ext.data.Model Model}'s * {@link Ext.data.Model#persistenceProperty data} using a {@link #tpl configured} * {@link Ext.XTemplate XTemplate}. * * @example * Ext.create('Ext.data.Store', { * storeId:'employeeStore', * fields:['firstname', 'lastname', 'seniority', 'department'], * groupField: 'department', * data:[ * { firstname: "Michael", lastname: "Scott", seniority: 7, department: "Management" }, * { firstname: "Dwight", lastname: "Schrute", seniority: 2, department: "Sales" }, * { firstname: "Jim", lastname: "Halpert", seniority: 3, department: "Sales" }, * { firstname: "Kevin", lastname: "Malone", seniority: 4, department: "Accounting" }, * { firstname: "Angela", lastname: "Martin", seniority: 5, department: "Accounting" } * ] * }); * * Ext.create('Ext.grid.Panel', { * title: 'Column Template Demo', * store: Ext.data.StoreManager.lookup('employeeStore'), * columns: [ * { text: 'Full Name', xtype: 'templatecolumn', tpl: '{firstname} {lastname}', flex:1 }, * { text: 'Department (Yrs)', xtype: 'templatecolumn', tpl: '{department} ({seniority})' } * ], * height: 200, * width: 300, * renderTo: Ext.getBody() * }); */ Ext.define('Ext.grid.column.Template', { extend: Ext.grid.column.Column , alias: ['widget.templatecolumn'], alternateClassName: 'Ext.grid.TemplateColumn', /** * @cfg {String/Ext.XTemplate} tpl * An {@link Ext.XTemplate XTemplate}, or an XTemplate *definition string* to use to process a * {@link Ext.data.Model Model}'s {@link Ext.data.Model#persistenceProperty data} to produce a * column's rendered value. */ /** * @cfg {Object} renderer * @hide */ /** * @cfg {Object} scope * @hide */ initComponent: function(){ var me = this; me.tpl = (!Ext.isPrimitive(me.tpl) && me.tpl.compile) ? me.tpl : new Ext.XTemplate(me.tpl); // Set this here since the template may access any record values, // so we must always run the update for this column me.hasCustomRenderer = true; me.callParent(arguments); }, defaultRenderer: function(value, meta, record) { var data = Ext.apply({}, record.data, record.getAssociatedData()); return this.tpl.apply(data); } }); /** * A feature is a type of plugin that is specific to the {@link Ext.grid.Panel}. It provides several * hooks that allows the developer to inject additional functionality at certain points throughout the * grid creation cycle. This class provides the base template methods that are available to the developer, * it should be extended. * * There are several built in features that extend this class, for example: * * - {@link Ext.grid.feature.Grouping} - Shows grid rows in groups as specified by the {@link Ext.data.Store} * - {@link Ext.grid.feature.RowBody} - Adds a body section for each grid row that can contain markup. * - {@link Ext.grid.feature.Summary} - Adds a summary row at the bottom of the grid with aggregate totals for a column. * * ## Using Features * A feature is added to the grid by specifying it an array of features in the configuration: * * var groupingFeature = Ext.create('Ext.grid.feature.Grouping'); * Ext.create('Ext.grid.Panel', { * // other options * features: [groupingFeature] * }); * * ## Writing Features * * A Feature may add new DOM structure within the structure of a grid. * * A grid is essentially a `
    ` element. A {@link Ext.view.Table TableView} instance uses three {@link Ext.XTemplate XTemplates} * to render the grid, `tableTpl`, `rowTpl`, `cellTpl`. * * * A {@link Ext.view.Table TableView} uses its `tableTpl` to emit the `
    ` and `` HTML tags into its output stream. It also emits a `` which contains a * sizing row. To ender the rows, it invokes {@link Ext.view.Table#renderRows} passing the `rows` member of its data object. * * The `tableTpl`'s data object Looks like this: * { * view: owningTableView, * rows: recordsToRender, * viewStartIndex: indexOfFirstRecordInStore, * tableStyle: styleString * } * * * A {@link Ext.view.Table TableView} uses its `rowTpl` to emit a `` HTML tag to its output stream. To render cells, * it invokes {@link Ext.view.Table#renderCell} passing the `rows` member of its data object. * * The `rowTpl`'s data object looks like this: * * { * view: owningTableView, * record: recordToRender, * recordIndex: indexOfRecordInStore, * columns: arrayOfColumnDefinitions, * itemClasses: arrayOfClassNames, // For outermost row in case of wrapping * rowClasses: arrayOfClassNames, // For internal data bearing row in case of wrapping * rowStyle: styleString * } * * * A {@link Ext.view.Table TableView} uses its `cellTpl` to emit a ` ', Ext.baseCSSPrefix, 'grid-group-row" {ariaRowAttr}>', '', '', '', '{%this.nextTpl.applyOut(values, out, parent);%}', '', { priority: 200, syncRowHeights: function(firstRow, secondRow) { firstRow = Ext.fly(firstRow, 'syncDest'); secondRow = Ext.fly(secondRow, 'sycSrc'); var owner = this.owner, firstHd = firstRow.down(owner.eventSelector, true), secondHd, firstSummaryRow = firstRow.down(owner.summaryRowSelector, true), secondSummaryRow, firstHeight, secondHeight; if (firstHd && (secondHd = secondRow.down(owner.eventSelector, true))) { firstHd.style.height = secondHd.style.height = ''; if ((firstHeight = firstHd.offsetHeight) > (secondHeight = secondHd.offsetHeight)) { Ext.fly(secondHd).setHeight(firstHeight); } else if (secondHeight > firstHeight) { Ext.fly(firstHd).setHeight(secondHeight); } } if (firstSummaryRow && (secondSummaryRow = secondRow.down(owner.summaryRowSelector, true))) { firstSummaryRow.style.height = secondSummaryRow.style.height = ''; if ((firstHeight = firstSummaryRow.offsetHeight) > (secondHeight = secondSummaryRow.offsetHeight)) { Ext.fly(secondSummaryRow).setHeight(firstHeight); } else if (secondHeight > firstHeight) { Ext.fly(firstSummaryRow).setHeight(secondHeight); } } }, syncContent: function(destRow, sourceRow) { destRow = Ext.fly(destRow, 'syncDest'); sourceRow = Ext.fly(sourceRow, 'sycSrc'); var owner = this.owner, destHd = destRow.down(owner.eventSelector, true), sourceHd = sourceRow.down(owner.eventSelector, true), destSummaryRow = destRow.down(owner.summaryRowSelector, true), sourceSummaryRow = sourceRow.down(owner.summaryRowSelector, true); if (destHd && sourceHd) { Ext.fly(destHd).syncContent(sourceHd); } if (destSummaryRow && sourceSummaryRow) { Ext.fly(destSummaryRow).syncContent(sourceSummaryRow); } } } ], constructor: function() { this.groupCache = {}; this.callParent(arguments); }, init: function(grid) { var me = this, view = me.view; if (view.store.groupField) { view.isGrouping = true; } if (me.lockingPartner && me.lockingPartner.groupCache) { me.groupCache = me.lockingPartner.groupCache; } me.mixins.summary.init.call(me); me.callParent(arguments); view.headerCt.on({ columnhide: me.onColumnHideShow, columnshow: me.onColumnHideShow, columnmove: me.onColumnMove, scope: me }); view.addTableTpl(me.tableTpl).groupingFeature = me; view.addRowTpl(Ext.XTemplate.getTpl(me, 'groupTpl')).groupingFeature = me; view.preserveScrollOnRefresh = true; if (view.store.buffered) { me.collapsible = false; } else { if (this.lockingPartner && this.lockingPartner.dataSource) { me.dataSource = view.dataSource = this.lockingPartner.dataSource; } else { me.dataSource = view.dataSource = new Ext.grid.feature.GroupStore(me, view.store); } } me.grid.on({ reconfigure: me.onReconfigure }); view.on({ afterrender: me.afterViewRender, scope: me, single: true }); }, indexOf: function(record) { var me = this, store = me.view.store, recordIdx = record.isModel ? store.indexOf(record) : Math.min(Math.max(record, 0), store.getCount() - 1), storeGroups, i, length, storeGroup, myGroup, groupStart, nextGroupStart = 0, skippedRecords = 0; storeGroups = store.getGroups(); for (i = 0, length = storeGroups.length; i < length; i++) { storeGroup = storeGroups[i]; myGroup = me.getGroup(storeGroup.name); groupStart = nextGroupStart; nextGroupStart = groupStart + storeGroup.children.length; if (recordIdx < nextGroupStart) { return recordIdx - skippedRecords; } if (myGroup.isCollapsed) { skippedRecords += storeGroup.children.length; skippedRecords -= 1; } } }, isInCollapsedGroup: function(record) { var groupData, store = this.view.store; if (store.isGrouped() && (groupData = this.getGroup(record))) { return groupData.isCollapsed || false; } return false; }, clearGroupCache: function() { var me = this, groupCache = me.groupCache = {}; if (me.lockingPartner) { me.lockingPartner.groupCache = groupCache; } return groupCache; }, vetoEvent: function(record, row, rowIndex, e) { if (e.type !== 'mouseover' && e.type !== 'mouseout' && e.type !== 'mouseenter' && e.type !== 'mouseleave' && e.getTarget(this.eventSelector)) { return false; } }, enable: function() { var me = this, view = me.view, store = view.store, groupToggleMenuItem; view.isGrouping = true; if (me.lastGroupers) { me.block(); store.group(me.lastGroupers); me.lastGroupers = null; me.unblock(); } me.callParent(); groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem'); if (groupToggleMenuItem) { groupToggleMenuItem.setChecked(true, true); } me.refreshIf(); }, disable: function() { var me = this, view = me.view, store = view.store, groupToggleMenuItem, lastGroupers = store.groupers.getRange(); view.isGrouping = false; if (lastGroupers.length) { me.lastGroupers = lastGroupers; me.block(); store.clearGrouping(); me.unblock(); } me.callParent(); groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem'); if (groupToggleMenuItem) { groupToggleMenuItem.setChecked(false, true); } me.refreshIf(); }, refreshIf: function() { var ownerCt = this.grid.ownerCt, view = this.view; if (!view.store.remoteGroup && !this.blockRefresh) { if (ownerCt && ownerCt.lockable) { ownerCt.view.refresh(); } else { view.refresh(); } } }, afterViewRender: function() { var me = this, view = me.view; view.on({ scope: me, groupclick: me.onGroupClick }); if (me.enableGroupingMenu) { me.injectGroupingMenu(); } me.pruneGroupedHeader(); me.lastGroupers = me.view.store.groupers.getRange(); me.block(); me.onGroupChange(); me.unblock(); if (me.disabled) { me.disable(); } }, injectGroupingMenu: function() { var me = this, headerCt = me.view.headerCt; headerCt.showMenuBy = me.showMenuBy; headerCt.getMenuItems = me.getMenuItems(); }, onColumnHideShow: function(headerOwnerCt, header) { var view = this.view, headerCt = view.headerCt, menu = headerCt.getMenu(), groupToggleMenuItem = menu.down('#groupMenuItem'), colCount = this.grid.getVisibleColumnManager().getColumns().length, items, len, i; if (groupToggleMenuItem) { if (headerCt.getVisibleGridColumns().length > 1) { groupToggleMenuItem.enable(); } else { groupToggleMenuItem.disable(); } } if (view.rendered) { items = view.el.query('.' + this.ctCls); for (i = 0, len = items.length; i < len; ++i) { items[i].colSpan = colCount; } } }, onColumnMove: function() { var me = this, store = me.view.store, groups, groupName, group, firstRec, lastRec; if (store.isGrouped()) { groups = me.groupCache; for (groupName in groups) { if (groups.hasOwnProperty(groupName)) { group = groups[groupName]; firstRec = group.children[0]; lastRec = group.children[group.children.length - 1]; store.fireEvent('update', store, firstRec, 'edit', null); if (lastRec !== firstRec && me.showSummaryRow) { store.fireEvent('update', store, lastRec, 'edit', null); } } } } }, showMenuBy: function(t, header) { var menu = this.getMenu(), groupMenuItem = menu.down('#groupMenuItem'), groupMenuMeth = header.groupable === false || header.dataIndex == null || this.view.headerCt.getVisibleGridColumns().length < 2 ? 'disable' : 'enable', groupToggleMenuItem = menu.down('#groupToggleMenuItem'), isGrouped = this.view.store.isGrouped(); groupMenuItem[groupMenuMeth](); if (groupToggleMenuItem) { groupToggleMenuItem.setChecked(isGrouped, true); groupToggleMenuItem[isGrouped ? 'enable' : 'disable'](); } Ext.grid.header.Container.prototype.showMenuBy.apply(this, arguments); }, getMenuItems: function() { var me = this, groupByText = me.groupByText, disabled = me.disabled || !me.getGroupField(), showGroupsText = me.showGroupsText, enableNoGroups = me.enableNoGroups, getMenuItems = me.view.headerCt.getMenuItems; return function() { var o = getMenuItems.call(this); o.push('-', { iconCls: Ext.baseCSSPrefix + 'group-by-icon', itemId: 'groupMenuItem', text: groupByText, handler: me.onGroupMenuItemClick, scope: me }); if (enableNoGroups) { o.push({ itemId: 'groupToggleMenuItem', text: showGroupsText, checked: !disabled, checkHandler: me.onGroupToggleMenuItemClick, scope: me }); } return o; }; }, onGroupMenuItemClick: function(menuItem, e) { var me = this, menu = menuItem.parentMenu, hdr = menu.activeHeader, view = me.view, store = view.store; me.lastGroupers = null; me.block(); me.enable(); store.group(hdr.dataIndex); me.pruneGroupedHeader(); me.unblock(); me.refreshIf(); }, block: function(fromPartner) { this.blockRefresh = this.view.blockRefresh = true; if (this.lockingPartner && !fromPartner) { this.lockingPartner.block(true); } }, unblock: function(fromPartner) { this.blockRefresh = this.view.blockRefresh = false; if (this.lockingPartner && !fromPartner) { this.lockingPartner.unblock(true); } }, onGroupToggleMenuItemClick: function(menuItem, checked) { this[checked ? 'enable' : 'disable'](); }, pruneGroupedHeader: function() { var me = this, header = me.getGroupedHeader(); if (me.hideGroupedHeader && header) { Ext.suspendLayouts(); if (me.prunedHeader && me.prunedHeader !== header) { me.prunedHeader.show(); } me.prunedHeader = header; header.hide(); Ext.resumeLayouts(true); } }, getHeaderNode: function(groupName) { return Ext.get(this.createGroupId(groupName)); }, getGroup: function(name) { if (name.isModel) { name = name.get(this.view.store.getGroupField()); } var cache = this.groupCache, item = cache[name]; if (!item) { item = cache[name] = { isCollapsed: false }; } return item; }, isExpanded: function(groupName) { return !this.getGroup(groupName).isCollapsed; }, expand: function(groupName, focus) { this.doCollapseExpand(false, groupName, focus); }, expandAll: function() { var me = this, groupCache = me.groupCache, groupName, lockingPartner = me.lockingPartner; for (groupName in groupCache) { if (groupCache.hasOwnProperty(groupName)) { groupCache[groupName].isCollapsed = false; } } Ext.suspendLayouts(); me.dataSource.onRefresh(); Ext.resumeLayouts(true); for (groupName in groupCache) { if (groupCache.hasOwnProperty(groupName)) { me.afterCollapseExpand(false, groupName); if (lockingPartner) { lockingPartner.afterCollapseExpand(false, groupName); } } } }, collapse: function(groupName, focus) { this.doCollapseExpand(true, groupName, focus); }, isAllCollapsed: function() { var me = this, groupCache = me.groupCache, groupName; for (groupName in groupCache) { if (groupCache.hasOwnProperty(groupName)) { if (!groupCache[groupName].isCollapsed) { return false; } } } return true; }, isAllExpanded: function() { var me = this, groupCache = me.groupCache, groupName; for (groupName in groupCache) { if (groupCache.hasOwnProperty(groupName)) { if (groupCache[groupName].isCollapsed) { return false; } } } return true; }, collapseAll: function() { var me = this, groupCache = me.groupCache, groupName, lockingPartner = me.lockingPartner; for (groupName in groupCache) { if (groupCache.hasOwnProperty(groupName)) { groupCache[groupName].isCollapsed = true; } } Ext.suspendLayouts(); me.dataSource.onRefresh(); if (lockingPartner && !lockingPartner.isAllCollapsed()) { lockingPartner.collapseAll(); } Ext.resumeLayouts(true); for (groupName in groupCache) { if (groupCache.hasOwnProperty(groupName)) { me.afterCollapseExpand(true, groupName); if (lockingPartner) { lockingPartner.afterCollapseExpand(true, groupName); } } } }, doCollapseExpand: function(collapsed, groupName, focus) { var me = this, lockingPartner = me.lockingPartner, group = me.groupCache[groupName]; if (group.isCollapsed != collapsed) { Ext.suspendLayouts(); if (collapsed) { me.dataSource.collapseGroup(group); } else { me.dataSource.expandGroup(group); } Ext.resumeLayouts(true); me.afterCollapseExpand(collapsed, groupName, focus); if (lockingPartner) { lockingPartner.afterCollapseExpand(collapsed, groupName, false); } } }, afterCollapseExpand: function(collapsed, groupName, focus) { var me = this, view = me.view, header; header = Ext.get(this.getHeaderNode(groupName)); view.fireEvent(collapsed ? 'groupcollapse' : 'groupexpand', view, header, groupName); if (focus) { header.up(view.getItemSelector()).scrollIntoView(view.el, null, true); } }, onGroupChange: function() { var me = this, field = me.getGroupField(), menuItem, visibleGridColumns, groupingByLastVisibleColumn; if (me.hideGroupedHeader) { if (me.lastGroupers && me.lastGroupers.length) { menuItem = me.getMenuItem(me.lastGroupers[0].property); if (menuItem) { menuItem.setChecked(true); } } if (field) { visibleGridColumns = me.view.headerCt.getVisibleGridColumns(); groupingByLastVisibleColumn = ((visibleGridColumns.length === 1) && (visibleGridColumns[0].dataIndex == field)); menuItem = me.getMenuItem(field); if (menuItem && !groupingByLastVisibleColumn) { menuItem.setChecked(false); } } } me.refreshIf(); me.lastGroupers = me.view.store.groupers.getRange(); }, getMenuItem: function(dataIndex){ var view = this.view, header = view.headerCt.down('gridcolumn[dataIndex=' + dataIndex + ']'), menu = view.headerCt.getMenu(); return header ? menu.down('menuitem[headerId='+ header.id +']') : null; }, onGroupKey: function(keyCode, event) { var me = this, groupName = me.getGroupName(event.target); if (groupName) { me.onGroupClick(me.view, event.target, groupName, event); } }, onGroupClick: function(view, rowElement, groupName, e) { var me = this, groupCache = me.groupCache, groupIsCollapsed = !me.isExpanded(groupName), g; if (me.collapsible) { if (e.ctrlKey) { Ext.suspendLayouts(); for (g in groupCache) { if (g === groupName) { if (groupIsCollapsed) { me.expand(groupName); } } else { me.doCollapseExpand(true, g, false); } } Ext.resumeLayouts(true); return; } if (groupIsCollapsed) { me.expand(groupName); } else { me.collapse(groupName); } } }, setupRowData: function(record, idx, rowValues) { var me = this, data = me.refreshData, groupInfo = me.groupInfo, header = data.header, groupField = data.groupField, dataSource = me.view.dataSource, grouper, groupName, prev, next; rowValues.isCollapsedGroup = false; rowValues.summaryRecord = null; if (data.doGrouping) { grouper = me.view.store.groupers.first(); if (record.children) { groupName = grouper.getGroupString(record.children[0]); rowValues.isFirstRow = rowValues.isLastRow = true; rowValues.itemClasses.push(me.hdCollapsedCls); rowValues.isCollapsedGroup = rowValues.needsWrap = true; rowValues.groupInfo = groupInfo; groupInfo.groupField = groupField; groupInfo.name = groupName; groupInfo.groupValue = record.children[0].get(groupField); groupInfo.columnName = header ? header.text : groupField; rowValues.collapsibleCls = me.collapsible ? me.collapsibleCls : me.hdNotCollapsibleCls; rowValues.groupId = me.createGroupId(groupName); groupInfo.rows = groupInfo.children = record.children; if (me.showSummaryRow) { rowValues.summaryRecord = data.summaryData[groupName]; } return; } groupName = grouper.getGroupString(record); if (record.group) { rowValues.isFirstRow = record === record.group.children[0]; rowValues.isLastRow = record === record.group.children[record.group.children.length - 1]; } else { rowValues.isFirstRow = idx === 0; if (!rowValues.isFirstRow) { prev = dataSource.getAt(idx - 1); if (prev) { rowValues.isFirstRow = !prev.isEqual(grouper.getGroupString(prev), groupName); } } rowValues.isLastRow = idx == dataSource.getTotalCount() - 1; if (!rowValues.isLastRow) { next = dataSource.getAt(idx + 1); if (next) { rowValues.isLastRow = !next.isEqual(grouper.getGroupString(next), groupName); } } } if (rowValues.isFirstRow) { groupInfo.groupField = groupField; groupInfo.name = groupName; groupInfo.groupValue = record.get(groupField); groupInfo.columnName = header ? header.text : groupField; rowValues.collapsibleCls = me.collapsible ? me.collapsibleCls : me.hdNotCollapsibleCls; rowValues.groupId = me.createGroupId(groupName); if (!me.isExpanded(groupName)) { rowValues.itemClasses.push(me.hdCollapsedCls); rowValues.isCollapsedGroup = true; } if (dataSource.buffered) { groupInfo.rows = groupInfo.children = []; } else { groupInfo.rows = groupInfo.children = me.getRecordGroup(record).children; } rowValues.groupInfo = groupInfo; } if (rowValues.isLastRow) { if (me.showSummaryRow) { rowValues.summaryRecord = data.summaryData[groupName]; } } rowValues.needsWrap = (rowValues.isFirstRow || rowValues.summaryRecord); } }, setup: function(rows, rowValues) { var me = this, data = me.refreshData, isGrouping = !me.disabled && me.view.store.isGrouped(); me.skippedRows = 0; if (rowValues.view.bufferedRenderer) { rowValues.view.bufferedRenderer.variableRowHeight = true; } data.groupField = me.getGroupField(); data.header = me.getGroupedHeader(data.groupField); data.doGrouping = isGrouping; rowValues.groupHeaderTpl = Ext.XTemplate.getTpl(me, 'groupHeaderTpl'); if (isGrouping && me.showSummaryRow) { data.summaryData = me.generateSummaryData(); } }, cleanup: function(rows, rowValues) { var data = this.refreshData; rowValues.groupInfo = rowValues.groupHeaderTpl = rowValues.isFirstRow = null; data.groupField = data.header = null; }, getGroupName: function(element) { var me = this, view = me.view, eventSelector = me.eventSelector, parts, targetEl, row; targetEl = Ext.fly(element).findParent(eventSelector); if (!targetEl) { row = Ext.fly(element).findParent(view.itemSelector); if (row) { targetEl = row.down(eventSelector, true); } } if (targetEl) { parts = targetEl.id.split(view.id + '-hd-'); if (parts.length === 2) { return Ext.htmlDecode(parts[1]); } } }, getRecordGroup: function(record) { var grouper = this.view.store.groupers.first(); if (grouper) { return this.groupCache[grouper.getGroupString(record)]; } }, createGroupId: function(group) { return this.view.id + '-hd-' + Ext.htmlEncode(group); }, createGroupCls: function(group) { return this.view.id + '-' + Ext.htmlEncode(group) + '-item'; }, getGroupField: function(){ return this.view.store.getGroupField(); }, getGroupedHeader: function(groupField) { var me = this, headerCt = me.view.headerCt, partner = me.lockingPartner, selector, header; groupField = groupField || this.getGroupField(); if (groupField) { selector = '[dataIndex=' + groupField + ']'; header = headerCt.down(selector); if (!header && partner) { header = partner.view.headerCt.down(selector); } } return header || null; }, getFireEventArgs: function(type, view, targetEl, e) { return [type, view, targetEl, this.getGroupName(targetEl), e]; }, destroy: function(){ var me = this, dataSource = me.dataSource; me.view = me.prunedHeader = me.grid = me.groupCache = me.dataSource = null; me.callParent(); if (dataSource) { dataSource.bindStore(null); } }, onReconfigure: function(grid, store, columns, oldStore, oldColumns) { var me = grid; if (store && store !== oldStore) { if (store.buffered !== oldStore.buffered) { Ext.Error.raise('Cannot reconfigure grouping switching between buffered and non-buffered stores'); } if (store.buffered) { me.bindStore(store); me.dataSource.processStore(store); } } } }); Ext.define('Ext.grid.feature.GroupingSummary', { extend: Ext.grid.feature.Grouping , alias: 'feature.groupingsummary', showSummaryRow: true, vetoEvent: function(record, row, rowIndex, e){ var result = this.callParent(arguments); if (result !== false) { if (e.getTarget(this.summaryRowSelector)) { result = false; } } return result; } }); Ext.define('Ext.grid.feature.RowBody', { extend: Ext.grid.feature.Feature , alias: 'feature.rowbody', rowBodyCls: Ext.baseCSSPrefix + 'grid-row-body', rowBodyHiddenCls: Ext.baseCSSPrefix + 'grid-row-body-hidden', rowBodyTdSelector: 'td.' + Ext.baseCSSPrefix + 'grid-cell-rowbody', eventPrefix: 'rowbody', eventSelector: 'tr.' + Ext.baseCSSPrefix + 'grid-rowbody-tr', colSpanDecrement: 0, tableTpl: { before: function(values, out) { var view = values.view, rowValues = view.rowValues; this.rowBody.setup(values.rows, rowValues); }, after: function(values, out) { var view = values.view, rowValues = view.rowValues; this.rowBody.cleanup(values.rows, rowValues); }, priority: 100 }, extraRowTpl: [ '{%', 'values.view.rowBodyFeature.setupRowData(values.record, values.recordIndex, values);', 'this.nextTpl.applyOut(values, out, parent);', '%}', '', '', '', { priority: 100, syncRowHeights: function(firstRow, secondRow) { var owner = this.owner, firstRowBody = Ext.fly(firstRow).down(owner.eventSelector, true), secondRowBody, firstHeight, secondHeight; if (firstRowBody && (secondRowBody = Ext.fly(secondRow).down(owner.eventSelector, true))) { if ((firstHeight = firstRowBody.offsetHeight) > (secondHeight = secondRowBody.offsetHeight)) { Ext.fly(secondRowBody).setHeight(firstHeight); } else if (secondHeight > firstHeight) { Ext.fly(firstRowBody).setHeight(secondHeight); } } }, syncContent: function(destRow, sourceRow) { var owner = this.owner, destRowBody = Ext.fly(destRow).down(owner.eventSelector, true), sourceRowBody; if (destRowBody && (sourceRowBody = Ext.fly(sourceRow).down(owner.eventSelector, true))) { Ext.fly(destRowBody).syncContent(sourceRowBody); } } } ], init: function(grid) { var me = this, view = me.view; view.rowBodyFeature = me; if (!view.findFeature('rowwrap')) { grid.mon(view, { element: 'el', mousedown: me.onMouseDown, scope: me }); me.mon(grid.getStore(), 'remove', me.onStoreRemove, me); } view.headerCt.on({ columnschanged: me.onColumnsChanged, scope: me }); view.addTableTpl(me.tableTpl).rowBody = me; view.addRowTpl(Ext.XTemplate.getTpl(this, 'extraRowTpl')); me.callParent(arguments); }, onStoreRemove: function(store, model, index){ var view = this.view, node; if (view.rendered) { node = view.getNode(index); if (node) { node = Ext.fly(node).next(this.eventSelector); if (node) { node.remove(); } } } }, onMouseDown: function(e) { var me = this, tableRow = e.getTarget(me.eventSelector); if (tableRow && Ext.fly(tableRow = tableRow.previousSibling).is(me.view.getItemSelector())) { e.target = tableRow; me.view.handleEvent(e); } }, getSelectedRow: function(view, rowIndex) { var selectedRow = view.getNode(rowIndex, false); if (selectedRow) { return Ext.fly(selectedRow).down(this.eventSelector); } return null; }, onColumnsChanged: function(headerCt) { var items = this.view.el.query(this.rowBodyTdSelector), colspan = headerCt.getVisibleGridColumns().length, len = items.length, i; for (i = 0; i < len; ++i) { items[i].colSpan = colspan; } }, setupRowData: function(record, rowIndex, rowValues) { if (this.getAdditionalData) { Ext.apply(rowValues, this.getAdditionalData(record.data, rowIndex, record, rowValues)); } }, setup: function(rows, rowValues) { rowValues.rowBodyCls = this.rowBodyCls; rowValues.rowBodyColspan = rowValues.view.getGridColumns().length - this.colSpanDecrement; }, cleanup: function(rows, rowValues) { rowValues.rowBodyCls = rowValues.rowBodyColspan = rowValues.rowBody = null; } }); Ext.define('Ext.grid.feature.RowWrap', { extend: Ext.grid.feature.Feature , alias: 'feature.rowwrap', rowWrapTd: 'td.' + Ext.baseCSSPrefix + 'grid-rowwrap', hasFeatureEvent: false, tableTpl: { before: function(values, out) { if (values.view.bufferedRenderer) { values.view.bufferedRenderer.variableRowHeight = true; } }, priority: 200 }, wrapTpl: [ '', '', '', { priority: 200 } ], init: function(grid) { var me = this; me.view.addTableTpl(me.tableTpl); me.view.addRowTpl(Ext.XTemplate.getTpl(me, 'wrapTpl')); me.view.headerCt.on({ columnhide: me.onColumnHideShow, columnshow: me.onColumnHideShow, scope: me }); }, onColumnHideShow: function() { var view = this.view, items = view.el.query(this.rowWrapTd), colspan = view.headerCt.getVisibleGridColumns().length, len = items.length, i; for (i = 0; i < len; ++i) { items[i].colSpan = colspan; } } }); Ext.define('Ext.grid.feature.Summary', { extend: Ext.grid.feature.AbstractSummary , alias: 'feature.summary', dock: undefined, dockedSummaryCls: Ext.baseCSSPrefix + 'docked-summary', panelBodyCls: Ext.baseCSSPrefix + 'summary-', scrollPadProperty: 'padding-right', init: function(grid) { var me = this, view = me.view; me.callParent(arguments); if (me.dock) { grid.headerCt.on({ afterlayout: me.onStoreUpdate, scope: me }); grid.on({ beforerender: function() { var tableCls = [me.summaryTableCls]; if (view.columnLines) { tableCls[tableCls.length] = view.ownerCt.colLinesCls; } me.summaryBar = grid.addDocked({ childEls: ['innerCt'], renderTpl: [ '
    ` HTML tag to its output stream. * * The `cellTpl's` data object looks like this: * * { * record: recordToRender * column: columnToRender; * recordIndex: indexOfRecordInStore, * columnIndex: columnIndex, * align: columnAlign, * tdCls: classForCell * } * * A Feature may inject its own tableTpl or rowTpl or cellTpl into the {@link Ext.view.Table TableView}'s rendering by * calling {@link Ext.view.Table#addTableTpl} or {@link Ext.view.Table#addRowTpl} or {@link Ext.view.Table#addCellTpl}. * * The passed XTemplate is added *upstream* of the default template for the table element in a link list of XTemplates which contribute * to the element's HTML. It may emit appropriate HTML strings into the output stream *around* a call to * * this.nextTpl.apply(values, out, parent); * * This passes the current value context, output stream and the parent value context to the next XTemplate in the list. * * @abstract */ Ext.define('Ext.grid.feature.Feature', { extend: Ext.util.Observable , alias: 'feature.feature', wrapsItem: false, /* * @property {Boolean} isFeature * `true` in this class to identify an object as an instantiated Feature, or subclass thereof. */ isFeature: true, /** * True when feature is disabled. */ disabled: false, /** * @property {Boolean} * Most features will expose additional events, some may not and will * need to change this to false. */ hasFeatureEvent: true, /** * @property {String} * Prefix to use when firing events on the view. * For example a prefix of group would expose "groupclick", "groupcontextmenu", "groupdblclick". */ eventPrefix: null, /** * @property {String} * Selector used to determine when to fire the event with the eventPrefix. */ eventSelector: null, /** * @property {Ext.view.Table} * Reference to the TableView. */ view: null, /** * @property {Ext.grid.Panel} * Reference to the grid panel */ grid: null, constructor: function(config) { this.initialConfig = config; this.callParent(arguments); }, clone: function() { return new this.self(this.initialConfig); }, init: Ext.emptyFn, destroy: function(){ this.clearListeners(); }, /** * Abstract method to be overriden when a feature should add additional * arguments to its event signature. By default the event will fire: * * - view - The underlying Ext.view.Table * - featureTarget - The matched element by the defined {@link #eventSelector} * * The method must also return the eventName as the first index of the array * to be passed to fireEvent. * @template */ getFireEventArgs: function(eventName, view, featureTarget, e) { return [eventName, view, featureTarget, e]; }, vetoEvent: Ext.emptyFn, /** * Enables the feature. */ enable: function() { this.disabled = false; }, /** * Disables the feature. */ disable: function() { this.disabled = true; } }); /** * A small abstract class that contains the shared behaviour for any summary * calculations to be used in the grid. */ Ext.define('Ext.grid.feature.AbstractSummary', { extend: Ext.grid.feature.Feature , alias: 'feature.abstractsummary', summaryRowCls: Ext.baseCSSPrefix + 'grid-row-summary', summaryTableCls: Ext.plainTableCls + ' ' + Ext.baseCSSPrefix + 'grid-table', summaryRowSelector: '.' + Ext.baseCSSPrefix + 'grid-row-summary', // High priority rowTpl interceptor which sees summary rows early, and renders them correctly and then aborts the row rendering chain. // This will only see action when summary rows are being updated and Table.onUpdate->Table.bufferRender renders the individual updated sumary row. summaryRowTpl: { before: function(values, out) { // If a summary record comes through the rendering pipeline, render it simply, and return false from the // before method which aborts the tpl chain if (values.record.isSummary && this.summaryFeature.showSummaryRow) { this.summaryFeature.outputSummaryRecord(values.record, values, out); return false; } }, priority: 1000 }, /** * @cfg {Boolean} * True to show the summary row. */ showSummaryRow: true, // Listen for store updates. Eg, from an Editor. init: function() { var me = this; me.view.summaryFeature = me; me.rowTpl = me.view.self.prototype.rowTpl; // Add a high priority interceptor which renders summary records simply // This will only see action ona bufferedRender situation where summary records are updated. me.view.addRowTpl(me.summaryRowTpl).summaryFeature = me; }, /** * Toggle whether or not to show the summary row. * @param {Boolean} visible True to show the summary row */ toggleSummaryRow: function(visible) { this.showSummaryRow = !!visible; }, outputSummaryRecord: function(summaryRecord, contextValues, out) { var view = contextValues.view, savedRowValues = view.rowValues, columns = contextValues.columns || view.headerCt.getVisibleGridColumns(), colCount = columns.length, i, column, // Set up a row rendering values object so that we can call the rowTpl directly to inject // the markup of a grid row into the output stream. values = { view: view, record: summaryRecord, rowStyle: '', rowClasses: [ this.summaryRowCls ], itemClasses: [], recordIndex: -1, rowId: view.getRowId(summaryRecord), columns: columns }; // Because we are using the regular row rendering pathway, temporarily swap out the renderer for the summaryRenderer for (i = 0; i < colCount; i++) { column = columns[i]; column.savedRenderer = column.renderer; if (column.summaryRenderer) { column.renderer = column.summaryRenderer; } else if (!column.summaryType) { column.renderer = Ext.emptyFn; } // Summary records may contain values based upon the column's ID if the column is not mapped from a field if (!column.dataIndex) { column.dataIndex = column.id; } } // Use the base template to render a summary row view.rowValues = values; view.self.prototype.rowTpl.applyOut(values, out); view.rowValues = savedRowValues; // Restore regular column renderers for (i = 0; i < colCount; i++) { column = columns[i]; column.renderer = column.savedRenderer; column.savedRenderer = null; } }, /** * Get the summary data for a field. * @private * @param {Ext.data.Store} store The store to get the data from * @param {String/Function} type The type of aggregation. If a function is specified it will * be passed to the stores aggregate function. * @param {String} field The field to aggregate on * @param {Boolean} group True to aggregate in grouped mode * @return {Number/String/Object} See the return type for the store functions. * if the group parameter is `true` An object is returned with a property named for each group who's * value is the summary value. */ getSummary: function(store, type, field, group){ var records = group.records; if (type) { if (Ext.isFunction(type)) { return store.getAggregate(type, null, records, [field]); } switch (type) { case 'count': return records.length; case 'min': return store.getMin(records, field); case 'max': return store.getMax(records, field); case 'sum': return store.getSum(records, field); case 'average': return store.getAverage(records, field); default: return ''; } } }, /** * Used by the Grouping Feature when {@link #showSummaryRow} is `true`. * * Generates group summary data for the whole store. * @private * @return {Object} An object hash keyed by group name containing summary records. */ generateSummaryData: function(){ var me = this, store = me.view.store, groups = store.groups.items, reader = store.proxy.reader, len = groups.length, groupField = me.getGroupField(), data = {}, lockingPartner = me.lockingPartner, i, group, record, root, summaryRows, hasRemote, convertedSummaryRow, remoteData; /** * @cfg {String} [remoteRoot=undefined] * The name of the property which contains the Array of summary objects. * It allows to use server-side calculated summaries. */ if (me.remoteRoot && reader.rawData) { hasRemote = true; remoteData = {}; // reset reader root and rebuild extractors to extract summaries data root = reader.root; reader.root = me.remoteRoot; reader.buildExtractors(true); summaryRows = reader.getRoot(reader.rawData)||[]; len = summaryRows.length; // Ensure the Reader has a data conversion function to convert a raw data row into a Record data hash if (!reader.convertRecordData) { reader.buildExtractors(); } for (i = 0; i < len; ++i) { convertedSummaryRow = {}; // Convert a raw data row into a Record's hash object using the Reader reader.convertRecordData(convertedSummaryRow, summaryRows[i]); remoteData[convertedSummaryRow[groupField]] = convertedSummaryRow; } // restore initial reader configuration reader.root = root; reader.buildExtractors(true); } for (i = 0; i < len; ++i) { group = groups[i]; // Something has changed or it doesn't exist, populate it if (hasRemote || group.isDirty() || !group.hasAggregate()) { if (hasRemote) { record = me.populateRemoteRecord(group, remoteData); } else { record = me.populateRecord(group); } // Clear the dirty state of the group if this is the only Summary, or this is the right hand (normal grid's) summary if (!lockingPartner || (me.view.ownerCt === me.view.ownerCt.ownerLockable.normalGrid)) { group.commit(); } } else { record = group.getAggregateRecord(); } data[group.key] = record; } return data; }, populateRemoteRecord: function(group, data) { var record = group.getAggregateRecord(true), groupData = data[group.key], field; record.beginEdit(); for (field in groupData) { if (groupData.hasOwnProperty(field)) { if (field !== record.idProperty) { record.set(field, groupData[field]); } } } record.endEdit(true); record.commit(true); return record; }, populateRecord: function(group){ var me = this, view = me.grid.ownerLockable ? me.grid.ownerLockable.view : me.view, store = me.view.store, record = group.getAggregateRecord(), // Use the full column set, regardless of locking columns = view.headerCt.getGridColumns(), len = columns.length, i, column, fieldName; record.beginEdit(); for (i = 0; i < len; ++i) { column = columns[i]; // Use the column id if there's no mapping, could be a calculated field fieldName = column.dataIndex || column.id; record.set(fieldName, me.getSummary(store, column.summaryType, fieldName, group)); } record.endEdit(true); record.commit(); return record; } }); /** * Private record store class which takes the place of the view's data store to provide a grouped * view of the data when the Grouping feature is used. * * Relays granular mutation events from the underlying store as refresh events to the view. * * On mutation events from the underlying store, updates the summary rows by firing update events on the corresponding * summary records. * @private */ Ext.define('Ext.grid.feature.GroupStore', { extend: Ext.util.Observable , isStore: true, // Number of records to load into a buffered grid before it has been bound to a view of known size defaultViewSize: 100, // Use this property moving forward for all feature stores. It will be used to ensure // that the correct object is used to call various APIs. See EXTJSIV-10022. isFeatureStore: true, constructor: function(groupingFeature, store) { var me = this; me.callParent(); me.groupingFeature = groupingFeature; me.bindStore(store); }, bindStore: function(store) { var me = this; if (me.store) { Ext.destroy(me.storeListeners); me.store = null; } if (store) { me.storeListeners = store.on({ bulkremove: me.onBulkRemove, add: me.onAdd, update: me.onUpdate, refresh: me.onRefresh, clear: me.onClear, scope: me, destroyable: true }); me.store = store; me.processStore(store); } }, processStore: function(store) { var me = this, groups = store.getGroups(), groupCount = groups.length, i, group, groupPlaceholder, data = me.data, oldGroupCache = me.groupingFeature.groupCache, groupCache = me.groupingFeature.clearGroupCache(), collapseAll = me.groupingFeature.startCollapsed; if (data) { data.clear(); } else { data = me.data = new Ext.util.MixedCollection(false, Ext.data.Store.recordIdFn); } if (store.getCount()) { // Upon first process of a loaded store, clear the "always" collapse" flag me.groupingFeature.startCollapsed = false; for (i = 0; i < groupCount; i++) { group = groups[i]; groupCache[group.name] = group; group.isCollapsed = collapseAll || (oldGroupCache[group.name] && oldGroupCache[group.name].isCollapsed); if (group.isCollapsed) { group.placeholder = groupPlaceholder = new store.model(null, 'group-' + group.name + '-placeholder'); groupPlaceholder.set(store.getGroupField(), group.name); groupPlaceholder.rows = groupPlaceholder.children = group.children; groupPlaceholder.isCollapsedPlaceholder = true; data.add(groupPlaceholder); } else { data.insert(me.data.length, group.children); } } } }, isCollapsed: function(name) { return this.groupingFeature.groupCache[name].isCollapsed; }, isInCollapsedGroup: function(record) { var store = this.store, groupData; if (store.isGrouped() && (groupData = this.groupingFeature.groupCache[record.get(store.getGroupField())])) { return groupData.isCollapsed || false; } return false; }, getCount: function() { return this.data.getCount(); }, getTotalCount: function() { return this.data.getCount(); }, rangeCached: function(start, end) { return end < this.getCount(); }, getRange: function(start, end, options) { var result = this.data.getRange(start, end); if (options && options.callback) { options.callback.call(options.scope || this, result, start, end, options); } return result; }, getAt: function(index) { return this.getRange(index, index)[0]; }, getById: function(id) { return this.store.getById(id); }, expandGroup: function(group) { var me = this, startIdx; if (typeof group === 'string') { group = me.groupingFeature.groupCache[group]; } if (group && group.children.length && (startIdx = me.indexOf(group.children[0], true, true)) !== -1) { group.isCollapsed = false; me.isExpandingOrCollapsing = 1; me.data.removeAt(startIdx); me.fireEvent('bulkremove', me, [me.getGroupPlaceholder(group)], [startIdx]); me.data.insert(startIdx, group.children); me.fireEvent('add', me, group.children, startIdx); me.fireEvent('groupexpand', me, group); me.isExpandingOrCollapsing = 0; } }, collapseGroup: function(group) { var me = this, startIdx, placeholder, i, j, len, removeIndices; if (typeof group === 'string') { group = me.groupingFeature.groupCache[group]; } if (group && (len = group.children.length) && (startIdx = me.indexOf(group.children[0], true)) !== -1) { group.isCollapsed = true; me.isExpandingOrCollapsing = 2; me.data.removeRange(startIdx, len); removeIndices = new Array(len); for (i = 0, j = startIdx; i < len; i++, j++) { removeIndices[i] = j; } me.fireEvent('bulkremove', me, group.children, removeIndices); me.data.insert(startIdx, placeholder = me.getGroupPlaceholder(group)); me.fireEvent('add', me, [placeholder], startIdx); me.fireEvent('groupcollapse', me, group); me.isExpandingOrCollapsing = 0; } }, getGroupPlaceholder: function(group) { if (!group.placeholder) { var groupPlaceholder = group.placeholder = new this.store.model(null, 'group-' + group.name + '-placeholder'); groupPlaceholder.set(this.store.getGroupField(), group.name); groupPlaceholder.rows = groupPlaceholder.children = group.children; groupPlaceholder.isCollapsedPlaceholder = true; } return group.placeholder; }, indexOf: function(record, viewOnly, includeCollapsed) { var me = this, groups, groupCount, i, group, groupIndex, result = 0; if (record && (includeCollapsed || !me.isInCollapsedGroup(record))) { groups = me.store.getGroups(); groupCount = groups.length; for (i = 0; i < groupCount; i++) { group = groups[i]; if (group.name === this.store.getGroupString(record)) { groupIndex = Ext.Array.indexOf(group.children, record); return result + groupIndex; } result += (viewOnly && me.isCollapsed(group.name)) ? 1 : group.children.length; } } return -1; }, indexOfTotal: function(record) { return this.store.indexOf(record); }, onRefresh: function(store) { this.processStore(this.store); this.fireEvent('refresh', this); }, onBulkRemove: function(store, records, indices) { this.processStore(this.store); this.fireEvent('refresh', this); }, onClear: function(store, records, startIndex) { this.processStore(this.store); this.fireEvent('clear', this); }, onAdd: function(store, records, startIndex) { this.processStore(this.store); this.fireEvent('refresh', this); }, onUpdate: function(store, record, operation, modifiedFieldNames) { var me = this, groupInfo, firstRec, lastRec; if (store.isGrouped()) { groupInfo = record.group = me.groupingFeature.getRecordGroup(record); if (modifiedFieldNames && Ext.Array.contains(modifiedFieldNames, me.groupingFeature.getGroupField())) { return me.onRefresh(me.store); } if (groupInfo.isCollapsed) { me.fireEvent('update', me, groupInfo.placeholder); } else { Ext.suspendLayouts(); me.fireEvent('update', me, record, operation, modifiedFieldNames); firstRec = groupInfo.children[0]; lastRec = groupInfo.children[groupInfo.children.length - 1]; if (firstRec !== record) { firstRec.group = groupInfo; me.fireEvent('update', me, firstRec, 'edit'); delete firstRec.group; } if (lastRec !== record && lastRec !== firstRec && me.groupingFeature.showSummaryRow) { lastRec.group = groupInfo; me.fireEvent('update', me, lastRec, 'edit'); delete lastRec.group; } Ext.resumeLayouts(true); } delete record.group; } else { me.fireEvent('update', me, record, operation, modifiedFieldNames); } } }); Ext.define('Ext.grid.feature.Grouping', { extend: Ext.grid.feature.Feature , mixins: { summary: Ext.grid.feature.AbstractSummary }, alias: 'feature.grouping', eventPrefix: 'group', groupCls: Ext.baseCSSPrefix + 'grid-group-hd', eventSelector: '.' + Ext.baseCSSPrefix + 'grid-group-hd', refreshData: {}, groupInfo: {}, wrapsItem: true, groupHeaderTpl: '{columnName}: {name}', depthToIndent: 17, collapsedCls: Ext.baseCSSPrefix + 'grid-group-collapsed', hdCollapsedCls: Ext.baseCSSPrefix + 'grid-group-hd-collapsed', hdNotCollapsibleCls: Ext.baseCSSPrefix + 'grid-group-hd-not-collapsible', collapsibleCls: Ext.baseCSSPrefix + 'grid-group-hd-collapsible', ctCls: Ext.baseCSSPrefix + 'group-hd-container', groupByText : 'Group by this field', showGroupsText : 'Show in groups', hideGroupedHeader : false, startCollapsed : false, enableGroupingMenu : true, enableNoGroups : true, collapsible: true, expandTip: 'Click to expand. CTRL key collapses all others', collapseTip: 'Click to collapse. CTRL/click collapses all others', showSummaryRow: false, tableTpl: { before: function(values) { if (this.groupingFeature.disabled || values.rows.length === 1 && values.rows[0].isSummary) { return; } this.groupingFeature.setup(values.rows, values.view.rowValues); }, after: function(values) { if (this.groupingFeature.disabled || values.rows.length === 1 && values.rows[0].isSummary) { return; } this.groupingFeature.cleanup(values.rows, values.view.rowValues); }, priority: 200 }, groupTpl: [ '{%', 'var me = this.groupingFeature;', 'if (me.disabled) {', 'values.needsWrap = false;', '} else {', 'me.setupRowData(values.record, values.rowIndex, values);', '}', '%}', '', '
    ', '', '{%', 'var groupTitleStyle = (!values.view.lockingPartner || (values.view.ownerCt === values.view.ownerCt.ownerLockable.lockedGrid) || (values.view.lockingPartner.headerCt.getVisibleGridColumns().length === 0)) ? "" : "visibility:hidden";', '%}', '
    ', '
    ', '{[values.groupHeaderTpl.apply(values.groupInfo, parent) || " "]}', '
    ', '
    ', '
    ', '', ' ', Ext.baseCSSPrefix, 'grid-table-summary"', 'border="0" cellspacing="0" cellpadding="0" style="width:100%" {ariaSummaryTableAttr}>', '{[values.view.renderColumnSizer(out)]}', '', '{%', 'values.itemClasses.length = 0;', 'this.nextTpl.applyOut(values, out, parent);', '%}', '', '', '{%me.outputSummaryRecord(values.summaryRecord, values, out);%}', '', '
    ', '
    ', '
    ', '
    {rowBody}
    ', '
    ', '', '{[values.view.renderColumnSizer(out)]}', '{%', 'values.itemClasses.length = 0;', 'this.nextTpl.applyOut(values, out, parent)', '%}', '
    ', '
    ', '', '
    ', '' ], style: 'overflow:hidden', itemId: 'summaryBar', cls: [ me.dockedSummaryCls, me.dockedSummaryCls + '-' + me.dock ], xtype: 'component', dock: me.dock, weight: 10000000 })[0]; }, afterrender: function() { grid.body.addCls(me.panelBodyCls + me.dock); view.mon(view.el, { scroll: me.onViewScroll, scope: me }); me.onStoreUpdate(); }, single: true }); grid.headerCt.afterComponentLayout = Ext.Function.createSequence(grid.headerCt.afterComponentLayout, function() { var width = this.getFullWidth(), innerCt = me.summaryBar.innerCt, scrollWidth; if (view.hasVerticalScroll()) { scrollWidth = Ext.getScrollbarSize().width; width -= scrollWidth; innerCt.down('table').setStyle(me.scrollPadProperty, scrollWidth + 'px'); } innerCt.setWidth(width); }); } else { me.view.addFooterFn(me.renderTFoot); } grid.on({ columnmove: me.onStoreUpdate, scope: me }); view.mon(view.store, { update: me.onStoreUpdate, datachanged: me.onStoreUpdate, scope: me }); }, renderTFoot: function(values, out) { var view = values.view, me = view.findFeature('summary'); if (me.showSummaryRow) { out.push(''); me.outputSummaryRecord(me.createSummaryRecord(view), values, out); out.push(''); } }, toggleSummaryRow: function(visible) { var me = this, bar = me.summaryBar; me.callParent(arguments); if (bar) { bar.setVisible(me.showSummaryRow); me.onViewScroll(); } }, vetoEvent: function(record, row, rowIndex, e) { return !e.getTarget(this.summaryRowSelector); }, onViewScroll: function() { this.summaryBar.el.dom.scrollLeft = this.view.el.dom.scrollLeft; }, createSummaryRecord: function(view) { var columns = view.headerCt.getVisibleGridColumns(), info = { records: view.store.getRange() }, colCount = columns.length, i, column, summaryRecord = this.summaryRecord || (this.summaryRecord = new view.store.model(null, view.id + '-summary-record')); summaryRecord.beginEdit(); for (i = 0; i < colCount; i++) { column = columns[i]; if (!column.dataIndex) { column.dataIndex = column.id; } summaryRecord.set(column.dataIndex, this.getSummary(view.store, column.summaryType, column.dataIndex, info)); } summaryRecord.endEdit(true); summaryRecord.commit(true); summaryRecord.isSummary = true; return summaryRecord; }, onStoreUpdate: function() { var me = this, view = me.view, record = me.createSummaryRecord(view), newRowDom = view.createRowElement(record, -1), oldRowDom, partner, p; if (!view.rendered) { return; } if (me.dock) { oldRowDom = me.summaryBar.el.down('.' + me.summaryRowCls, true); } else { oldRowDom = me.view.getNode(record); } if (oldRowDom) { p = oldRowDom.parentNode; p.insertBefore(newRowDom, oldRowDom); p.removeChild(oldRowDom); partner = me.lockingPartner; if (partner && partner.grid.rendered && !me.calledFromLockingPartner) { partner.calledFromLockingPartner = true; partner.onStoreUpdate(); partner.calledFromLockingPartner = false; } } if (me.dock) { me.onColumnHeaderLayout(); } }, onColumnHeaderLayout: function() { var view = this.view, columns = view.headerCt.getVisibleGridColumns(), column, len = columns.length, i, summaryEl = this.summaryBar.el, el; for (i = 0; i < len; i++) { column = columns[i]; el = summaryEl.down(view.getCellSelector(column)); if (el) { if (column.hidden) { el.setDisplayed(false); } else { el.setDisplayed(true); el.setWidth(column.width || (column.lastBox ? column.lastBox.width : 100)); } } } } }); Ext.define('Ext.grid.locking.HeaderContainer', { extend: Ext.grid.header.Container , constructor: function(lockable) { var me = this, events, event, eventNames = [], lockedGrid = lockable.lockedGrid, normalGrid = lockable.normalGrid; me.lockable = lockable; me.callParent(); lockedGrid.visibleColumnManager.rootColumns = normalGrid.visibleColumnManager.rootColumns = lockable.visibleColumnManager = me.visibleColumnManager = new Ext.grid.ColumnManager(true, lockedGrid.headerCt, normalGrid.headerCt); lockedGrid.columnManager.rootColumns = normalGrid.columnManager.rootColumns = lockable.columnManager = me.columnManager = new Ext.grid.ColumnManager(false, lockedGrid.headerCt, normalGrid.headerCt); events = lockedGrid.headerCt.events; for (event in events) { if (events.hasOwnProperty(event)) { eventNames.push(event); } } me.relayEvents(lockedGrid.headerCt, eventNames); me.relayEvents(normalGrid.headerCt, eventNames); }, getRefItems: function() { return this.lockable.lockedGrid.headerCt.getRefItems().concat(this.lockable.normalGrid.headerCt.getRefItems()); }, getGridColumns: function() { return this.lockable.lockedGrid.headerCt.getGridColumns().concat(this.lockable.normalGrid.headerCt.getGridColumns()); }, getColumnsState: function () { var me = this, locked = me.lockable.lockedGrid.headerCt.getColumnsState(), normal = me.lockable.normalGrid.headerCt.getColumnsState(); return locked.concat(normal); }, applyColumnsState: function (columns) { var me = this, lockedGrid = me.lockable.lockedGrid, lockedHeaderCt = lockedGrid.headerCt, normalHeaderCt = me.lockable.normalGrid.headerCt, lockedCols = Ext.Array.toValueMap(lockedHeaderCt.items.items, 'headerId'), normalCols = Ext.Array.toValueMap(normalHeaderCt.items.items, 'headerId'), locked = [], normal = [], lockedWidth = 1, length = columns.length, i, existing, lockedDefault, col; for (i = 0; i < length; i++) { col = columns[i]; lockedDefault = lockedCols[col.id]; existing = lockedDefault || normalCols[col.id]; if (existing) { if (existing.applyColumnState) { existing.applyColumnState(col); } if (existing.locked === undefined) { existing.locked = !!lockedDefault; } if (existing.locked) { locked.push(existing); if (!existing.hidden && typeof existing.width == 'number') { lockedWidth += existing.width; } } else { normal.push(existing); } } } if (locked.length + normal.length == lockedHeaderCt.items.getCount() + normalHeaderCt.items.getCount()) { lockedHeaderCt.removeAll(false); normalHeaderCt.removeAll(false); lockedHeaderCt.add(locked); normalHeaderCt.add(normal); lockedGrid.setWidth(lockedWidth); } } }); Ext.define('Ext.grid.locking.View', { alternateClassName: 'Ext.grid.LockingView', mixins: { observable: Ext.util.Observable }, isLockingView: true, eventRelayRe: /^(beforeitem|beforecontainer|item|container|cell|refresh)/, constructor: function(config){ var me = this, eventNames = [], eventRe = me.eventRelayRe, locked = config.locked.getView(), normal = config.normal.getView(), events, event; Ext.apply(me, { lockedView: locked, normalView: normal, lockedGrid: config.locked, normalGrid: config.normal, panel: config.panel }); me.mixins.observable.constructor.call(me, config); events = locked.events; for (event in events) { if (events.hasOwnProperty(event) && eventRe.test(event)) { eventNames.push(event); } } me.relayEvents(locked, eventNames); me.relayEvents(normal, eventNames); normal.on({ scope: me, itemmouseleave: me.onItemMouseLeave, itemmouseenter: me.onItemMouseEnter }); locked.on({ scope: me, itemmouseleave: me.onItemMouseLeave, itemmouseenter: me.onItemMouseEnter }); me.panel.on({ render: me.onPanelRender, scope: me }); }, onPanelRender: function() { var me = this, mask = me.loadMask, cfg = { target: me.panel, msg: me.loadingText, msgCls: me.loadingCls, useMsg: me.loadingUseMsg, store: me.panel.store }; me.el = me.panel.body; me.fireEvent('render', me); if (mask) { if (Ext.isObject(mask)) { cfg = Ext.apply(cfg, mask); } me.loadMask = new Ext.LoadMask(cfg); } }, getGridColumns: function() { var cols = this.lockedGrid.headerCt.getVisibleGridColumns(); return cols.concat(this.normalGrid.headerCt.getVisibleGridColumns()); }, getEl: function(column){ return this.getViewForColumn(column).getEl(); }, getViewForColumn: function(column) { var view = this.lockedView, inLocked; view.headerCt.cascade(function(col){ if (col === column) { inLocked = true; return false; } }); return inLocked ? view : this.normalView; }, onItemMouseEnter: function(view, record){ var me = this, locked = me.lockedView, other = me.normalView, item; if (view.trackOver) { if (view !== locked) { other = locked; } item = other.getNode(record, false); other.highlightItem(item); } }, onItemMouseLeave: function(view, record){ var me = this, locked = me.lockedView, other = me.normalView; if (view.trackOver) { if (view !== locked) { other = locked; } other.clearHighlight(); } }, relayFn: function(name, args){ args = args || []; var view = this.lockedView; view[name].apply(view, args); view = this.normalView; view[name].apply(view, args); }, getSelectionModel: function(){ return this.panel.getSelectionModel(); }, getStore: function(){ return this.panel.store; }, getNode: function(nodeInfo, dataRow) { return this.normalView.getNode(nodeInfo, dataRow); }, getCell: function(record, column) { var view = this.getViewForColumn(column), row = view.getNode(record, true); return Ext.fly(row).down(column.getCellSelector()); }, indexOf: function(record) { var result = this.lockedView.indexOf(record); if (!result) { result = this.normalView.indexOf(record); } return result; }, focus: function() { var p = this.getSelectionModel().getCurrentPosition(), v = p ? p.view : this.normalView; v.focus(); }, focusRow: function(row) { this.normalView.focusRow(row); }, focusCell: function(position) { position.view.focusCell(position); }, isVisible: function(deep) { return this.panel.isVisible(deep); }, getCellByPosition: function(pos, returnDom) { var col = pos.column, lockedSize = this.lockedGrid.getColumnManager().getColumns().length; if (col >= lockedSize) { pos = Ext.apply({}, pos); pos.column -= lockedSize; return this.normalView.getCellByPosition(pos, returnDom); } else { return this.lockedView.getCellByPosition(pos, returnDom); } }, getRecord: function(node) { var result = this.lockedView.getRecord(node); if (!result) { result = this.normalView.getRecord(node); } return result; }, scrollBy: function(){ var normal = this.normalView; normal.scrollBy.apply(normal, arguments); }, addElListener: function(eventName, fn, scope){ this.relayFn('addElListener', arguments); }, refreshNode: function(){ this.relayFn('refreshNode', arguments); }, refresh: function(){ this.relayFn('refresh', arguments); }, bindStore: function(){ this.relayFn('bindStore', arguments); }, addRowCls: function(){ this.relayFn('addRowCls', arguments); }, removeRowCls: function(){ this.relayFn('removeRowCls', arguments); }, destroy: function(){ var me = this, mask = me.loadMask; me.clearListeners(); if (mask && mask.bindStore) { mask.bindStore(null); } } }); Ext.define('Ext.grid.locking.Lockable', { alternateClassName: 'Ext.grid.Lockable', syncRowHeight: true, headerCounter: 0, scrollDelta: 40, lockedGridCls: Ext.baseCSSPrefix + 'grid-inner-locked', unlockText: 'Unlock', lockText: 'Lock', bothCfgCopy: [ 'invalidateScrollerOnRefresh', 'hideHeaders', 'enableColumnHide', 'enableColumnMove', 'enableColumnResize', 'sortableColumns', 'columnLines', 'rowLines' ], normalCfgCopy: [ 'verticalScroller', 'verticalScrollDock', 'verticalScrollerType', 'scroll' ], lockedCfgCopy: [], determineXTypeToCreate: function(lockedSide) { var me = this, typeToCreate, xtypes, xtypesLn, xtype, superxtype; if (me.subGridXType) { typeToCreate = me.subGridXType; } else { if (!lockedSide) { return 'gridpanel'; } xtypes = this.getXTypes().split('/'); xtypesLn = xtypes.length; xtype = xtypes[xtypesLn - 1]; superxtype = xtypes[xtypesLn - 2]; if (superxtype !== 'tablepanel') { typeToCreate = superxtype; } else { typeToCreate = xtype; } } return typeToCreate; }, injectLockable: function() { this.lockable = true; this.hasView = true; var me = this, scrollbarHeight = Ext.getScrollbarSize().height, store = me.store = Ext.StoreManager.lookup(me.store), selModel = me.getSelectionModel(), allFeatures, allPlugins, lockedGrid, normalGrid, i, columns, lockedHeaderCt, normalHeaderCt, lockedView, normalView, listeners, loadMask = me.viewConfig && me.viewConfig.loadMask, bufferedRenderer = me.findPlugin('bufferedrenderer'); allFeatures = me.constructLockableFeatures(); if (me.features) { me.features = null; } allPlugins = me.constructLockablePlugins(); me.plugins = allPlugins.topPlugins; lockedGrid = Ext.apply({ id: me.id + '-locked', isLocked: true, ownerLockable: me, xtype: me.determineXTypeToCreate(true), store: store, scrollerOwner: false, animate: false, scroll: scrollbarHeight ? false : 'vertical', selModel: selModel, border: false, cls: me.lockedGridCls, isLayoutRoot: function() { return false; }, features: allFeatures.lockedFeatures, plugins: allPlugins.lockedPlugins }, me.lockedGridConfig); normalGrid = Ext.apply({ id: me.id + '-normal', isLocked: false, ownerLockable: me, xtype: me.determineXTypeToCreate(), store: store, scrollerOwner: false, selModel: selModel, border: false, isLayoutRoot: function() { return false; }, features: allFeatures.normalFeatures, plugins: allPlugins.normalPlugins }, me.normalGridConfig); me.addCls(Ext.baseCSSPrefix + 'grid-locked'); Ext.copyTo(normalGrid, me, me.bothCfgCopy, true); Ext.copyTo(lockedGrid, me, me.bothCfgCopy, true); Ext.copyTo(normalGrid, me, me.normalCfgCopy, true); Ext.copyTo(lockedGrid, me, me.lockedCfgCopy, true); for (i = 0; i < me.normalCfgCopy.length; i++) { delete me[me.normalCfgCopy[i]]; } for (i = 0; i < me.lockedCfgCopy.length; i++) { delete me[me.lockedCfgCopy[i]]; } me.addEvents( 'processcolumns', 'lockcolumn', 'unlockcolumn' ); me.addStateEvents(['lockcolumn', 'unlockcolumn']); columns = me.processColumns(me.columns); lockedGrid.width = columns.lockedWidth + Ext.num(selModel.headerWidth, 0) + (columns.locked.items.length ? 1 : 0); lockedGrid.columns = columns.locked; normalGrid.columns = columns.normal; normalGrid.flex = 1; lockedGrid.viewConfig = me.lockedViewConfig || {}; lockedGrid.viewConfig.loadingUseMsg = false; lockedGrid.viewConfig.loadMask = false; if (scrollbarHeight) { lockedGrid.viewConfig.style = 'border-bottom:' + scrollbarHeight + 'px solid #f6f6f6;' + (lockedGrid.viewConfig.style || ''); } normalGrid.viewConfig = me.normalViewConfig || {}; normalGrid.viewConfig.loadMask = false; Ext.applyIf(lockedGrid.viewConfig, me.viewConfig); Ext.applyIf(normalGrid.viewConfig, me.viewConfig); me.lockedGrid = Ext.ComponentManager.create(lockedGrid); if (me.isTree) { me.lockedGrid.getView().animate = false; normalGrid.store = me.lockedGrid.view.store; normalGrid.deferRowRender = false; normalGrid.viewConfig.stripeRows = me.lockedGrid.view.stripeRows; normalGrid.rowLines = me.lockedGrid.rowLines; } lockedView = me.lockedGrid.getView(); normalGrid.viewConfig.lockingPartner = lockedView; me.normalGrid = Ext.ComponentManager.create(normalGrid); lockedView.lockingPartner = normalView = me.normalGrid.getView(); me.view = new Ext.grid.locking.View({ loadingText: normalView.loadingText, loadingCls: normalView.loadingCls, loadingUseMsg: normalView.loadingUseMsg, loadMask: loadMask === undefined ? me.loadMask : loadMask, locked: me.lockedGrid, normal: me.normalGrid, panel: me }); listeners = bufferedRenderer ? {} : { scroll: { fn: me.onLockedViewScroll, element: 'el', scope: me } }; if (scrollbarHeight) { me.lockedGrid.on({ afterlayout: me.afterLockedViewLayout, scope: me }); lockedView.getOverflowStyle(); if (lockedView.scrollFlags.y) { me.lockedGrid.headerCt.forceFit = true; } else { listeners.mousewheel = { fn: me.onLockedViewMouseWheel, element: 'el', scope: me }; } } lockedView.on(listeners); listeners = bufferedRenderer ? {} : { scroll: { fn: me.onNormalViewScroll, element: 'el', scope: me }, scope: me }; normalView.on(listeners); lockedHeaderCt = me.lockedGrid.headerCt; normalHeaderCt = me.normalGrid.headerCt; me.headerCt = me.view.headerCt = new Ext.grid.locking.HeaderContainer(me); lockedHeaderCt.lockedCt = true; lockedHeaderCt.lockableInjected = true; normalHeaderCt.lockableInjected = true; lockedHeaderCt.on({ add: { buffer: 1, scope: me, fn: me.onLockedHeaderAdd }, columnshow: me.onLockedHeaderShow, columnhide: me.onLockedHeaderHide, sortchange: me.onLockedHeaderSortChange, columnresize: me.onLockedHeaderResize, scope: me }); normalHeaderCt.on({ sortchange: me.onNormalHeaderSortChange, scope: me }); me.modifyHeaderCt(); me.items = [me.lockedGrid, me.normalGrid]; me.relayHeaderCtEvents(lockedHeaderCt); me.relayHeaderCtEvents(normalHeaderCt); me.storeRelayers = me.relayEvents(store, [ 'filterchange', 'groupchange' ]); me.layout = { type: 'hbox', align: 'stretch' }; }, getLockingViewConfig: function(){ return { xclass: 'Ext.grid.locking.View', locked: this.lockedGrid, normal: this.normalGrid, panel: this }; }, processColumns: function(columns) { var i, len, column, cp = new Ext.grid.header.Container(), lockedHeaders = [], normalHeaders = [], lockedHeaderCt = { itemId: 'lockedHeaderCt', stretchMaxPartner: '^^>>#normalHeaderCt', items: lockedHeaders }, normalHeaderCt = { itemId: 'normalHeaderCt', stretchMaxPartner: '^^>>#lockedHeaderCt', items: normalHeaders }, result = { lockedWidth: 0, locked: lockedHeaderCt, normal: normalHeaderCt }; if (Ext.isObject(columns)) { Ext.applyIf(lockedHeaderCt, columns); Ext.applyIf(normalHeaderCt, columns); Ext.apply(cp, columns); columns = columns.items; } for (i = 0, len = columns.length; i < len; ++i) { column = columns[i]; if (!column.isComponent) { column = cp.lookupComponent(cp.applyDefaults(column)); } column.processed = true; if (column.locked || column.autoLock) { if (!column.hidden) { result.lockedWidth += this.getColumnWidth(column) || cp.defaultWidth; } lockedHeaders.push(column); } else { normalHeaders.push(column); } if (!column.headerId) { column.headerId = (column.initialConfig || column).id || ('h' + (++this.headerCounter)); } } this.fireEvent('processcolumns', this, lockedHeaders, normalHeaders); cp.destroy(); return result; }, getColumnWidth: function(column) { var result = column.width || 0, subcols, len, i; if (!result && column.isGroupHeader) { subcols = column.items.items; len = subcols.length; for (i = 0; i < len; i++) { result += this.getColumnWidth(subcols[i]); } } return result; }, afterLockedViewLayout: function() { var me = this, lockedView = me.lockedGrid.getView(), lockedViewEl = lockedView.el.dom, spacerHeight = (me.normalGrid.headerCt.tooNarrow ? Ext.getScrollbarSize().height : 0); if (lockedView.scrollFlags.x && lockedViewEl.scrollWidth > lockedViewEl.clientWidth) { spacerHeight = 0; } lockedView.el.dom.style.borderBottomWidth = spacerHeight + 'px'; if (!Ext.isBorderBox) { lockedView.el.setHeight(lockedView.lastBox.height); } }, onLockedViewMouseWheel: function(e) { var me = this, scrollDelta = -me.scrollDelta, deltaY = scrollDelta * e.getWheelDeltas().y, vertScrollerEl = me.lockedGrid.getView().el.dom, verticalCanScrollDown, verticalCanScrollUp; if (!me.ignoreMousewheel) { if (vertScrollerEl) { verticalCanScrollDown = vertScrollerEl.scrollTop !== vertScrollerEl.scrollHeight - vertScrollerEl.clientHeight; verticalCanScrollUp = vertScrollerEl.scrollTop !== 0; } if ((deltaY < 0 && verticalCanScrollUp) || (deltaY > 0 && verticalCanScrollDown)) { e.stopEvent(); vertScrollerEl.scrollTop += deltaY; me.normalGrid.getView().el.dom.scrollTop = vertScrollerEl.scrollTop; me.onNormalViewScroll(); } } }, onLockedViewScroll: function() { var me = this, lockedView = me.lockedGrid.getView(), normalView = me.normalGrid.getView(), normalDom = normalView.el.dom, lockedDom = lockedView.el.dom, normalTable, lockedTable; if (normalDom.scrollTop !== lockedDom.scrollTop) { normalDom.scrollTop = lockedDom.scrollTop; if (me.store.buffered) { lockedTable = lockedView.el.child('table', true); normalTable = normalView.el.child('table', true); normalTable.style.position = 'absolute'; normalTable.style.top = lockedTable.style.top; } } }, onNormalViewScroll: function() { var me = this, lockedView = me.lockedGrid.getView(), normalView = me.normalGrid.getView(), normalDom = normalView.el.dom, lockedDom = lockedView.el.dom, normalTable, lockedTable; if (normalDom.scrollTop !== lockedDom.scrollTop) { lockedDom.scrollTop = normalDom.scrollTop; if (me.store.buffered) { lockedTable = lockedView.el.child('table', true); normalTable = normalView.el.child('table', true); lockedTable.style.position = 'absolute'; lockedTable.style.top = normalTable.style.top; } } }, syncRowHeights: function() { var me = this, i, lockedView = me.lockedGrid.getView(), normalView = me.normalGrid.getView(), lockedRowEls = lockedView.all.slice(), normalRowEls = normalView.all.slice(), ln = lockedRowEls.length, scrollTop; if (normalRowEls.length === ln) { for (i = 0; i < ln; i++) { normalView.syncRowHeights(lockedRowEls[i], normalRowEls[i]); } scrollTop = normalView.el.dom.scrollTop; normalView.el.dom.scrollTop = scrollTop; lockedView.el.dom.scrollTop = scrollTop; } }, modifyHeaderCt: function() { var me = this; me.lockedGrid.headerCt.getMenuItems = me.getMenuItems(me.lockedGrid.headerCt.getMenuItems, true); me.normalGrid.headerCt.getMenuItems = me.getMenuItems(me.normalGrid.headerCt.getMenuItems, false); me.lockedGrid.headerCt.showMenuBy = Ext.Function.createInterceptor(me.lockedGrid.headerCt.showMenuBy, me.showMenuBy); me.normalGrid.headerCt.showMenuBy = Ext.Function.createInterceptor(me.normalGrid.headerCt.showMenuBy, me.showMenuBy); }, onUnlockMenuClick: function() { this.unlock(); }, onLockMenuClick: function() { this.lock(); }, showMenuBy: function(t, header) { var menu = this.getMenu(), unlockItem = menu.down('#unlockItem'), lockItem = menu.down('#lockItem'), sep = unlockItem.prev(); if (header.lockable === false) { sep.hide(); unlockItem.hide(); lockItem.hide(); } else { sep.show(); unlockItem.show(); lockItem.show(); if (!unlockItem.initialConfig.disabled) { unlockItem.setDisabled(header.lockable === false); } if (!lockItem.initialConfig.disabled) { lockItem.setDisabled(!header.isLockable()); } } }, getMenuItems: function(getMenuItems, locked) { var me = this, unlockText = me.unlockText, lockText = me.lockText, unlockCls = Ext.baseCSSPrefix + 'hmenu-unlock', lockCls = Ext.baseCSSPrefix + 'hmenu-lock', unlockHandler = Ext.Function.bind(me.onUnlockMenuClick, me), lockHandler = Ext.Function.bind(me.onLockMenuClick, me); return function() { var o = getMenuItems.call(this); o.push('-', { itemId: 'unlockItem', iconCls: unlockCls, text: unlockText, handler: unlockHandler, disabled: !locked }); o.push({ itemId: 'lockItem', iconCls: lockCls, text: lockText, handler: lockHandler, disabled: locked }); return o; }; }, syncLockedWidth: function() { var me = this, locked = me.lockedGrid, lockedView = locked.view, lockedViewEl = lockedView.el.dom, normal = me.normalGrid, lockedColCount = locked.headerCt.getVisibleGridColumns().length, normalColCount = normal.headerCt.getVisibleGridColumns().length; Ext.suspendLayouts(); if (normalColCount) { normal.show(); if (lockedColCount) { if (!locked.headerCt.forceFit) { delete locked.flex; locked.setWidth(locked.headerCt.getFullWidth()); } locked.addCls(me.lockedGridCls); locked.show(); } else { locked.getView().refresh(); locked.hide(); } lockedView.el.setStyle(lockedView.getOverflowStyle()); me.ignoreMousewheel = lockedView.scrollFlags.y; } else { normal.hide(); lockedViewEl.style.borderBottomWidth = '0'; locked.flex = 1; delete locked.width; locked.removeCls(me.lockedGridCls); locked.show(); lockedView.el.setStyle(normal.view.getOverflowStyle()); me.ignoreMousewheel = true; } Ext.resumeLayouts(true); return [lockedColCount, normalColCount]; }, onLockedHeaderAdd: function() { if (!this.ignoreAddLockedColumn) { this.syncLockedWidth(); } }, onLockedHeaderResize: function() { this.syncLockedWidth(); }, onLockedHeaderHide: function() { this.syncLockedWidth(); }, onLockedHeaderShow: function() { this.syncLockedWidth(); }, onLockedHeaderSortChange: function(headerCt, header, sortState) { if (sortState) { this.normalGrid.headerCt.clearOtherSortStates(null, true); } }, onNormalHeaderSortChange: function(headerCt, header, sortState) { if (sortState) { this.lockedGrid.headerCt.clearOtherSortStates(null, true); } }, lock: function(activeHd, toIdx, toCt) { var me = this, normalGrid = me.normalGrid, lockedGrid = me.lockedGrid, normalHCt = normalGrid.headerCt, refreshFlags, ownerCt; activeHd = activeHd || normalHCt.getMenu().activeHeader; toCt = toCt || lockedGrid.headerCt, ownerCt = activeHd.ownerCt; if (!activeHd.isLockable()) { return; } if (activeHd.flex) { activeHd.width = activeHd.getWidth(); activeHd.flex = null; } Ext.suspendLayouts(); ownerCt.remove(activeHd, false); activeHd.locked = true; me.ignoreAddLockedColumn = true; if (Ext.isDefined(toIdx)) { toCt.insert(toIdx, activeHd); } else { toCt.add(activeHd); } me.ignoreAddLockedColumn = false; refreshFlags = me.syncLockedWidth(); if (refreshFlags[0]) { lockedGrid.getView().refresh(); } if (refreshFlags[1]) { normalGrid.getView().refresh(); } Ext.resumeLayouts(true); me.fireEvent('lockcolumn', me, activeHd); }, unlock: function(activeHd, toIdx, toCt) { var me = this, normalGrid = me.normalGrid, lockedGrid = me.lockedGrid, lockedHCt = lockedGrid.headerCt, refreshFlags; if (!Ext.isDefined(toIdx)) { toIdx = 0; } activeHd = activeHd || lockedHCt.getMenu().activeHeader; toCt = toCt || normalGrid.headerCt; Ext.suspendLayouts(); activeHd.ownerCt.remove(activeHd, false); activeHd.locked = false; toCt.insert(toIdx, activeHd); refreshFlags = me.syncLockedWidth(); if (refreshFlags[0]) { lockedGrid.getView().refresh(); } if (refreshFlags[1]) { normalGrid.getView().refresh(); } Ext.resumeLayouts(true); me.fireEvent('unlockcolumn', me, activeHd); }, reconfigureLockable: function(store, columns) { var me = this, oldStore = me.store, lockedGrid = me.lockedGrid, normalGrid = me.normalGrid; Ext.suspendLayouts(); if (columns) { lockedGrid.headerCt.removeAll(); normalGrid.headerCt.removeAll(); columns = me.processColumns(columns); me.ignoreAddLockedColumn = true; lockedGrid.headerCt.add(columns.locked.items); me.ignoreAddLockedColumn = false; normalGrid.headerCt.add(columns.normal.items); me.syncLockedWidth(); } if (store && store !== oldStore) { store = Ext.data.StoreManager.lookup(store); me.store = store; lockedGrid.bindStore(store); normalGrid.bindStore(store); } else { lockedGrid.getView().refresh(); normalGrid.getView().refresh(); } Ext.resumeLayouts(true); }, constructLockableFeatures: function() { var features = this.features, feature, featureClone, lockedFeatures, normalFeatures, i = 0, len; if (features) { if (!Ext.isArray(features)) { features = [ features ]; } lockedFeatures = []; normalFeatures = []; len = features.length; for (; i < len; i++) { feature = features[i]; if (!feature.isFeature) { feature = Ext.create('feature.' + feature.ftype, feature); } switch (feature.lockableScope) { case 'locked': lockedFeatures.push(feature); break; case 'normal': normalFeatures.push(feature); break; default: feature.lockableScope = 'both'; lockedFeatures.push(feature); normalFeatures.push(featureClone = feature.clone()); featureClone.lockingPartner = feature; feature.lockingPartner = featureClone; } } } return { normalFeatures: normalFeatures, lockedFeatures: lockedFeatures }; }, constructLockablePlugins: function() { var plugins = this.plugins, plugin, normalPlugin, lockedPlugin, topPlugins, lockedPlugins, normalPlugins, i = 0, len, lockableScope, pluginCls; if (plugins) { if (!Ext.isArray(plugins)) { plugins = [ plugins ]; } topPlugins = []; lockedPlugins = []; normalPlugins = []; len = plugins.length; for (; i < len; i++) { plugin = plugins[i]; if (plugin.init) { lockableScope = plugin.lockableScope; } else { pluginCls = plugin.ptype ? Ext.ClassManager.getByAlias(('plugin.' + plugin.ptype)) : Ext.ClassManager.get(plugin.xclass); lockableScope = pluginCls.prototype.lockableScope; } switch (lockableScope) { case 'both': lockedPlugins.push(lockedPlugin = plugin.clonePlugin()); normalPlugins.push(normalPlugin = plugin.clonePlugin()); lockedPlugin.lockingPartner = normalPlugin; normalPlugin.lockingPartner = lockedPlugin; Ext.destroy(plugin); break; case 'locked': lockedPlugins.push(plugin); break; case 'normal': normalPlugins.push(plugin); break; default: topPlugins.push(plugin); } } } return { topPlugins: topPlugins, normalPlugins: normalPlugins, lockedPlugins: lockedPlugins }; }, destroyLockable: function(){ Ext.destroy(this.view, this.headerCt); } }, function() { this.borrow(Ext.AbstractComponent, ['constructPlugin']); }); Ext.define('Ext.tree.View', { extend: Ext.view.Table , alias: 'widget.treeview', isTreeView: true, loadingCls: Ext.baseCSSPrefix + 'grid-tree-loading', expandedCls: Ext.baseCSSPrefix + 'grid-tree-node-expanded', leafCls: Ext.baseCSSPrefix + 'grid-tree-node-leaf', expanderSelector: '.' + Ext.baseCSSPrefix + 'tree-expander', checkboxSelector: '.' + Ext.baseCSSPrefix + 'tree-checkbox', expanderIconOverCls: Ext.baseCSSPrefix + 'tree-expander-over', nodeAnimWrapCls: Ext.baseCSSPrefix + 'tree-animator-wrap', ariaRole: 'tree', blockRefresh: true, loadMask: false, rootVisible: true, deferInitialRefresh: false, expandDuration: 250, collapseDuration: 250, toggleOnDblClick: true, stripeRows: false, uiFields: ['expanded', 'loaded', 'checked', 'expandable', 'leaf', 'icon', 'iconCls', 'loading', 'qtip', 'qtitle'], treeRowTpl: [ '{%', 'this.processRowValues(values);', 'this.nextTpl.applyOut(values, out, parent);', '%}', { priority: 10, processRowValues: function(rowValues) { var record = rowValues.record, view = rowValues.view; rowValues.rowAttr = {}; rowValues.rowAttr['data-qtip'] = record.get('qtip') || ''; rowValues.rowAttr['data-qtitle'] = record.get('qtitle') || ''; if (record.isExpanded()) { rowValues.rowClasses.push(view.expandedCls); } if (record.isLeaf()) { rowValues.rowClasses.push(view.leafCls); } if (record.isLoading()) { rowValues.rowClasses.push(view.loadingCls); } } } ], initComponent: function() { var me = this, treeStore = me.panel.getStore(), store = me.store; if (me.initialConfig.animate === undefined) { me.animate = Ext.enableFx; } if (!store || store === treeStore) { me.store = store = new Ext.data.NodeStore({ treeStore: treeStore, recursive: true, rootVisible: me.rootVisible }); } if (me.node) { me.setRootNode(me.node); } me.animQueue = {}; me.animWraps = {}; me.addEvents( 'afteritemexpand', 'afteritemcollapse', 'nodedragover' ); me.callParent(arguments); me.addRowTpl(Ext.XTemplate.getTpl(me, 'treeRowTpl')); }, onBeforeFill: function(treeStore, fillRoot) { this.store.suspendEvents(); }, onFillComplete: function(treeStore, fillRoot, newNodes) { var me = this, store = me.store, start = store.indexOf(newNodes[0]); store.resumeEvents(); fillRoot.triggerUIUpdate(); if (!newNodes.length || start === -1) { return; } me.onAdd(me.store, newNodes, start); me.refreshPartner(); }, onBeforeSort: function() { this.store.suspendEvents(); }, onSort: function(o) { if (o.isStore) { this.store.resumeEvents(); this.refresh(); this.refreshPartner(); } }, refreshPartner: function() { var partner = this.lockingPartner; if (partner) { partner.refresh(); } }, getMaskStore: function() { return this.panel.getStore(); }, afterRender: function() { var me = this; me.callParent(arguments); me.el.on({ scope: me, delegate: me.expanderSelector, mouseover: me.onExpanderMouseOver, mouseout: me.onExpanderMouseOut, click: { delegate: me.checkboxSelector, fn: me.onCheckboxChange, scope: me } }); }, afterComponentLayout: function() { this.callParent(arguments); var stretcher = this.stretcher; if (stretcher) { stretcher.setWidth((this.getWidth() - Ext.getScrollbarSize().width)); } }, processUIEvent: function(e) { if (e.getTarget('.' + this.nodeAnimWrapCls, this.el)) { return false; } return this.callParent(arguments); }, onClear: function() { this.store.removeAll(); }, setRootNode: function(node) { var me = this; me.store.setNode(node); me.node = node; }, onCheckboxChange: function(e, t) { var me = this, item = e.getTarget(me.getItemSelector(), me.getTargetEl()); if (item) { me.onCheckChange(me.getRecord(item)); } }, onCheckChange: function(record) { var checked = record.get('checked'); if (Ext.isBoolean(checked)) { checked = !checked; record.set('checked', checked); this.fireEvent('checkchange', record, checked); } }, getChecked: function() { var checked = []; this.node.cascadeBy(function(rec){ if (rec.get('checked')) { checked.push(rec); } }); return checked; }, isItemChecked: function(rec) { return rec.get('checked'); }, createAnimWrap: function(record, index) { var me = this, node = me.getNode(record), tmpEl, nodeEl, columnSizer = []; me.renderColumnSizer(columnSizer); nodeEl = Ext.get(node); tmpEl = nodeEl.insertSibling({ role: 'presentation', tag: 'tr', html: [ '', '', '' ].join('') }, 'after'); return { record: record, node: node, el: tmpEl, expanding: false, collapsing: false, animating: false, animateEl: tmpEl.down('div'), targetEl: tmpEl.down('tbody') }; }, getAnimWrap: function(parent, bubble) { if (!this.animate) { return null; } var wraps = this.animWraps, wrap = wraps[parent.internalId]; if (bubble !== false) { while (!wrap && parent) { parent = parent.parentNode; if (parent) { wrap = wraps[parent.internalId]; } } } return wrap; }, doAdd: function(records, index) { var me = this, nodes = me.bufferRender(records, index, true), record = records[0], parent = record.parentNode, all = me.all, relativeIndex, animWrap = me.getAnimWrap(parent), targetEl, children, len; if (!animWrap || !animWrap.expanding) { return me.callParent(arguments); } parent = animWrap.record; targetEl = animWrap.targetEl; children = targetEl.dom.childNodes; len = children.length; relativeIndex = index - me.indexInStore(parent) - 1; if (!len || relativeIndex >= len) { targetEl.appendChild(nodes); } else { Ext.fly(children[relativeIndex]).insertSibling(nodes, 'before', true); } all.insert(index, nodes); if (animWrap.isAnimating) { me.onExpand(parent); } }, onRemove : function(ds, records, indexes) { var me = this, empty, i; if (me.viewReady) { empty = me.store.getCount() === 0; if (empty) { me.refresh(); } else { for (i = indexes.length - 1; i >= 0; --i) { me.doRemove(records[i], indexes[i]); } } if (me.hasListeners.itemremove) { for (i = indexes.length - 1; i >= 0; --i) { me.fireEvent('itemremove', records[i], indexes[i]); } } } }, doRemove: function(record, index) { var me = this, all = me.all, animWrap = me.getAnimWrap(record), item = all.item(index), node = item ? item.dom : null; if (!node || !animWrap || !animWrap.collapsing) { return me.callParent(arguments); } animWrap.targetEl.dom.insertBefore(node, animWrap.targetEl.dom.firstChild); all.removeElement(index); }, onBeforeExpand: function(parent, records, index) { var me = this, animWrap; if (me.rendered && me.all.getCount() && me.animate) { if (me.getNode(parent)) { animWrap = me.getAnimWrap(parent, false); if (!animWrap) { animWrap = me.animWraps[parent.internalId] = me.createAnimWrap(parent); animWrap.animateEl.setHeight(0); } else if (animWrap.collapsing) { animWrap.targetEl.select(me.itemSelector).remove(); } animWrap.expanding = true; animWrap.collapsing = false; } } }, onExpand: function(parent) { var me = this, queue = me.animQueue, id = parent.getId(), node = me.getNode(parent), index = node ? me.indexOf(node) : -1, animWrap, animateEl, targetEl, fromHeight = Ext.isIEQuirks ? 1 : 0 if (me.singleExpand) { me.ensureSingleExpand(parent); } if (index === -1) { return; } animWrap = me.getAnimWrap(parent, false); if (!animWrap) { me.refreshSelection(); parent.isExpandingOrCollapsing = false; me.fireEvent('afteritemexpand', parent, index, node); me.refreshSize(); return; } animateEl = animWrap.animateEl; targetEl = animWrap.targetEl; animateEl.stopAnimation(); queue[id] = true; animateEl.dom.style.height = fromHeight + 'px'; animateEl.animate({ from: { height: fromHeight }, to: { height: targetEl.getHeight() }, duration: me.expandDuration, listeners: { afteranimate: function() { var items = targetEl.query(me.itemSelector); if (items.length) { animWrap.el.insertSibling(items, 'before', true); } animWrap.el.remove(); me.refreshSize(); delete me.animWraps[animWrap.record.internalId]; delete queue[id]; } }, callback: function() { me.refreshSelection(); parent.isExpandingOrCollapsing = false; me.fireEvent('afteritemexpand', parent, index, node); } }); animWrap.isAnimating = true; }, onBeforeCollapse: function(parent, records, index, callback, scope) { var me = this, animWrap; if (me.rendered && me.all.getCount()) { if (me.animate) { if (Ext.Array.contains(parent.stores, me.store)) { animWrap = me.getAnimWrap(parent); if (!animWrap) { animWrap = me.animWraps[parent.internalId] = me.createAnimWrap(parent, index); } else if (animWrap.expanding) { animWrap.targetEl.select(this.itemSelector).remove(); } animWrap.expanding = false; animWrap.collapsing = true; animWrap.callback = callback; animWrap.scope = scope; } } else { me.onCollapseCallback = callback; me.onCollapseScope = scope; } me.onRowDeselect(me.indexOf(parent.firstChild)); } }, onCollapse: function(parent) { var me = this, queue = me.animQueue, id = parent.getId(), node = me.getNode(parent), index = node ? me.indexOf(node) : -1, animWrap = me.getAnimWrap(parent), animateEl; if (!me.all.getCount() || !Ext.Array.contains(parent.stores, me.store)) { return; } if (!animWrap) { me.refreshSelection(); parent.isExpandingOrCollapsing = false; me.fireEvent('afteritemcollapse', parent, index, node); me.refreshSize(); Ext.callback(me.onCollapseCallback, me.onCollapseScope); me.onCollapseCallback = me.onCollapseScope = null; return; } animateEl = animWrap.animateEl; queue[id] = true; animateEl.stopAnimation(); animateEl.animate({ to: { height: Ext.isIEQuirks ? 1 : 0 }, duration: me.collapseDuration, listeners: { afteranimate: function() { animWrap.el.remove(); me.refreshSize(); delete me.animWraps[animWrap.record.internalId]; delete queue[id]; } }, callback: function() { me.refreshSelection(); parent.isExpandingOrCollapsing = false; me.fireEvent('afteritemcollapse', parent, index, node); Ext.callback(animWrap.callback, animWrap.scope); animWrap.callback = animWrap.scope = null; } }); animWrap.isAnimating = true; }, isAnimating: function(node) { return !!this.animQueue[node.getId()]; }, expand: function(record, deep, callback, scope) { var me = this, doAnimate = !!me.animate, result; if (!doAnimate || !record.isExpandingOrCollapsing) { if (!record.isLeaf()) { record.isExpandingOrCollapsing = doAnimate; } Ext.suspendLayouts(); result = record.expand(deep, callback, scope); Ext.resumeLayouts(true); return result; } }, collapse: function(record, deep, callback, scope) { var me = this, doAnimate = !!me.animate; if (!doAnimate || !record.isExpandingOrCollapsing) { if (!record.isLeaf()) { record.isExpandingOrCollapsing = doAnimate; } return record.collapse(deep, callback, scope); } }, toggle: function(record, deep, callback, scope) { if (record.isExpanded()) { this.collapse(record, deep, callback, scope); } else { this.expand(record, deep, callback, scope); } }, onItemDblClick: function(record, item, index) { var me = this, editingPlugin = me.editingPlugin; me.callParent(arguments); if (me.toggleOnDblClick && record.isExpandable() && !(editingPlugin && editingPlugin.clicksToEdit === 2)) { me.toggle(record); } }, onBeforeItemMouseDown: function(record, item, index, e) { if (e.getTarget(this.expanderSelector, item)) { return false; } return this.callParent(arguments); }, onItemClick: function(record, item, index, e) { if (e.getTarget(this.expanderSelector, item) && record.isExpandable()) { this.toggle(record, e.ctrlKey); return false; } return this.callParent(arguments); }, onExpanderMouseOver: function(e, t) { e.getTarget(this.cellSelector, 10, true).addCls(this.expanderIconOverCls); }, onExpanderMouseOut: function(e, t) { e.getTarget(this.cellSelector, 10, true).removeCls(this.expanderIconOverCls); }, getStoreListeners: function(){ var me = this, listeners = me.callParent(arguments); return Ext.apply(listeners, { beforeexpand: me.onBeforeExpand, expand: me.onExpand, beforecollapse: me.onBeforeCollapse, collapse: me.onCollapse, write: me.onStoreWrite, datachanged: me.onStoreDataChanged }); }, onBindStore: function(){ var me = this, treeStore = me.getTreeStore(); me.callParent(arguments); me.mon(treeStore, { scope: me, beforefill: me.onBeforeFill, fillcomplete: me.onFillComplete }); if (!treeStore.remoteSort) { me.mon(treeStore, { scope: me, beforesort: me.onBeforeSort, sort: me.onSort }); } }, onUnbindStore: function(){ var me = this, treeStore = me.getTreeStore(); me.callParent(arguments); me.mun(treeStore, { scope: me, beforefill: me.onBeforeFill, fillcomplete: me.onFillComplete }); if (!treeStore.remoteSort) { me.mun(treeStore, { scope: me, beforesort: me.onBeforeSort, sort: me.onSort }); } }, getTreeStore: function() { return this.panel.store; }, ensureSingleExpand: function(node) { var parent = node.parentNode; if (parent) { parent.eachChild(function(child) { if (child !== node && child.isExpanded()) { child.collapse(); } }); } }, shouldUpdateCell: function(record, column, changedFieldNames){ if (changedFieldNames) { var i = 0, len = changedFieldNames.length; for (; i < len; ++i) { if (Ext.Array.contains(this.uiFields, changedFieldNames[i])) { return true; } } } return this.callParent(arguments); }, onStoreWrite: function(store, operation) { var treeStore = this.panel.store; treeStore.fireEvent('write', treeStore, operation); }, onStoreDataChanged: function(store, operation) { var treeStore = this.panel.store; treeStore.fireEvent('datachanged', treeStore); } }); Ext.define('Ext.grid.plugin.BufferedRendererTreeView', { override: 'Ext.tree.View', onRemove: function(store, records, indices) { var me = this; if (me.rendered && me.bufferedRenderer) { me.refreshView(); } else { me.callParent([store, records, indices]); } } }); Ext.define('Ext.grid.plugin.BufferedRenderer', { extend: Ext.AbstractPlugin , alias: 'plugin.bufferedrenderer', lockableScope: 'both', percentageFromEdge: 0.35, variableRowHeight: false, numFromEdge: 8, trailingBufferZone: 10, leadingBufferZone: 20, synchronousRender: true, scrollToLoadBuffer: 200, viewSize: 0, rowHeight: 21, position: 0, lastScrollDirection: 1, bodyTop: 0, init: function(grid) { var me = this, view = grid.view, viewListeners = { scroll: { fn: me.onViewScroll, element: 'el', scope: me }, boxready: me.onViewResize, resize: me.onViewResize, refresh: me.onViewRefresh, scope: me, destroyable: true }; if (!me.variableRowHeight && grid.ownerLockable) { grid.ownerLockable.syncRowHeight = false; } if (grid.isTree || grid.ownerLockable && grid.ownerLockable.isTree) { view.blockRefresh = false; view.loadMask = true; } if (view.positionBody) { viewListeners.refresh = me.onViewRefresh; } me.grid = grid; me.view = view; view.bufferedRenderer = me; view.preserveScrollOnRefresh = true; me.bindStore(view.dataSource); view.getViewRange = function() { return me.getViewRange(); }; me.position = 0; me.gridListeners = grid.on('reconfigure', me.onReconfigure, me); me.viewListeners = view.on(viewListeners); }, bindStore: function(store) { var me = this; if (me.store) { me.unbindStore(); } me.storeListeners = store.on({ scope: me, clear: me.onStoreClear, destroyable: true }); me.store = store; if (me.view.componentLayout.layoutCount) { me.onViewResize(me.view, 0, me.view.getHeight()); } }, onReconfigure: function(grid, store){ if (store && store !== this.store) { this.bindStore(store); } }, unbindStore: function() { this.storeListeners.destroy(); this.store = null; }, onStoreClear: function() { var me = this; if (me.view.rendered && !me.store.isDestroyed) { if (me.scrollTop !== 0) { me.ignoreNextScrollEvent = true; me.view.el.dom.scrollTop = 0; } me.bodyTop = me.scrollTop = me.position = me.scrollHeight = 0; me.lastScrollDirection = me.scrollOffset = null; delete me.rowHeight; } }, onViewRefresh: function() { var me = this, view = me.view, oldScrollHeight = me.scrollHeight, scrollHeight; if (view.all.getCount()) { delete me.rowHeight; } scrollHeight = me.getScrollHeight(); if (!oldScrollHeight || scrollHeight != oldScrollHeight) { me.stretchView(view, scrollHeight); } if (me.scrollTop !== view.el.dom.scrollTop) { me.onViewScroll(); } else { me.setBodyTop(me.bodyTop); if (view.all.getCount()) { me.viewSize = 0; me.onViewResize(view, null, view.getHeight()); } } }, onViewResize: function(view, width, height, oldWidth, oldHeight) { if (!oldHeight || height !== oldHeight) { var me = this, newViewSize; newViewSize = Math.ceil(height / me.rowHeight) + me.trailingBufferZone + me.leadingBufferZone; me.viewSize = me.setViewSize(newViewSize); } }, stretchView: function(view, scrollRange) { var me = this, recordCount = (me.store.buffered ? me.store.getTotalCount() : me.store.getCount()); if (me.stretcher) { me.stretcher.dom.style.marginTop = (scrollRange - 1) + 'px'; } else { var el = view.el; if (view.refreshCounter) { view.fixedNodes++; } if (recordCount && (me.view.all.endIndex === recordCount - 1)) { scrollRange = me.bodyTop + view.body.dom.offsetHeight; } this.stretcher = el.createChild({ style: { width: '1px', height: '1px', 'marginTop': (scrollRange - 1) + 'px', left: 0, position: 'absolute' } }, el.dom.firstChild); } }, setViewSize: function(viewSize) { if (viewSize !== this.viewSize) { this.scrollTop = this.view.el.dom.scrollTop; var me = this, store = me.store, elCount = me.view.all.getCount(), start, end, lockingPartner = me.lockingPartner; me.viewSize = store.viewSize = viewSize; if (elCount) { start = me.view.all.startIndex; end = Math.min(start + viewSize - 1, (store.buffered ? store.getTotalCount() : store.getCount()) - 1); if (lockingPartner) { lockingPartner.disable(); } me.renderRange(start, end); if (lockingPartner) { lockingPartner.enable(); } } } return viewSize; }, getViewRange: function() { var me = this, rows = me.view.all, store = me.store; if (store.data.getCount()) { return store.getRange(rows.startIndex, rows.startIndex + (me.viewSize || store.defaultViewSize) - 1); } else { return []; } }, scrollTo: function(recordIdx, doSelect, callback, scope) { var me = this, view = me.view, viewDom = view.el.dom, store = me.store, total = store.buffered ? store.getTotalCount() : store.getCount(), startIdx, endIdx, targetRec, targetRow, tableTop, groupingFeature, group, record; if ((groupingFeature = view.dataSource.groupingFeature) && (groupingFeature.collapsible !== false)) { recordIdx = Math.min(Math.max(recordIdx, 0), view.store.getCount() - 1); record = view.store.getAt(recordIdx); recordIdx = groupingFeature.indexOf(recordIdx); group = groupingFeature.getGroup(record); if (group.isCollapsed) { groupingFeature.expand(group.name); total = store.buffered ? store.getTotalCount() : store.getCount(); } } else { recordIdx = Math.min(Math.max(recordIdx, 0), total - 1); } startIdx = Math.max(Math.min(recordIdx - ((me.leadingBufferZone + me.trailingBufferZone) / 2), total - me.viewSize + 1), 0); tableTop = startIdx * me.rowHeight; endIdx = Math.min(startIdx + me.viewSize - 1, total - 1); store.getRange(startIdx, endIdx, { callback: function(range, start, end) { me.renderRange(start, end, true); targetRec = store.data.getRange(recordIdx, recordIdx)[0]; targetRow = view.getNode(targetRec, false); view.body.dom.style.top = tableTop + 'px'; me.position = me.scrollTop = viewDom.scrollTop = tableTop = Math.min(Math.max(0, tableTop - view.body.getOffsetsTo(targetRow)[1]), viewDom.scrollHeight - viewDom.clientHeight); if (Ext.isIE) { viewDom.scrollTop = tableTop; } if (doSelect) { view.selModel.select(targetRec); } if (callback) { callback.call(scope||me, recordIdx, targetRec); } } }); }, onViewScroll: function(e, t) { var me = this, store = me.store, totalCount = (store.buffered ? store.getTotalCount() : store.getCount()), vscrollDistance, scrollDirection, scrollTop = me.scrollTop = me.view.el.dom.scrollTop, scrollHandled = false; if (me.ignoreNextScrollEvent) { me.ignoreNextScrollEvent = false; return; } if (!(me.disabled || totalCount < me.viewSize)) { vscrollDistance = scrollTop - me.position; scrollDirection = vscrollDistance > 0 ? 1 : -1; if (Math.abs(vscrollDistance) >= 20 || (scrollDirection !== me.lastScrollDirection)) { me.lastScrollDirection = scrollDirection; me.handleViewScroll(me.lastScrollDirection); scrollHandled = true; } } if (!scrollHandled) { if (me.lockingPartner && me.lockingPartner.scrollTop !== scrollTop) { me.lockingPartner.view.el.dom.scrollTop = scrollTop; } } }, handleViewScroll: function(direction) { var me = this, rows = me.view.all, store = me.store, viewSize = me.viewSize, totalCount = (store.buffered ? store.getTotalCount() : store.getCount()), requestStart, requestEnd; if (direction == -1) { if (rows.startIndex) { if ((me.getFirstVisibleRowIndex() - rows.startIndex) < me.numFromEdge) { requestStart = Math.max(0, me.getLastVisibleRowIndex() + me.trailingBufferZone - viewSize); } } } else { if (rows.endIndex < totalCount - 1) { if ((rows.endIndex - me.getLastVisibleRowIndex()) < me.numFromEdge) { requestStart = Math.max(0, me.getFirstVisibleRowIndex() - me.trailingBufferZone); } } } if (requestStart != null) { requestEnd = Math.min(requestStart + viewSize - 1, totalCount - 1); if (requestStart !== rows.startIndex || requestEnd !== rows.endIndex) { me.renderRange(requestStart, requestEnd); return; } } if (me.lockingPartner && me.lockingPartner.view.el && me.lockingPartner.scrollTop !== me.scrollTop) { me.lockingPartner.view.el.dom.scrollTop = me.scrollTop; } }, renderRange: function(start, end, forceSynchronous) { var me = this, rows = me.view.all, store = me.store; if (!(start === rows.startIndex && end === rows.endIndex)) { if (store.rangeCached(start, end)) { me.cancelLoad(); if (me.synchronousRender || forceSynchronous) { me.onRangeFetched(null, start, end); } else { if (!me.renderTask) { me.renderTask = new Ext.util.DelayedTask(me.onRangeFetched, me, null, false); } me.renderTask.delay(1, null, null, [null, start, end]); } } else { me.attemptLoad(start, end); } } }, onRangeFetched: function(range, start, end, fromLockingPartner) { var me = this, view = me.view, oldStart, rows = view.all, removeCount, increment = 0, calculatedTop = start * me.rowHeight, top, lockingPartner = me.lockingPartner; if (view.isDestroyed) { return; } if (!range) { range = me.store.getRange(start, end); if (!range) { return; } } if (start > rows.endIndex || end < rows.startIndex) { rows.clear(true); top = calculatedTop; } if (!rows.getCount()) { view.doAdd(range, start); } else if (end > rows.endIndex) { removeCount = Math.max(start - rows.startIndex, 0); if (me.variableRowHeight) { increment = rows.item(rows.startIndex + removeCount, true).offsetTop; } rows.scroll(Ext.Array.slice(range, rows.endIndex + 1 - start), 1, removeCount, start, end); if (me.variableRowHeight) { top = me.bodyTop + increment; } else { top = calculatedTop; } } else { removeCount = Math.max(rows.endIndex - end, 0); oldStart = rows.startIndex; rows.scroll(Ext.Array.slice(range, 0, rows.startIndex - start), -1, removeCount, start, end); if (me.variableRowHeight) { top = me.bodyTop - rows.item(oldStart, true).offsetTop; } else { top = calculatedTop; } } me.position = me.scrollTop; if (view.positionBody) { me.setBodyTop(top, calculatedTop); } if (lockingPartner && !lockingPartner.disabled && !fromLockingPartner) { lockingPartner.onRangeFetched(range, start, end, true); if (lockingPartner.scrollTop !== me.scrollTop) { lockingPartner.view.el.dom.scrollTop = me.scrollTop; } } }, setBodyTop: function(bodyTop, calculatedTop) { var me = this, view = me.view, store = me.store, body = view.body.dom, delta; bodyTop = Math.floor(bodyTop); if (calculatedTop !== undefined) { delta = bodyTop - calculatedTop; bodyTop = calculatedTop; } body.style.position = 'absolute'; body.style.top = (me.bodyTop = bodyTop) + 'px'; if (delta) { me.scrollTop = me.position = view.el.dom.scrollTop -= delta; } if (view.all.endIndex === (store.buffered ? store.getTotalCount() : store.getCount()) - 1) { me.stretchView(view, me.bodyTop + body.offsetHeight); } }, getFirstVisibleRowIndex: function(startRow, endRow, viewportTop, viewportBottom) { var me = this, view = me.view, rows = view.all, elements = rows.elements, clientHeight = view.el.dom.clientHeight, target, targetTop; if (rows.getCount() && me.variableRowHeight) { if (!arguments.length) { startRow = rows.startIndex; endRow = rows.endIndex; viewportTop = me.scrollTop; viewportBottom = viewportTop + clientHeight; if (me.bodyTop > viewportBottom || me.bodyTop + view.body.getHeight() < viewportTop) { return Math.floor(me.scrollTop / me.rowHeight); } target = startRow + Math.min(me.numFromEdge + ((me.lastScrollDirection == -1) ? me.leadingBufferZone : me.trailingBufferZone), Math.floor((endRow - startRow) / 2)); } else { target = startRow + Math.floor((endRow - startRow) / 2); } targetTop = me.bodyTop + elements[target].offsetTop; if (targetTop + elements[target].offsetHeight < viewportTop) { return me.getFirstVisibleRowIndex(target + 1, endRow, viewportTop, viewportBottom); } if (targetTop <= viewportTop) { return target; } else if (target !== startRow) { return me.getFirstVisibleRowIndex(startRow, target - 1, viewportTop, viewportBottom); } } return Math.floor(me.scrollTop / me.rowHeight); }, getLastVisibleRowIndex: function(startRow, endRow, viewportTop, viewportBottom) { var me = this, view = me.view, rows = view.all, elements = rows.elements, clientHeight = view.el.dom.clientHeight, target, targetTop, targetBottom; if (rows.getCount() && me.variableRowHeight) { if (!arguments.length) { startRow = rows.startIndex; endRow = rows.endIndex; viewportTop = me.scrollTop; viewportBottom = viewportTop + clientHeight; if (me.bodyTop > viewportBottom || me.bodyTop + view.body.getHeight() < viewportTop) { return Math.floor(me.scrollTop / me.rowHeight) + Math.ceil(clientHeight / me.rowHeight); } target = endRow - Math.min(me.numFromEdge + ((me.lastScrollDirection == 1) ? me.leadingBufferZone : me.trailingBufferZone), Math.floor((endRow - startRow) / 2)); } else { target = startRow + Math.floor((endRow - startRow) / 2); } targetTop = me.bodyTop + elements[target].offsetTop; if (targetTop > viewportBottom) { return me.getLastVisibleRowIndex(startRow, target - 1, viewportTop, viewportBottom); } targetBottom = targetTop + elements[target].offsetHeight; if (targetBottom >= viewportBottom) { return target; } else if (target !== endRow) { return me.getLastVisibleRowIndex(target + 1, endRow, viewportTop, viewportBottom); } } return me.getFirstVisibleRowIndex() + Math.ceil(clientHeight / me.rowHeight); }, getScrollHeight: function() { var me = this, view = me.view, store = me.store, doCalcHeight = !me.hasOwnProperty('rowHeight'), storeCount = me.store.getCount(); if (!storeCount) { return 0; } if (doCalcHeight) { if (view.all.getCount()) { me.rowHeight = Math.floor(view.body.getHeight() / view.all.getCount()); } } return this.scrollHeight = Math.floor((store.buffered ? store.getTotalCount() : store.getCount()) * me.rowHeight); }, attemptLoad: function(start, end) { var me = this; if (me.scrollToLoadBuffer) { if (!me.loadTask) { me.loadTask = new Ext.util.DelayedTask(me.doAttemptLoad, me, []); } me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]); } else { me.store.getRange(start, end, { callback: me.onRangeFetched, scope: me, fireEvent: false }); } }, cancelLoad: function() { if (this.loadTask) { this.loadTask.cancel(); } }, doAttemptLoad: function(start, end) { this.store.getRange(start, end, { callback: this.onRangeFetched, scope: this, fireEvent: false }); }, destroy: function() { var me = this, view = me.view; if (view && view.el) { view.el.un('scroll', me.onViewScroll, me); } Ext.destroy(me.viewListeners, me.storeListeners, me.gridListeners); } }); Ext.define('Ext.grid.plugin.Editing', { alias: 'editing.editing', extend: Ext.AbstractPlugin , mixins: { observable: Ext.util.Observable }, clicksToEdit: 2, triggerEvent: undefined, relayedEvents: [ 'beforeedit', 'edit', 'validateedit', 'canceledit' ], defaultFieldXType: 'textfield', editStyle: '', constructor: function(config) { var me = this; me.addEvents( 'beforeedit', 'edit', 'validateedit', 'canceledit' ); me.callParent(arguments); me.mixins.observable.constructor.call(me); me.on("edit", function(editor, e) { me.fireEvent("afteredit", editor, e); }); }, init: function(grid) { var me = this; me.grid = grid; me.view = grid.view; me.initEvents(); me.mon(grid, { beforereconfigure: me.onBeforeReconfigure, reconfigure: me.onReconfigure, scope: me, beforerender: { fn: me.onReconfigure, single: true, scope: me } }); grid.relayEvents(me, me.relayedEvents); if (me.grid.ownerLockable) { me.grid.ownerLockable.relayEvents(me, me.relayedEvents); } grid.isEditable = true; grid.editingPlugin = grid.view.editingPlugin = me; }, onBeforeReconfigure: function() { this.reconfiguring = true; }, onReconfigure: function() { this.initFieldAccessors(this.grid.getTopLevelColumnManager().getColumns()); delete this.reconfiguring; }, destroy: function() { var me = this, grid = me.grid; Ext.destroy(me.keyNav); me.clearListeners(); if (grid) { grid.editingPlugin = grid.view.editingPlugin = me.grid = me.view = me.editor = me.keyNav = null; } }, getEditStyle: function() { return this.editStyle; }, initFieldAccessors: function(columns) { if (columns.isGroupHeader) { columns = columns.getGridColumns(); } else if (!Ext.isArray(columns)) { columns = [columns]; } var me = this, c, cLen = columns.length, column; for (c = 0; c < cLen; c++) { column = columns[c]; if (!column.getEditor) { column.getEditor = function(record, defaultField) { return me.getColumnField(this, defaultField); }; } if (!column.hasEditor) { column.hasEditor = function() { return me.hasColumnField(this); }; } if (!column.setEditor) { column.setEditor = function(field) { me.setColumnField(this, field); }; } } }, removeFieldAccessors: function(columns) { if (columns.isGroupHeader) { columns = columns.getGridColumns(); } else if (!Ext.isArray(columns)) { columns = [columns]; } var c, cLen = columns.length, column; for (c = 0; c < cLen; c++) { column = columns[c]; column.getEditor = column.hasEditor = column.setEditor = null; } }, getColumnField: function(columnHeader, defaultField) { var field = columnHeader.field; if (!(field && field.isFormField)) { field = columnHeader.field = this.createColumnField(columnHeader, defaultField); } return field; }, hasColumnField: function(columnHeader) { return !!columnHeader.field; }, setColumnField: function(columnHeader, field) { columnHeader.field = field; columnHeader.field = this.createColumnField(columnHeader); }, createColumnField: function(columnHeader, defaultField) { var field = columnHeader.field; if (!field && columnHeader.editor) { field = columnHeader.editor; columnHeader.editor = null; } if (!field && defaultField) { field = defaultField; } if (field) { if (field.isComponent) { field.column = columnHeader; field.isEditorComponent = true; } else { if (Ext.isString(field)) { field = { name: columnHeader.dataIndex, xtype: field, column: columnHeader, isEditorComponent: true }; } else { field = Ext.apply({ name: columnHeader.dataIndex, column: columnHeader, isEditorComponent: true }, field); } field = Ext.ComponentManager.create(field, this.defaultFieldXType); } columnHeader.field = field; } return field; }, initEvents: function() { var me = this; me.initEditTriggers(); me.initLockableEvents(); me.initCancelTriggers(); }, initCancelTriggers: Ext.emptyFn, initEditTriggers: function() { var me = this, view = me.view; if (me.triggerEvent == 'cellfocus') { me.mon(view, 'cellfocus', me.onCellFocus, me); } else if (me.triggerEvent == 'rowfocus') { me.mon(view, 'rowfocus', me.onRowFocus, me); } else { if (view.getSelectionModel().isCellModel) { view.onCellFocus = Ext.Function.bind(me.beforeViewCellFocus, me); } me.mon(view, me.triggerEvent || ('cell' + (me.clicksToEdit === 1 ? 'click' : 'dblclick')), me.onCellClick, me); } me.initAddRemoveHeaderEvents(); view.on('render', me.initKeyNavHeaderEvents, me, {single: true}); }, initLockableEvents: function() { var me = this, grid = me.grid.ownerLockable; if (grid) { grid.on({ lockcolumn: me.onColumnLockUnlock, unlockcolumn: me.onColumnLockUnlock, scope: me }); } }, beforeViewCellFocus: function(position) { if (this.view.selModel.keyNavigation || !this.editing || !this.isCellEditable || !this.isCellEditable(position.row, position.columnHeader)) { this.view.focusCell.apply(this.view, arguments); } }, onRowFocus: function(record, row, rowIdx) { this.startEdit(row, 0); }, onCellFocus: function(record, cell, position) { this.startEdit(position.row, position.column); }, onCellClick: function(view, cell, colIdx, record, row, rowIdx, e) { var expanderSelector = view.expanderSelector, columnHeader = view.ownerCt.getColumnManager().getHeaderAtIndex(colIdx), editor = columnHeader.getEditor(record); if (editor && !expanderSelector || !e.getTarget(expanderSelector)) { this.startEdit(record, columnHeader); } }, initAddRemoveHeaderEvents: function(){ var me = this; me.mon(me.grid.headerCt, { scope: me, add: me.onColumnAdd, remove: me.onColumnRemove, columnmove: me.onColumnMove }); }, initKeyNavHeaderEvents: function() { var me = this; me.keyNav = Ext.create('Ext.util.KeyNav', me.view.el, { enter: me.onEnterKey, esc: me.onEscKey, scope: me }); }, onColumnAdd: function(ct, column) { this.initFieldAccessors(column); }, onColumnRemove: function(ct, column) { this.removeFieldAccessors(column); }, onColumnMove: function(headerCt, column, fromIdx, toIdx) { this.initFieldAccessors(column); }, onColumnLockUnlock: function(view, column) { this.initFieldAccessors(column); }, onEnterKey: function(e) { var me = this, grid = me.grid, selModel = grid.getSelectionModel(), record, pos, columnHeader; if (selModel.getCurrentPosition && (pos = selModel.getCurrentPosition())) { record = pos.record; columnHeader = pos.columnHeader; } else { record = selModel.getLastSelected(); columnHeader = grid.getColumnManager().getHeaderAtIndex(0); } if (record && columnHeader) { me.startEdit(record, columnHeader); } }, onEscKey: function(e) { return this.cancelEdit(); }, beforeEdit: Ext.emptyFn, startEdit: function(record, columnHeader) { var me = this, context, layoutView = me.grid.lockable ? me.grid : me.view; if (!layoutView.componentLayoutCounter) { layoutView.on({ boxready: Ext.Function.bind(me.startEdit, me, [record, columnHeader]), single: true }); return false; } if (me.grid.collapsed || !me.grid.view.isVisible(true)) { return false; } context = me.getEditingContext(record, columnHeader); if (context == null) { return false; } if (!me.preventBeforeCheck) { if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', me, context) === false || context.cancel) { return false; } } return context; }, getEditingContext: function(record, columnHeader) { var me = this, grid = me.grid, colMgr = grid.getColumnManager(), view, gridRow, rowIdx, colIdx; if (Ext.isNumber(columnHeader)) { columnHeader = colMgr.getHeaderAtIndex(columnHeader); } if (columnHeader.hidden) { columnHeader = columnHeader.next(':not([hidden])') || columnHeader.prev(':not([hidden])'); } if (!columnHeader) { return; } view = columnHeader.getOwnerHeaderCt().view; gridRow = view.getNode(record, true); if (!gridRow) { return; } colIdx = colMgr.getHeaderIndex(columnHeader); if (Ext.isNumber(record)) { rowIdx = record; record = view.getRecord(gridRow); } else { rowIdx = view.indexOf(gridRow); } if (!record) { return; } return { grid : grid, view : view, store : view.dataSource, record : record, field : columnHeader.dataIndex, value : record.get(columnHeader.dataIndex), row : gridRow, column : columnHeader, rowIdx : rowIdx, colIdx : colIdx }; }, cancelEdit: function() { var me = this; me.editing = false; me.fireEvent('canceledit', me, me.context); }, completeEdit: function() { var me = this; if (me.editing && me.validateEdit()) { me.fireEvent('edit', me, me.context); } me.context = null; me.editing = false; }, validateEdit: function() { var me = this, context = me.context; return me.fireEvent('validateedit', me, context) !== false && !context.cancel; } }); Ext.define('Ext.grid.plugin.CellEditing', { alias: 'plugin.cellediting', extend: Ext.grid.plugin.Editing , lockableScope: 'both', init: function(grid) { var me = this, lockingPartner = me.lockingPartner; me.callParent(arguments); if (lockingPartner) { if (lockingPartner.editors) { me.editors = lockingPartner.editors; } else { me.editors = lockingPartner.editors = new Ext.util.MixedCollection(false, function(editor) { return editor.editorId; }); } } else { me.editors = new Ext.util.MixedCollection(false, function(editor) { return editor.editorId; }); } }, onReconfigure: function(grid, store, columns){ if (columns) { this.editors.clear(); } this.callParent(); }, destroy: function() { var me = this; if (me.editors) { me.editors.each(Ext.destroy, Ext); me.editors.clear(); } me.callParent(arguments); }, onBodyScroll: function() { var me = this, ed = me.getActiveEditor(), scroll = me.view.el.getScroll(); if (ed && ed.editing && ed.editingPlugin === me) { if (scroll.top !== me.scroll.top) { if (ed.field) { if (ed.field.triggerBlur) { ed.field.triggerBlur(); } else { ed.field.blur(); } } } else { ed.realign(); } } me.scroll = scroll; }, initCancelTriggers: function() { var me = this, grid = me.grid, view = grid.view; me.mon(view, 'bodyscroll', me.onBodyScroll, me); me.mon(grid, { columnresize: me.cancelEdit, columnmove: me.cancelEdit, scope: me }); }, isCellEditable: function(record, columnHeader) { var me = this, context = me.getEditingContext(record, columnHeader); if (me.grid.view.isVisible(true) && context) { columnHeader = context.column; record = context.record; if (columnHeader && me.getEditor(record, columnHeader)) { return true; } } }, startEdit: function(record, columnHeader, context) { var me = this, isEditorEditing, isFieldEditable, ed; if (!context) { me.preventBeforeCheck = true; context = me.callParent(arguments); delete me.preventBeforeCheck; if (context === false) { return false; } } if (context && me.grid.view.isVisible(true)) { record = context.record; columnHeader = context.column; isFieldEditable = (columnHeader && columnHeader.getEditor(record)) && !(me.beforeEdit(context) === false || me.fireEvent('beforeedit', me, context) === false || context.cancel); if (isFieldEditable) { ed = me.getEditor(record, columnHeader); isEditorEditing = ed.editing; } me.completeEdit(); if (!isFieldEditable) { return false; } me.context = context; context.originalValue = context.value = record.get(columnHeader.dataIndex); me.grid.view.cancelFocus(); me.view.scrollCellIntoView(me.getCell(record, columnHeader)); if (ed) { if (Ext.isIE && isEditorEditing) { ed.selectSameEditor = true; } me.showEditor(ed, context, context.value); return true; } return false; } }, showEditor: function(ed, context, value) { var me = this, record = context.record, columnHeader = context.column, sm = me.grid.getSelectionModel(), preventFocus = sm.preventFocus, selection = sm.getCurrentPosition(); if (!columnHeader.up(me.view.ownerCt)) { return me.lockingPartner.showEditor(ed, me.lockingPartner.getEditingContext(selection.record, selection.columnHeader), value); } me.setEditingContext(context); me.setActiveEditor(ed); me.setActiveRecord(record); me.setActiveColumn(columnHeader); if (!selection || !sm.isCellSelected(me.view, record, columnHeader)) { sm.preventFocus = true; sm.selectByPosition({ row: record, column: columnHeader, view: me.view }); sm.preventFocus = preventFocus; } if (Ext.isIE && Ext.EventObject.type === 'click') { Ext.Function.defer(ed.startEdit, 1, ed, [me.getCell(record, columnHeader), value, context]); } else { ed.startEdit(me.getCell(record, columnHeader), value, context); } me.editing = true; me.scroll = me.view.el.getScroll(); }, completeEdit: function() { var activeEd = this.getActiveEditor(); if (activeEd) { activeEd.completeEdit(); this.editing = false; } }, setEditingContext: function(context) { this.context = context; if (this.lockingPartner) { this.lockingPartner.context = context; } }, setActiveEditor: function(ed) { this.activeEditor = ed; if (this.lockingPartner) { this.lockingPartner.activeEditor = ed; } }, getActiveEditor: function() { return this.activeEditor; }, setActiveColumn: function(column) { this.activeColumn = column; if (this.lockingPartner) { this.lockingPartner.activeColumn = column; } }, getActiveColumn: function() { return this.activeColumn; }, setActiveRecord: function(record) { this.activeRecord = record; if (this.lockingPartner) { this.lockingPartner.activeRecord = record; } }, getActiveRecord: function() { return this.activeRecord; }, getEditor: function(record, column) { var me = this, editors = me.editors, editorId = column.getItemId(), editor = editors.getByKey(editorId), editorOwner = me.grid.ownerLockable || me.grid; if (!editor) { editor = column.getEditor(record); if (!editor) { return false; } if (editor instanceof Ext.grid.CellEditor) { editor.floating = true; } else { editor = new Ext.grid.CellEditor({ floating: true, editorId: editorId, field: editor }); } editor.field.excludeForm = true; editorOwner.add(editor); editor.on({ scope: me, specialkey: me.onSpecialKey, complete: me.onEditComplete, canceledit: me.cancelEdit }); column.on('removed', me.cancelActiveEdit, me); editors.add(editor); } if (column.isTreeColumn) { editor.isForTree = column.isTreeColumn; editor.addCls(Ext.baseCSSPrefix + 'tree-cell-editor'); } editor.grid = me.grid; editor.editingPlugin = me; return editor; }, cancelActiveEdit: function(column){ var context = this.context; if (context && context.column === column) { this.cancelEdit(); } }, setColumnField: function(column, field) { var ed = this.editors.getByKey(column.getItemId()); Ext.destroy(ed, column.field); this.editors.removeAtKey(column.getItemId()); this.callParent(arguments); }, getCell: function(record, column) { return this.grid.getView().getCell(record, column); }, onSpecialKey: function(ed, field, e) { var sm; if (e.getKey() === e.TAB) { e.stopEvent(); if (ed) { ed.onEditorTab(e); } sm = ed.up('tablepanel').getSelectionModel(); if (sm.onEditorTab) { return sm.onEditorTab(ed.editingPlugin, e); } } }, onEditComplete : function(ed, value, startValue) { var me = this, activeColumn = me.getActiveColumn(), context = me.context, record; if (activeColumn) { record = context.record; me.setActiveEditor(null); me.setActiveColumn(null); me.setActiveRecord(null); context.value = value; if (!me.validateEdit()) { me.editing = false; return; } if (!record.isEqual(value, startValue)) { record.set(activeColumn.dataIndex, value); } context.view.focusRow(context.rowIdx, 100); me.fireEvent('edit', me, context); me.editing = false; } }, cancelEdit: function() { var me = this, context = me.context, activeEd = me.getActiveEditor(); me.setActiveEditor(null); me.setActiveColumn(null); me.setActiveRecord(null); if (activeEd) { if (activeEd.field) { me.context.value = ('editedValue' in activeEd) ? activeEd.editedValue : activeEd.getValue(); activeEd.cancelEdit(); } context.view.focusRow(context.rowIdx, 100); me.callParent(arguments); return; } return true; }, startEditByPosition: function(position) { var cm = this.grid.getColumnManager(), index, col; if (!position.isCellContext) { position = new Ext.grid.CellContext(this.view).setPosition(position); } index = cm.getHeaderIndex(position.columnHeader); position.setColumn(cm.getVisibleHeaderClosestToIndex(index)); return this.startEdit(position.record, position.columnHeader); } }); Ext.define('Ext.grid.plugin.DivRenderer', { alias: 'plugin.divrenderer', extend: Ext.AbstractPlugin , tableTpl: [ '
    ', '{%', 'values.view.renderRows(values.rows, values.viewStartIndex, out);', '%}', '
    ', { priority: 0 } ], rowTpl: [ '{%', 'var dataRowCls = values.recordIndex === -1 ? "" : " ' + Ext.baseCSSPrefix + 'grid-data-row";', '%}', '
    ', '' + '{%', 'parent.view.renderCell(values, parent.record, parent.recordIndex, xindex - 1, out, parent)', '%}', '', '
    ', { priority: 0 } ], cellTpl: [ '
    ', '
    {style}" {ariaCellInnerAttr}>{value}
    ', '
    ', { priority: 0 } ], selectors: { bodySelector: 'div', nodeContainerSelector: 'div', itemSelector: 'dl.' + Ext.baseCSSPrefix + 'grid-row', dataRowSelector: 'dl.' + Ext.baseCSSPrefix + 'grid-data-row', cellSelector: 'dt.' + Ext.baseCSSPrefix + 'grid-cell', innerSelector: 'div.' + Ext.baseCSSPrefix + 'grid-cell-inner', getNodeContainerSelector: function() { return this.getBodySelector(); }, getNodeContainer: function() { return this.el.getById(this.id + '-table', true); } }, init: function(grid) { var view = grid.getView(); view.tableTpl = Ext.XTemplate.getTpl(this, 'tableTpl'); view.rowTpl = Ext.XTemplate.getTpl(this, 'rowTpl'); view.cellTpl = Ext.XTemplate.getTpl(this, 'cellTpl'); Ext.apply(view, this.selectors); } }); Ext.define('Ext.grid.plugin.DragDrop', { extend: Ext.AbstractPlugin , alias: 'plugin.gridviewdragdrop', dragText : '{0} selected row{1}', ddGroup : "GridDD", enableDrop: true, enableDrag: true, containerScroll: false, init : function(view) { view.on('render', this.onViewRender, this, {single: true}); }, destroy: function() { Ext.destroy(this.dragZone, this.dropZone); }, enable: function() { var me = this; if (me.dragZone) { me.dragZone.unlock(); } if (me.dropZone) { me.dropZone.unlock(); } me.callParent(); }, disable: function() { var me = this; if (me.dragZone) { me.dragZone.lock(); } if (me.dropZone) { me.dropZone.lock(); } me.callParent(); }, onViewRender : function(view) { var me = this, scrollEl; if (me.enableDrag) { if (me.containerScroll) { scrollEl = view.getEl(); } me.dragZone = new Ext.view.DragZone({ view: view, ddGroup: me.dragGroup || me.ddGroup, dragText: me.dragText, containerScroll: me.containerScroll, scrollEl: scrollEl }); } if (me.enableDrop) { me.dropZone = new Ext.grid.ViewDropZone({ view: view, ddGroup: me.dropGroup || me.ddGroup }); } } }); Ext.define('Ext.grid.plugin.RowEditing', { extend: Ext.grid.plugin.Editing , alias: 'plugin.rowediting', lockableScope: 'top', editStyle: 'row', autoCancel: true, errorSummary: true, constructor: function() { var me = this; me.callParent(arguments); if (!me.clicksToMoveEditor) { me.clicksToMoveEditor = me.clicksToEdit; } me.autoCancel = !!me.autoCancel; }, destroy: function() { Ext.destroy(this.editor); this.callParent(arguments); }, onBeforeReconfigure: function() { this.callParent(arguments); this.cancelEdit(); }, onReconfigure: function(grid, store, columns) { var ed = this.editor; this.callParent(arguments); if (columns && ed && ed.rendered) { ed.needsSyncFieldWidths = true; } }, startEdit: function(record, columnHeader) { var me = this, editor = me.getEditor(), context; if (Ext.isEmpty(columnHeader)) { columnHeader = me.grid.getTopLevelVisibleColumnManager().getHeaderAtIndex(0); } if (editor.beforeEdit() !== false) { context = me.callParent([record, columnHeader]); if (context) { me.context = context; if (me.lockingPartner) { me.lockingPartner.cancelEdit(); } editor.startEdit(context.record, context.column, context); me.editing = true; return true; } } return false; }, cancelEdit: function() { var me = this; if (me.editing) { me.getContextFieldValues(); me.getEditor().cancelEdit(); me.callParent(arguments); return; } return true; }, completeEdit: function() { var me = this; if (me.editing && me.validateEdit()) { me.editing = false; me.fireEvent('edit', me, me.context); } }, onEnterKey: function() { if (this.getEditor().getForm().isValid()) { this.completeEdit(); } }, validateEdit: function() { this.getContextFieldValues(); this.editing = this.callParent(arguments) && this.getEditor().completeEdit(); return this.editing; }, getEditor: function() { var me = this; if (!me.editor) { me.editor = me.initEditor(); } return me.editor; }, getContextFieldValues: function () { var editor = this.editor, context = this.context, record = context.record, newValues = {}, originalValues = {}, editors = editor.query('>[isFormField]'), len = editors.length, i, name, item; for (i = 0; i < len; i++) { item = editors[i]; name = item.name; newValues[name] = item.getValue(); originalValues[name] = record.get(name); } Ext.apply(context, { newValues : newValues, originalValues : originalValues }); }, initEditor: function() { return new Ext.grid.RowEditor(this.initEditorConfig()); }, initEditorConfig: function(){ var me = this, grid = me.grid, view = me.view, headerCt = grid.headerCt, btns = ['saveBtnText', 'cancelBtnText', 'errorsText', 'dirtyText'], b, bLen = btns.length, cfg = { autoCancel: me.autoCancel, errorSummary: me.errorSummary, fields: headerCt.getGridColumns(), hidden: true, view: view, editingPlugin: me }, item; for (b = 0; b < bLen; b++) { item = btns[b]; if (Ext.isDefined(me[item])) { cfg[item] = me[item]; } } return cfg; }, initEditTriggers: function() { var me = this, view = me.view, moveEditorEvent = me.clicksToMoveEditor === 1 ? 'click' : 'dblclick'; me.callParent(arguments); if (me.clicksToMoveEditor !== me.clicksToEdit) { me.mon(view, 'cell' + moveEditorEvent, me.moveEditorByClick, me); } view.on({ render: function() { me.mon(me.grid.headerCt, { scope: me, columnresize: me.onColumnResize, columnhide: me.onColumnHide, columnshow: me.onColumnShow }); }, single: true }); }, startEditByClick: function() { var me = this; if (!me.editing || me.clicksToMoveEditor === me.clicksToEdit) { me.callParent(arguments); } }, moveEditorByClick: function() { var me = this; if (me.editing) { me.superclass.onCellClick.apply(me, arguments); } }, onColumnAdd: function(ct, column) { if (column.isHeader) { var me = this, editor; me.initFieldAccessors(column); editor = me.editor; if (editor) { editor.onColumnAdd(column); } } }, onColumnRemove: function(ct, column) { if (column.isHeader) { var me = this, editor = me.getEditor(); if (editor) { editor.onColumnRemove(ct, column); } me.removeFieldAccessors(column); } }, onColumnResize: function(ct, column, width) { if (column.isHeader) { var me = this, editor = me.getEditor(); if (editor) { editor.onColumnResize(column, width); } } }, onColumnHide: function(ct, column) { var me = this, editor = me.getEditor(); if (editor) { editor.onColumnHide(column); } }, onColumnShow: function(ct, column) { var me = this, editor = me.getEditor(); if (editor) { editor.onColumnShow(column); } }, onColumnMove: function(ct, column, fromIdx, toIdx) { var me = this, editor = me.getEditor(); me.initFieldAccessors(column); if (editor) { editor.onColumnMove(column, fromIdx, toIdx); } }, setColumnField: function(column, field) { var me = this, editor = me.getEditor(); if (editor) { editor.removeColumnEditor(column, true); } me.callParent(arguments); if (editor) { editor.insertColumnEditor(column); } }, createColumnField: function(column, defaultField) { var editor = this.editor, def; if (editor) { def = editor.getDefaultFieldCfg(); } return this.callParent([column, defaultField || def]); } }); Ext.define('Ext.grid.plugin.RowExpander', { extend: Ext.AbstractPlugin , lockableScope: 'normal', alias: 'plugin.rowexpander', rowBodyTpl: null, expandOnEnter: true, expandOnDblClick: true, selectRowOnExpand: false, rowBodyTrSelector: '.' + Ext.baseCSSPrefix + 'grid-rowbody-tr', rowBodyHiddenCls: Ext.baseCSSPrefix + 'grid-row-body-hidden', rowCollapsedCls: Ext.baseCSSPrefix + 'grid-row-collapsed', addCollapsedCls: { before: function(values, out) { var me = this.rowExpander; if (!me.recordsExpanded[values.record.internalId]) { values.itemClasses.push(me.rowCollapsedCls); } }, priority: 500 }, setCmp: function(grid) { var me = this, rowBodyTpl, features; me.callParent(arguments); me.recordsExpanded = {}; me.rowBodyTpl = Ext.XTemplate.getTpl(me, 'rowBodyTpl'); rowBodyTpl = this.rowBodyTpl; features = [{ ftype: 'rowbody', lockableScope: 'normal', recordsExpanded: me.recordsExpanded, rowBodyHiddenCls: me.rowBodyHiddenCls, rowCollapsedCls: me.rowCollapsedCls, setupRowData: me.getRowBodyFeatureData, setup: me.setup, getRowBodyContents: function(record) { return rowBodyTpl.applyTemplate(record.getData()); } },{ ftype: 'rowwrap', lockableScope: 'normal' }]; if (grid.features) { grid.features = Ext.Array.push(features, grid.features); } else { grid.features = features; } }, init: function(grid) { var me = this, reconfigurable = grid, view, normalView, lockedView; if (grid.lockable) { grid = grid.lockedGrid; } me.callParent(arguments); me.grid = grid; view = me.view = grid.getView(); me.addExpander(); me.bindView(view); view.addRowTpl(me.addCollapsedCls).rowExpander = me; if (grid.ownerLockable) { reconfigurable = grid.ownerLockable; reconfigurable.syncRowHeight = false; lockedView = reconfigurable.lockedGrid.getView(); me.bindView(lockedView); lockedView.addRowTpl(me.addCollapsedCls).rowExpander = me; reconfigurable.mon(reconfigurable, 'columnschanged', me.refreshRowHeights, me); reconfigurable.mon(reconfigurable.store, 'datachanged', me.refreshRowHeights, me); } reconfigurable.on('beforereconfigure', me.beforeReconfigure, me); if (grid.ownerLockable && !grid.rowLines) { view.on('rowfocus', me.refreshRowHeights, me); } }, beforeReconfigure: function(grid, store, columns, oldStore, oldColumns) { var expander = this.getHeaderConfig(); expander.locked = true; columns.unshift(expander); }, addExpander: function() { var me = this, expanderGrid = me.grid, expanderHeader = me.getHeaderConfig(); if (expanderGrid.ownerLockable) { expanderGrid = expanderGrid.ownerLockable.lockedGrid; expanderGrid.width += expanderHeader.width; } expanderGrid.headerCt.insert(0, expanderHeader); expanderGrid.getSelectionModel().injectCheckbox = 1; }, getRowBodyFeatureData: function(record, idx, rowValues) { var me = this; me.self.prototype.setupRowData.apply(me, arguments); rowValues.rowBody = me.getRowBodyContents(record); rowValues.rowBodyCls = me.recordsExpanded[record.internalId] ? '' : me.rowBodyHiddenCls; }, setup: function(rows, rowValues){ var me = this; me.self.prototype.setup.apply(me, arguments); if (!me.grid.ownerLockable) { rowValues.rowBodyColspan -= 1; } }, bindView: function(view) { if (this.expandOnEnter) { view.on('itemkeydown', this.onKeyDown, this); } if (this.expandOnDblClick) { view.on('itemdblclick', this.onDblClick, this); } }, onKeyDown: function(view, record, row, rowIdx, e) { if (e.getKey() == e.ENTER) { var ds = view.store, sels = view.getSelectionModel().getSelection(), ln = sels.length, i = 0; for (; i < ln; i++) { rowIdx = ds.indexOf(sels[i]); this.toggleRow(rowIdx, sels[i]); } } }, onDblClick: function(view, record, row, rowIdx, e) { this.toggleRow(rowIdx, record); }, toggleRow: function(rowIdx, record) { var me = this, view = me.view, rowNode = view.getNode(rowIdx), row = Ext.fly(rowNode, '_rowExpander'), nextBd = row.down(me.rowBodyTrSelector, true), isCollapsed = row.hasCls(me.rowCollapsedCls), addOrRemoveCls = isCollapsed ? 'removeCls' : 'addCls', ownerLock, rowHeight, fireView; Ext.suspendLayouts(); row[addOrRemoveCls](me.rowCollapsedCls); Ext.fly(nextBd)[addOrRemoveCls](me.rowBodyHiddenCls); me.recordsExpanded[record.internalId] = isCollapsed; view.refreshSize(); if (me.grid.ownerLockable) { ownerLock = me.grid.ownerLockable; fireView = ownerLock.getView(); view = ownerLock.lockedGrid.view; rowHeight = row.getHeight(); row.setHeight(isCollapsed ? rowHeight : ''); row = Ext.fly(view.getNode(rowIdx), '_rowExpander'); row.setHeight(isCollapsed ? rowHeight : ''); row[addOrRemoveCls](me.rowCollapsedCls); view.refreshSize(); } else { fireView = view; } fireView.fireEvent(isCollapsed ? 'expandbody' : 'collapsebody', row.dom, record, nextBd); Ext.resumeLayouts(true); }, refreshRowHeights: function() { Ext.globalEvents.on({ idle: this.doRefreshRowHeights, scope: this, single: true }); }, doRefreshRowHeights: function() { var me = this, recordsExpanded = me.recordsExpanded, key, record, lockedView = me.grid.ownerLockable.lockedGrid.view, normalView = me.grid.ownerLockable.normalGrid.view, normalRow, lockedRow, lockedHeight, normalHeight; for (key in recordsExpanded) { if (recordsExpanded.hasOwnProperty(key)) { record = this.view.store.data.get(key); lockedRow = lockedView.getNode(record, false); normalRow = normalView.getNode(record, false); lockedRow.style.height = normalRow.style.height = ''; lockedHeight = lockedRow.offsetHeight; normalHeight = normalRow.offsetHeight; if (normalHeight > lockedHeight) { lockedRow.style.height = normalHeight + 'px'; } else if (lockedHeight > normalHeight) { normalRow.style.height = lockedHeight + 'px'; } } } }, getHeaderConfig: function() { var me = this; return { width: 24, lockable: false, sortable: false, resizable: false, draggable: false, hideable: false, menuDisabled: true, tdCls: Ext.baseCSSPrefix + 'grid-cell-special', innerCls: Ext.baseCSSPrefix + 'grid-cell-inner-row-expander', renderer: function(value, metadata) { if (!me.grid.ownerLockable) { metadata.tdAttr += ' rowspan="2"'; } return ''; }, processEvent: function(type, view, cell, rowIndex, cellIndex, e, record) { if (type == "mousedown" && e.getTarget('.' + Ext.baseCSSPrefix + 'grid-row-expander')) { me.toggleRow(rowIndex, record); return me.selectRowOnExpand; } } }; } }); Ext.define('Ext.grid.property.Grid', { extend: Ext.grid.Panel , alias: 'widget.propertygrid', alternateClassName: 'Ext.grid.PropertyGrid', valueField: 'value', nameField: 'name', inferTypes: true, enableColumnMove: false, columnLines: true, stripeRows: false, trackMouseOver: false, clicksToEdit: 1, enableHdMenu: false, gridCls: Ext.baseCSSPrefix + 'property-grid', initComponent : function() { var me = this; me.source = me.source || {}; me.addCls(me.gridCls); me.plugins = me.plugins || []; me.plugins.push(new Ext.grid.plugin.CellEditing({ clicksToEdit: me.clicksToEdit, startEdit: function(record, column) { return this.self.prototype.startEdit.call(this, record, me.valueColumn); } })); me.selModel = { selType: 'cellmodel', onCellSelect: function(position) { position.columnHeader = me.valueColumn; position.column = me.valueColumn.getVisibleIndex(); return this.self.prototype.onCellSelect.call(this, position); } }; me.sourceConfig = Ext.apply({}, me.sourceConfig); if (!me.store) { me.propStore = me.store = new Ext.grid.property.Store(me, me.source); } me.configure(me.sourceConfig); if (me.sortableColumns) { me.store.sort('name', 'ASC'); } me.columns = new Ext.grid.property.HeaderContainer(me, me.store); me.addEvents( 'beforepropertychange', 'propertychange' ); me.callParent(); me.getView().walkCells = this.walkCells; me.editors = { 'date' : new Ext.grid.CellEditor({ field: new Ext.form.field.Date({selectOnFocus: true})}), 'string' : new Ext.grid.CellEditor({ field: new Ext.form.field.Text({selectOnFocus: true})}), 'number' : new Ext.grid.CellEditor({ field: new Ext.form.field.Number({selectOnFocus: true})}), 'boolean' : new Ext.grid.CellEditor({ field: new Ext.form.field.ComboBox({ editable: false, store: [[ true, me.headerCt.trueText ], [false, me.headerCt.falseText ]] })}) }; me.store.on('update', me.onUpdate, me); }, configure: function(config){ var me = this, store = me.store, i = 0, len = me.store.getCount(), nameField = me.nameField, valueField = me.valueField, name, value, rec, type; me.configureLegacy(config); if (me.inferTypes) { for (; i < len; ++i) { rec = store.getAt(i); name = rec.get(nameField); if (!me.getConfig(name, 'type')) { value = rec.get(valueField); if (Ext.isDate(value)) { type = 'date'; } else if (Ext.isNumber(value)) { type = 'number'; } else if (Ext.isBoolean(value)) { type = 'boolean'; } else { type = 'string'; } me.setConfig(name, 'type', type); } } } }, getConfig: function(fieldName, key, defaultValue) { var config = this.sourceConfig[fieldName], out; if (config) { out = config[key]; } return out || defaultValue; }, setConfig: function(fieldName, key, value) { var sourceCfg = this.sourceConfig, o = sourceCfg[fieldName]; if (!o) { o = sourceCfg[fieldName] = { __copied: true }; } else if (!o.__copied) { o = Ext.apply({ __copied: true }, o); sourceCfg[fieldName] = o; } o[key] = value; return value; }, configureLegacy: function(config){ var me = this; me.copyLegacyObject(config, me.customRenderers, 'renderer'); me.copyLegacyObject(config, me.customEditors, 'editor'); me.copyLegacyObject(config, me.propertyNames, 'displayName'); }, copyLegacyObject: function(config, o, keyName){ var key; for (key in o) { if (o.hasOwnProperty(key)) { if (!config[key]) { config[key] = {}; } config[key][keyName] = o[key]; } } }, onUpdate : function(store, record, operation) { var me = this, v, oldValue; if (me.rendered && operation == Ext.data.Model.EDIT) { v = record.get(me.valueField); oldValue = record.modified.value; if (me.fireEvent('beforepropertychange', me.source, record.getId(), v, oldValue) !== false) { if (me.source) { me.source[record.getId()] = v; } record.commit(); me.fireEvent('propertychange', me.source, record.getId(), v, oldValue); } else { record.reject(); } } }, walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) { var me = this, valueColumn = me.ownerCt.valueColumn; if (direction == 'left') { direction = 'up'; } else if (direction == 'right') { direction = 'down'; } pos = Ext.view.Table.prototype.walkCells.call(me, pos, direction, e, preventWrap, verifierFn, scope); pos.columnHeader = valueColumn; pos.column = valueColumn.getVisibleIndex(); return pos; }, getCellEditor : function(record, column) { var me = this, propName = record.get(me.nameField), val = record.get(me.valueField), editor = me.getConfig(propName, 'editor'), type = me.getConfig(propName, 'type'), editors = me.editors; if (editor) { if (!(editor instanceof Ext.grid.CellEditor)) { if (!(editor instanceof Ext.form.field.Base)) { editor = Ext.ComponentManager.create(editor, 'textfield'); } editor = me.setConfig(propName, 'editor', new Ext.grid.CellEditor({ field: editor })); } } else if (type) { switch (type) { case 'date': editor = editors.date; break; case 'number': editor = editors.number; break; case 'boolean': editor = me.editors['boolean']; break; default: editor = editors.string; } } else if (Ext.isDate(val)) { editor = editors.date; } else if (Ext.isNumber(val)) { editor = editors.number; } else if (Ext.isBoolean(val)) { editor = editors['boolean']; } else { editor = editors.string; } editor.editorId = propName; return editor; }, beforeDestroy: function() { var me = this; me.callParent(); me.destroyEditors(me.editors); me.destroyEditors(me.customEditors); delete me.source; }, destroyEditors: function (editors) { for (var ed in editors) { if (editors.hasOwnProperty(ed)) { Ext.destroy(editors[ed]); } } }, setSource: function(source, sourceConfig) { var me = this; me.source = source; if (sourceConfig !== undefined) { me.sourceConfig = Ext.apply({}, sourceConfig); me.configure(me.sourceConfig); } me.propStore.setSource(source); }, getSource: function() { return this.propStore.getSource(); }, setProperty: function(prop, value, create) { this.propStore.setValue(prop, value, create); }, removeProperty: function(prop) { this.propStore.remove(prop); } }); Ext.define('Ext.grid.property.HeaderContainer', { extend: Ext.grid.header.Container , alternateClassName: 'Ext.grid.PropertyColumnModel', nameWidth: 115, nameText : 'Name', valueText : 'Value', dateFormat : 'm/j/Y', trueText: 'true', falseText: 'false', nameColumnCls: Ext.baseCSSPrefix + 'grid-property-name', nameColumnInnerCls: Ext.baseCSSPrefix + 'grid-cell-inner-property-name', constructor : function(grid, store) { var me = this; me.grid = grid; me.store = store; me.callParent([{ isRootHeader: true, enableColumnResize: Ext.isDefined(grid.enableColumnResize) ? grid.enableColumnResize : me.enableColumnResize, enableColumnMove: Ext.isDefined(grid.enableColumnMove) ? grid.enableColumnMove : me.enableColumnMove, items: [{ header: me.nameText, width: grid.nameColumnWidth || me.nameWidth, sortable: grid.sortableColumns, dataIndex: grid.nameField, renderer: Ext.Function.bind(me.renderProp, me), itemId: grid.nameField, menuDisabled: true, tdCls: me.nameColumnCls, innerCls: me.nameColumnInnerCls }, { header: me.valueText, renderer: Ext.Function.bind(me.renderCell, me), getEditor: Ext.Function.bind(me.getCellEditor, me), sortable: grid.sortableColumns, flex: 1, fixed: true, dataIndex: grid.valueField, itemId: grid.valueField, menuDisabled: true }] }]); me.grid.valueColumn = me.items.items[1]; }, getCellEditor: function(record){ return this.grid.getCellEditor(record, this); }, renderProp : function(v) { return this.getPropertyName(v); }, renderCell : function(val, meta, rec) { var me = this, grid = me.grid, renderer = grid.getConfig(rec.get(grid.nameField), 'renderer'), result = val; if (renderer) { return renderer.apply(me, arguments); } if (Ext.isDate(val)) { result = me.renderDate(val); } else if (Ext.isBoolean(val)) { result = me.renderBool(val); } return Ext.util.Format.htmlEncode(result); }, renderDate : Ext.util.Format.date, renderBool : function(bVal) { return this[bVal ? 'trueText' : 'falseText']; }, getPropertyName : function(name) { return this.grid.getConfig(name, 'displayName', name); } }); Ext.define('Ext.grid.property.Property', { extend: Ext.data.Model , alternateClassName: 'Ext.PropGridProperty', fields: [{ name: 'name', type: 'string' }, { name: 'value' }], idProperty: 'name' }); Ext.define('Ext.grid.property.Store', { extend: Ext.data.Store , alternateClassName: 'Ext.grid.PropertyStore', sortOnLoad: false, constructor : function(grid, source){ var me = this; me.grid = grid; me.source = source; me.callParent([{ data: source, model: Ext.grid.property.Property, proxy: me.getProxy() }]); }, getProxy: function() { if (!this.proxy) { Ext.grid.property.Store.prototype.proxy = new Ext.data.proxy.Memory({ model: Ext.grid.property.Property, reader: this.getReader() }); } return this.proxy; }, getReader: function() { if (!this.reader) { Ext.grid.property.Store.prototype.reader = new Ext.data.reader.Reader({ model: Ext.grid.property.Property, buildExtractors: Ext.emptyFn, read: function(dataObject) { return this.readRecords(dataObject); }, readRecords: function(dataObject) { var val, propName, result = { records: [], success: true }; for (propName in dataObject) { if (dataObject.hasOwnProperty(propName)) { val = dataObject[propName]; if (this.isEditableValue(val)) { result.records.push(new Ext.grid.property.Property({ name: propName, value: val }, propName)); } } } result.total = result.count = result.records.length; return new Ext.data.ResultSet(result); }, isEditableValue: function(val){ return Ext.isPrimitive(val) || Ext.isDate(val) || val === null; } }); } return this.reader; }, setSource : function(dataObject) { var me = this; me.source = dataObject; me.suspendEvents(); me.removeAll(); me.proxy.data = dataObject; me.load(); me.resumeEvents(); me.fireEvent('datachanged', me); me.fireEvent('refresh', me); }, getProperty : function(row) { return Ext.isNumber(row) ? this.getAt(row) : this.getById(row); }, setValue : function(prop, value, create){ var me = this, rec = me.getRec(prop); if (rec) { rec.set('value', value); me.source[prop] = value; } else if (create) { me.source[prop] = value; rec = new Ext.grid.property.Property({name: prop, value: value}, prop); me.add(rec); } }, remove : function(prop) { var rec = this.getRec(prop); if (rec) { this.callParent([rec]); delete this.source[prop]; } }, getRec : function(prop) { return this.getById(prop); }, getSource : function() { return this.source; } }); Ext.define('Ext.layout.ClassList', (function () { var splitWords = Ext.String.splitWords, toMap = Ext.Array.toMap; return { dirty: false, constructor: function (owner) { this.owner = owner; this.map = toMap(this.classes = splitWords(owner.el.className)); }, add: function (cls) { var me = this; if (!me.map[cls]) { me.map[cls] = true; me.classes.push(cls); if (!me.dirty) { me.dirty = true; me.owner.markDirty(); } } }, addMany: function (classes) { Ext.each(splitWords(classes), this.add, this); }, contains: function (cls) { return this.map[cls]; }, flush: function () { this.owner.el.className = this.classes.join(' '); this.dirty = false; }, remove: function (cls) { var me = this; if (me.map[cls]) { delete me.map[cls]; me.classes = Ext.Array.filter(me.classes, function (c) { return c != cls; }); if (!me.dirty) { me.dirty = true; me.owner.markDirty(); } } }, removeMany: function (classes) { var me = this, remove = toMap(splitWords(classes)); me.classes = Ext.Array.filter(me.classes, function (c) { if (!remove[c]) { return true; } delete me.map[c]; if (!me.dirty) { me.dirty = true; me.owner.markDirty(); } return false; }); } }; }())); Ext.define('Ext.util.Queue', { constructor: function() { this.clear(); }, add : function(obj) { var me = this, key = me.getKey(obj); if (!me.map[key]) { ++me.length; me.items.push(obj); me.map[key] = obj; } return obj; }, clear : function(){ var me = this, items = me.items; me.items = []; me.map = {}; me.length = 0; return items; }, contains: function (obj) { var key = this.getKey(obj); return this.map.hasOwnProperty(key); }, getCount : function(){ return this.length; }, getKey : function(obj){ return obj.id; }, remove : function(obj){ var me = this, key = me.getKey(obj), items = me.items, index; if (me.map[key]) { index = Ext.Array.indexOf(items, obj); Ext.Array.erase(items, index, 1); delete me.map[key]; --me.length; } return obj; } }); Ext.define('Ext.layout.ContextItem', { heightModel: null, widthModel: null, sizeModel: null, optOut: false, ownerSizePolicy: null, boxChildren: null, boxParent: null, isBorderBoxValue: null, children: [], dirty: null, dirtyCount: 0, hasRawContent: true, isContextItem: true, isTopLevel: false, consumersContentHeight: 0, consumersContentWidth: 0, consumersContainerHeight: 0, consumersContainerWidth: 0, consumersHeight: 0, consumersWidth: 0, ownerCtContext: null, remainingChildDimensions: 0, props: null, state: null, wrapsComponent: false, constructor: function (config) { var me = this, sizeModels = Ext.layout.SizeModel.sizeModels, configured = sizeModels.configured, shrinkWrap = sizeModels.shrinkWrap, el, lastBox, ownerCt, ownerCtContext, props, sizeModel, target, lastWidth, lastHeight, sameWidth, sameHeight, widthModel, heightModel, optOut; Ext.apply(me, config); el = me.el; me.id = el.id; me.flushedProps = {}; me.props = props = {}; me.styles = {}; target = me.target; if (!target.isComponent) { lastBox = el.lastBox; } else { me.wrapsComponent = true; me.framing = target.frameSize || null; me.isComponentChild = target.ownerLayout && target.ownerLayout.isComponentLayout; lastBox = target.lastBox; ownerCt = target.ownerCt; if (ownerCt && (ownerCtContext = ownerCt.el && me.context.items[ownerCt.el.id])) { me.ownerCtContext = ownerCtContext; } me.sizeModel = sizeModel = target.getSizeModel(ownerCtContext && ownerCtContext.widthModel.pairsByHeightOrdinal[ownerCtContext.heightModel.ordinal]); me.widthModel = widthModel = sizeModel.width; me.heightModel = heightModel = sizeModel.height; if (lastBox && lastBox.invalid === false) { sameWidth = (target.width === (lastWidth = lastBox.width)); sameHeight = (target.height === (lastHeight = lastBox.height)); if (widthModel === shrinkWrap && heightModel === shrinkWrap) { optOut = true; } else if (widthModel === configured && sameWidth) { optOut = heightModel === shrinkWrap || (heightModel === configured && sameHeight); } if (optOut) { me.optOut = true; props.width = lastWidth; props.height = lastHeight; } } } me.lastBox = lastBox; }, init: function (full, options) { var me = this, oldProps = me.props, oldDirty = me.dirty, ownerCtContext = me.ownerCtContext, ownerLayout = me.target.ownerLayout, firstTime = !me.state, ret = full || firstTime, children, i, n, ownerCt, sizeModel, target, oldHeightModel = me.heightModel, oldWidthModel = me.widthModel, newHeightModel, newWidthModel, remainingCount = 0; me.dirty = me.invalid = false; me.props = {}; me.remainingChildDimensions = 0; if (me.boxChildren) { me.boxChildren.length = 0; } if (!firstTime) { me.clearAllBlocks('blocks'); me.clearAllBlocks('domBlocks'); } if (!me.wrapsComponent) { return ret; } target = me.target; me.state = {}; if (firstTime) { if (target.beforeLayout && target.beforeLayout !== Ext.emptyFn) { target.beforeLayout(); } if (!ownerCtContext && (ownerCt = target.ownerCt)) { ownerCtContext = me.context.items[ownerCt.el.id]; } if (ownerCtContext) { me.ownerCtContext = ownerCtContext; me.isBoxParent = target.ownerLayout.isItemBoxParent(me); } else { me.isTopLevel = true; } me.frameBodyContext = me.getEl('frameBody'); } else { ownerCtContext = me.ownerCtContext; me.isTopLevel = !ownerCtContext; children = me.children; for (i = 0, n = children.length; i < n; ++i) { children[i].init(true); } } me.hasRawContent = !(target.isContainer && target.items.items.length > 0); if (full) { me.widthModel = me.heightModel = null; sizeModel = target.getSizeModel(ownerCtContext && ownerCtContext.widthModel.pairsByHeightOrdinal[ownerCtContext.heightModel.ordinal]); if (firstTime) { me.sizeModel = sizeModel; } me.widthModel = sizeModel.width; me.heightModel = sizeModel.height; if (ownerCtContext && !me.isComponentChild) { ownerCtContext.remainingChildDimensions += 2; } } else if (oldProps) { me.recoverProp('x', oldProps, oldDirty); me.recoverProp('y', oldProps, oldDirty); if (me.widthModel.calculated) { me.recoverProp('width', oldProps, oldDirty); } else if ('width' in oldProps) { ++remainingCount; } if (me.heightModel.calculated) { me.recoverProp('height', oldProps, oldDirty); } else if ('height' in oldProps) { ++remainingCount; } if (ownerCtContext && !me.isComponentChild) { ownerCtContext.remainingChildDimensions += remainingCount; } } if (oldProps && ownerLayout && ownerLayout.manageMargins) { me.recoverProp('margin-top', oldProps, oldDirty); me.recoverProp('margin-right', oldProps, oldDirty); me.recoverProp('margin-bottom', oldProps, oldDirty); me.recoverProp('margin-left', oldProps, oldDirty); } if (options) { newHeightModel = options.heightModel; newWidthModel = options.widthModel; if (newWidthModel && newHeightModel && oldWidthModel && oldHeightModel) { if (oldWidthModel.shrinkWrap && oldHeightModel.shrinkWrap) { if (newWidthModel.constrainedMax && newHeightModel.constrainedMin) { newHeightModel = null; } } } if (newWidthModel) { me.widthModel = newWidthModel; } if (newHeightModel) { me.heightModel = newHeightModel; } if (options.state) { Ext.apply(me.state, options.state); } } return ret; }, initContinue: function (full) { var me = this, ownerCtContext = me.ownerCtContext, comp = me.target, widthModel = me.widthModel, hierarchyState = comp.getHierarchyState(), boxParent; if (widthModel.fixed) { hierarchyState.inShrinkWrapTable = false; } else { delete hierarchyState.inShrinkWrapTable; } if (full) { if (ownerCtContext && widthModel.shrinkWrap) { boxParent = ownerCtContext.isBoxParent ? ownerCtContext : ownerCtContext.boxParent; if (boxParent) { boxParent.addBoxChild(me); } } else if (widthModel.natural) { me.boxParent = ownerCtContext; } } return full; }, initDone: function(containerLayoutDone) { var me = this, props = me.props, state = me.state; if (me.remainingChildDimensions === 0) { props.containerChildrenSizeDone = true; } if (containerLayoutDone) { props.containerLayoutDone = true; } if (me.boxChildren && me.boxChildren.length && me.widthModel.shrinkWrap) { me.el.setWidth(10000); state.blocks = (state.blocks || 0) + 1; } }, initAnimation: function() { var me = this, target = me.target, ownerCtContext = me.ownerCtContext; if (ownerCtContext && ownerCtContext.isTopLevel) { me.animatePolicy = target.ownerLayout.getAnimatePolicy(me); } else if (!ownerCtContext && target.isCollapsingOrExpanding && target.animCollapse) { me.animatePolicy = target.componentLayout.getAnimatePolicy(me); } if (me.animatePolicy) { me.context.queueAnimation(me); } }, addCls: function(newCls) { this.getClassList().addMany(newCls); }, removeCls: function(removeCls) { this.getClassList().removeMany(removeCls); }, addBlock: function (name, layout, propName) { var me = this, collection = me[name] || (me[name] = {}), blockedLayouts = collection[propName] || (collection[propName] = {}); if (!blockedLayouts[layout.id]) { blockedLayouts[layout.id] = layout; ++layout.blockCount; ++me.context.blockCount; } }, addBoxChild: function (boxChildItem) { var me = this, children, widthModel = boxChildItem.widthModel; boxChildItem.boxParent = this; boxChildItem.measuresBox = widthModel.shrinkWrap ? boxChildItem.hasRawContent : widthModel.natural; if (boxChildItem.measuresBox) { children = me.boxChildren; if (children) { children.push(boxChildItem); } else { me.boxChildren = [ boxChildItem ]; } } }, addPositionStyles: function(styles, props) { var x = props.x, y = props.y, count = 0; if (x !== undefined) { styles.left = x + 'px'; ++count; } if (y !== undefined) { styles.top = y + 'px'; ++count; } return count; }, addTrigger: function (propName, inDom) { var me = this, name = inDom ? 'domTriggers' : 'triggers', collection = me[name] || (me[name] = {}), context = me.context, layout = context.currentLayout, triggers = collection[propName] || (collection[propName] = {}); if (!triggers[layout.id]) { triggers[layout.id] = layout; ++layout.triggerCount; triggers = context.triggers[inDom ? 'dom' : 'data']; (triggers[layout.id] || (triggers[layout.id] = [])).push({ item: this, prop: propName }); if (me.props[propName] !== undefined) { if (!inDom || !(me.dirty && (propName in me.dirty))) { ++layout.firedTriggers; } } } }, boxChildMeasured: function () { var me = this, state = me.state, count = (state.boxesMeasured = (state.boxesMeasured || 0) + 1); if (count == me.boxChildren.length) { state.clearBoxWidth = 1; ++me.context.progressCount; me.markDirty(); } }, borderNames: [ 'border-top-width', 'border-right-width', 'border-bottom-width', 'border-left-width'], marginNames: [ 'margin-top', 'margin-right', 'margin-bottom', 'margin-left' ], paddingNames: [ 'padding-top', 'padding-right', 'padding-bottom', 'padding-left' ], trblNames: [ 'top', 'right', 'bottom', 'left' ], cacheMissHandlers: { borderInfo: function (me) { var info = me.getStyles(me.borderNames, me.trblNames); info.width = info.left + info.right; info.height = info.top + info.bottom; return info; }, marginInfo: function (me) { var info = me.getStyles(me.marginNames, me.trblNames); info.width = info.left + info.right; info.height = info.top + info.bottom; return info; }, paddingInfo: function (me) { var item = me.frameBodyContext || me, info = item.getStyles(me.paddingNames, me.trblNames); info.width = info.left + info.right; info.height = info.top + info.bottom; return info; } }, checkCache: function (entry) { return this.cacheMissHandlers[entry](this); }, clearAllBlocks: function (name) { var collection = this[name], propName; if (collection) { for (propName in collection) { this.clearBlocks(name, propName); } } }, clearBlocks: function (name, propName) { var collection = this[name], blockedLayouts = collection && collection[propName], context, layout, layoutId; if (blockedLayouts) { delete collection[propName]; context = this.context; for (layoutId in blockedLayouts) { layout = blockedLayouts[layoutId]; --context.blockCount; if (! --layout.blockCount && !layout.pending && !layout.done) { context.queueLayout(layout); } } } }, block: function (layout, propName) { this.addBlock('blocks', layout, propName); }, domBlock: function (layout, propName) { this.addBlock('domBlocks', layout, propName); }, fireTriggers: function (name, propName) { var collection = this[name], triggers = collection && collection[propName], context = this.context, layout, layoutId; if (triggers) { for (layoutId in triggers) { layout = triggers[layoutId]; ++layout.firedTriggers; if (!layout.done && !layout.blockCount && !layout.pending) { context.queueLayout(layout); } } } }, flush: function () { var me = this, dirty = me.dirty, state = me.state, targetEl = me.el; me.dirtyCount = 0; if (me.classList && me.classList.dirty) { me.classList.flush(); } if ('attributes' in me) { targetEl.set(me.attributes); delete me.attributes; } if ('innerHTML' in me) { targetEl.innerHTML = me.innerHTML; delete me.innerHTML; } if (state && state.clearBoxWidth) { state.clearBoxWidth = 0; me.el.setStyle('width', null); if (! --state.blocks) { me.context.queueItemLayouts(me); } } if (dirty) { delete me.dirty; me.writeProps(dirty, true); } }, flushAnimations: function() { var me = this, animateFrom = me.previousSize, target, targetAnim, duration, animateProps, anim, changeCount, j, propsLen, propName, oldValue, newValue; if (animateFrom) { target = me.target; targetAnim = target.layout && target.layout.animate; if (targetAnim) { duration = Ext.isNumber(targetAnim) ? targetAnim : targetAnim.duration; } animateProps = Ext.Object.getKeys(me.animatePolicy); anim = Ext.apply({}, { from: {}, to: {}, duration: duration || Ext.fx.Anim.prototype.duration }, targetAnim); for (changeCount = 0, j = 0, propsLen = animateProps.length; j < propsLen; j++) { propName = animateProps[j]; oldValue = animateFrom[propName]; newValue = me.peek(propName); if (oldValue != newValue) { propName = me.translateProps[propName]||propName; anim.from[propName] = oldValue; anim.to[propName] = newValue; ++changeCount; } } if (changeCount) { if (me.isCollapsingOrExpanding === 1) { target.componentLayout.undoLayout(me); } else { me.writeProps(anim.from); } me.el.animate(anim); Ext.fx.Manager.getFxQueue(me.el.id)[0].on({ afteranimate: function() { if (me.isCollapsingOrExpanding === 1) { target.componentLayout.redoLayout(me); target.afterCollapse(true); } else if (me.isCollapsingOrExpanding === 2) { target.afterExpand(true); } } }); } } }, getBorderInfo: function () { var me = this, info = me.borderInfo; if (!info) { me.borderInfo = info = me.checkCache('borderInfo'); } return info; }, getClassList: function () { return this.classList || (this.classList = new Ext.layout.ClassList(this)); }, getEl: function (nameOrEl, owner) { var me = this, src, el, elContext; if (nameOrEl) { if (nameOrEl.dom) { el = nameOrEl; } else { src = me.target; if (owner) { src = owner; } el = src[nameOrEl]; if (typeof el == 'function') { el = el.call(src); if (el === me.el) { return this; } } } if (el) { elContext = me.context.getEl(me, el); } } return elContext || null; }, getFrameInfo: function () { var me = this, info = me.frameInfo, framing, border; if (!info) { framing = me.framing; border = me.getBorderInfo(); me.frameInfo = info = framing ? { top : framing.top + border.top, right : framing.right + border.right, bottom: framing.bottom + border.bottom, left : framing.left + border.left, width : framing.width + border.width, height: framing.height + border.height } : border; } return info; }, getMarginInfo: function () { var me = this, info = me.marginInfo, comp, manageMargins, margins, ownerLayout, ownerLayoutId; if (!info) { if (!me.wrapsComponent) { info = me.checkCache('marginInfo'); } else { comp = me.target; ownerLayout = comp.ownerLayout; ownerLayoutId = ownerLayout ? ownerLayout.id : null; manageMargins = ownerLayout && ownerLayout.manageMargins; info = comp.margin$; if (info && info.ownerId !== ownerLayoutId) { info = null; } if (!info) { info = me.parseMargins(comp, comp.margin) || me.checkCache('marginInfo'); if (manageMargins) { margins = me.parseMargins(comp, comp.margins, ownerLayout.defaultMargins); if (margins) { info = { top: info.top + margins.top, right: info.right + margins.right, bottom: info.bottom + margins.bottom, left: info.left + margins.left }; } me.setProp('margin-top', 0); me.setProp('margin-right', 0); me.setProp('margin-bottom', 0); me.setProp('margin-left', 0); } info.ownerId = ownerLayoutId; comp.margin$ = info; } info.width = info.left + info.right; info.height = info.top + info.bottom; } me.marginInfo = info; } return info; }, clearMarginCache: function() { delete this.marginInfo; delete this.target.margin$; }, getPaddingInfo: function () { var me = this, info = me.paddingInfo; if (!info) { me.paddingInfo = info = me.checkCache('paddingInfo'); } return info; }, getProp: function (propName) { var me = this, result = me.props[propName]; me.addTrigger(propName); return result; }, getDomProp: function (propName) { var me = this, result = (me.dirty && (propName in me.dirty)) ? undefined : me.props[propName]; me.addTrigger(propName, true); return result; }, getStyle: function (styleName) { var me = this, styles = me.styles, info, value; if (styleName in styles) { value = styles[styleName]; } else { info = me.styleInfo[styleName]; value = me.el.getStyle(styleName); if (info && info.parseInt) { value = parseInt(value, 10) || 0; } styles[styleName] = value; } return value; }, getStyles: function (styleNames, altNames) { var me = this, styleCache = me.styles, values = {}, hits = 0, n = styleNames.length, i, missing, missingAltNames, name, info, styleInfo, styles, value; altNames = altNames || styleNames; for (i = 0; i < n; ++i) { name = styleNames[i]; if (name in styleCache) { values[altNames[i]] = styleCache[name]; ++hits; if (i && hits==1) { missing = styleNames.slice(0, i); missingAltNames = altNames.slice(0, i); } } else if (hits) { (missing || (missing = [])).push(name); (missingAltNames || (missingAltNames = [])).push(altNames[i]); } } if (hits < n) { missing = missing || styleNames; missingAltNames = missingAltNames || altNames; styleInfo = me.styleInfo; styles = me.el.getStyle(missing); for (i = missing.length; i--; ) { name = missing[i]; info = styleInfo[name]; value = styles[name]; if (info && info.parseInt) { value = parseInt(value, 10) || 0; } values[missingAltNames[i]] = value; styleCache[name] = value; } } return values; }, hasProp: function (propName) { return this.getProp(propName) != null; }, hasDomProp: function (propName) { return this.getDomProp(propName) != null; }, invalidate: function (options) { this.context.queueInvalidate(this, options); }, markDirty: function () { if (++this.dirtyCount == 1) { this.context.queueFlush(this); } }, onBoxMeasured: function () { var boxParent = this.boxParent, state = this.state; if (boxParent && boxParent.widthModel.shrinkWrap && !state.boxMeasured && this.measuresBox) { state.boxMeasured = 1; boxParent.boxChildMeasured(); } }, parseMargins: function (comp, margins, defaultMargins) { if (margins === true) { margins = 5; } var type = typeof margins, ret; if (type == 'string' || type == 'number') { ret = comp.parseBox(margins); } else if (margins || defaultMargins) { ret = { top: 0, right: 0, bottom: 0, left: 0 }; if (defaultMargins) { Ext.apply(ret, this.parseMargins(comp, defaultMargins)); } if (margins) { margins = Ext.apply(ret, comp.parseBox(margins)); } } return ret; }, peek: function (propName) { return this.props[propName]; }, recoverProp: function (propName, oldProps, oldDirty) { var me = this, props = me.props, dirty; if (propName in oldProps) { props[propName] = oldProps[propName]; if (oldDirty && propName in oldDirty) { dirty = me.dirty || (me.dirty = {}); dirty[propName] = oldDirty[propName]; } } }, redo: function(deep) { var me = this, items, len, i; me.revertProps(me.props); if (deep && me.wrapsComponent) { if (me.childItems) { for (i = 0, items = me.childItems, len = items.length; i < len; i++) { items[i].redo(deep); } } for (i = 0, items = me.children, len = items.length; i < len; i++) { items[i].redo(); } } }, removeEl: function(nameOrEl, owner) { var me = this, src, el; if (nameOrEl) { if (nameOrEl.dom) { el = nameOrEl; } else { src = me.target; if (owner) { src = owner; } el = src[nameOrEl]; if (typeof el == 'function') { el = el.call(src); if (el === me.el) { return this; } } } if (el) { me.context.removeEl(me, el); } } }, revertProps: function (props) { var name, flushed = this.flushedProps, reverted = {}; for (name in props) { if (flushed.hasOwnProperty(name)) { reverted[name] = props[name]; } } this.writeProps(reverted); }, setAttribute: function(name, value) { var me = this; if (!me.attributes) { me.attributes = {}; } me.attributes[name] = value; me.markDirty(); }, setBox: function (box) { var me = this; if ('left' in box) { me.setProp('x', box.left); } if ('top' in box) { me.setProp('y', box.top); } me.setSize(box.width, box.height); }, setContentHeight: function (height, measured) { if (!measured && this.hasRawContent) { return 1; } return this.setProp('contentHeight', height); }, setContentWidth: function (width, measured) { if (!measured && this.hasRawContent) { return 1; } return this.setProp('contentWidth', width); }, setContentSize: function (width, height, measured) { return this.setContentWidth(width, measured) + this.setContentHeight(height, measured) == 2; }, setProp: function (propName, value, dirty) { var me = this, valueType = typeof value, borderBox, info; if (valueType == 'undefined' || (valueType === 'number' && isNaN(value))) { return 0; } if (me.props[propName] === value) { return 1; } me.props[propName] = value; ++me.context.progressCount; if (dirty === false) { me.fireTriggers('domTriggers', propName); me.clearBlocks('domBlocks', propName); } else { info = me.styleInfo[propName]; if (info) { if (!me.dirty) { me.dirty = {}; } if (propName == 'width' || propName == 'height') { borderBox = me.isBorderBoxValue; if (borderBox === null) { me.isBorderBoxValue = borderBox = !!me.el.isBorderBox(); } if (!borderBox) { me.borderInfo || me.getBorderInfo(); me.paddingInfo || me.getPaddingInfo(); } } me.dirty[propName] = value; me.markDirty(); } } me.fireTriggers('triggers', propName); me.clearBlocks('blocks', propName); return 1; }, setHeight: function (height, dirty ) { var me = this, comp = me.target, ownerCtContext = me.ownerCtContext, frameBody, frameInfo, min, oldHeight, rem; if (height < 0) { height = 0; } if (!me.wrapsComponent) { if (!me.setProp('height', height, dirty)) { return NaN; } } else { min = me.collapsedVert ? 0 : (comp.minHeight || 0); height = Ext.Number.constrain(height, min, comp.maxHeight); oldHeight = me.props.height; if (!me.setProp('height', height, dirty)) { return NaN; } if (ownerCtContext && !me.isComponentChild && isNaN(oldHeight)) { rem = --ownerCtContext.remainingChildDimensions; if (!rem) { ownerCtContext.setProp('containerChildrenSizeDone', true); } } frameBody = me.frameBodyContext; if (frameBody){ frameInfo = me.getFrameInfo(); frameBody.setHeight(height - frameInfo.height, dirty); } } return height; }, setWidth: function (width, dirty ) { var me = this, comp = me.target, ownerCtContext = me.ownerCtContext, frameBody, frameInfo, min, oldWidth, rem; if (width < 0) { width = 0; } if (!me.wrapsComponent) { if (!me.setProp('width', width, dirty)) { return NaN; } } else { min = me.collapsedHorz ? 0 : (comp.minWidth || 0); width = Ext.Number.constrain(width, min, comp.maxWidth); oldWidth = me.props.width if (!me.setProp('width', width, dirty)) { return NaN; } if (ownerCtContext && !me.isComponentChild && isNaN(oldWidth)) { rem = --ownerCtContext.remainingChildDimensions; if (!rem) { ownerCtContext.setProp('containerChildrenSizeDone', true); } } frameBody = me.frameBodyContext; if (frameBody) { frameInfo = me.getFrameInfo(); frameBody.setWidth(width - frameInfo.width, dirty); } } return width; }, setSize: function (width, height, dirty) { this.setWidth(width, dirty); this.setHeight(height, dirty); }, translateProps: { x: 'left', y: 'top' }, undo: function(deep) { var me = this, items, len, i; me.revertProps(me.lastBox); if (deep && me.wrapsComponent) { if (me.childItems) { for (i = 0, items = me.childItems, len = items.length; i < len; i++) { items[i].undo(deep); } } for (i = 0, items = me.children, len = items.length; i < len; i++) { items[i].undo(); } } }, unsetProp: function (propName) { var dirty = this.dirty; delete this.props[propName]; if (dirty) { delete dirty[propName]; } }, writeProps: function(dirtyProps, flushing) { if (!(dirtyProps && typeof dirtyProps == 'object')) { return; } var me = this, el = me.el, styles = {}, styleCount = 0, styleInfo = me.styleInfo, info, propName, numericValue, width = dirtyProps.width, height = dirtyProps.height, isBorderBox = me.isBorderBoxValue, target = me.target, max = Math.max, paddingWidth = 0, paddingHeight = 0, hasWidth, hasHeight, isAbsolute, scrollbarSize, style, targetEl; if ('displayed' in dirtyProps) { el.setDisplayed(dirtyProps.displayed); } for (propName in dirtyProps) { if (flushing) { me.fireTriggers('domTriggers', propName); me.clearBlocks('domBlocks', propName); me.flushedProps[propName] = 1; } info = styleInfo[propName]; if (info && info.dom) { if (info.suffix && (numericValue = parseInt(dirtyProps[propName], 10))) { styles[propName] = numericValue + info.suffix; } else { styles[propName] = dirtyProps[propName]; } ++styleCount; } } if ('x' in dirtyProps || 'y' in dirtyProps) { if (target.isComponent) { target.setPosition(dirtyProps.x, dirtyProps.y); } else { styleCount += me.addPositionStyles(styles, dirtyProps); } } if (!isBorderBox && (width > 0 || height > 0)) { if(!me.frameBodyContext) { paddingWidth = me.paddingInfo.width; paddingHeight = me.paddingInfo.height; } if (width) { width = max(parseInt(width, 10) - (me.borderInfo.width + paddingWidth), 0); styles.width = width + 'px'; ++styleCount; } if (height) { height = max(parseInt(height, 10) - (me.borderInfo.height + paddingHeight), 0); styles.height = height + 'px'; ++styleCount; } } if (me.wrapsComponent && Ext.isIE9 && Ext.isStrict) { if ((hasWidth = width !== undefined && me.hasOverflowY) || (hasHeight = height !== undefined && me.hasOverflowX)) { isAbsolute = me.isAbsolute; if (isAbsolute === undefined) { isAbsolute = false; targetEl = me.target.getTargetEl(); style = targetEl.getStyle('position'); if (style == 'absolute') { style = targetEl.getStyle('box-sizing'); isAbsolute = (style == 'border-box'); } me.isAbsolute = isAbsolute; } if (isAbsolute) { scrollbarSize = Ext.getScrollbarSize(); if (hasWidth) { width = parseInt(width, 10) + scrollbarSize.width; styles.width = width + 'px'; ++styleCount; } if (hasHeight) { height = parseInt(height, 10) + scrollbarSize.height; styles.height = height + 'px'; ++styleCount; } } } } if (styleCount) { el.setStyle(styles); } } }, function () { var px = { dom: true, parseInt: true, suffix: 'px' }, isDom = { dom: true }, faux = { dom: false }; this.prototype.styleInfo = { containerChildrenSizeDone: faux, containerLayoutDone: faux, displayed: faux, done: faux, x: faux, y: faux, columnWidthsDone: faux, left: px, top: px, right: px, bottom: px, width: px, height: px, 'border-top-width': px, 'border-right-width': px, 'border-bottom-width': px, 'border-left-width': px, 'margin-top': px, 'margin-right': px, 'margin-bottom': px, 'margin-left': px, 'padding-top': px, 'padding-right': px, 'padding-bottom': px, 'padding-left': px, 'line-height': isDom, display: isDom }; }); Ext.define('Ext.layout.Context', { remainingLayouts: 0, state: 0, constructor: function (config) { var me = this; Ext.apply(me, config); me.items = {}; me.layouts = {}; me.blockCount = 0; me.cycleCount = 0; me.flushCount = 0; me.calcCount = 0; me.animateQueue = me.newQueue(); me.completionQueue = me.newQueue(); me.finalizeQueue = me.newQueue(); me.finishQueue = me.newQueue(); me.flushQueue = me.newQueue(); me.invalidateData = {}; me.layoutQueue = me.newQueue(); me.invalidQueue = []; me.triggers = { data: { }, dom: {} }; }, callLayout: function (layout, methodName) { this.currentLayout = layout; layout[methodName](this.getCmp(layout.owner)); }, cancelComponent: function (comp, isChild, isDestroying) { var me = this, components = comp, isArray = !comp.isComponent, length = isArray ? components.length : 1, i, k, klen, items, layout, newQueue, oldQueue, entry, temp, ownerCtContext; for (i = 0; i < length; ++i) { if (isArray) { comp = components[i]; } if (isDestroying && comp.ownerCt) { ownerCtContext = this.items[comp.ownerCt.el.id]; if (ownerCtContext) { Ext.Array.remove(ownerCtContext.childItems, me.getCmp(comp)); } } if (!isChild) { oldQueue = me.invalidQueue; klen = oldQueue.length; if (klen) { me.invalidQueue = newQueue = []; for (k = 0; k < klen; ++k) { entry = oldQueue[k]; temp = entry.item.target; if (temp != comp && !temp.isDescendant(comp)) { newQueue.push(entry); } } } } layout = comp.componentLayout; me.cancelLayout(layout); if (layout.getLayoutItems) { items = layout.getLayoutItems(); if (items.length) { me.cancelComponent(items, true); } } if (comp.isContainer && !comp.collapsed) { layout = comp.layout; me.cancelLayout(layout); items = layout.getVisibleItems(); if (items.length) { me.cancelComponent(items, true); } } } }, cancelLayout: function (layout) { var me = this; me.completionQueue.remove(layout); me.finalizeQueue.remove(layout); me.finishQueue.remove(layout); me.layoutQueue.remove(layout); if (layout.running) { me.layoutDone(layout); } layout.ownerContext = null; }, clearTriggers: function (layout, inDom) { var id = layout.id, collection = this.triggers[inDom ? 'dom' : 'data'], triggers = collection && collection[id], length = (triggers && triggers.length) || 0, i, item, trigger; for (i = 0; i < length; ++i) { trigger = triggers[i]; item = trigger.item; collection = inDom ? item.domTriggers : item.triggers; delete collection[trigger.prop][id]; } }, flush: function () { var me = this, items = me.flushQueue.clear(), length = items.length, i; if (length) { ++me.flushCount; for (i = 0; i < length; ++i) { items[i].flush(); } } }, flushAnimations: function() { var me = this, items = me.animateQueue.clear(), len = items.length, i; if (len) { for (i = 0; i < len; i++) { if (items[i].target.animate !== false) { items[i].flushAnimations(); } } Ext.fx.Manager.runner(); } }, flushInvalidates: function () { var me = this, queue = me.invalidQueue, length = queue && queue.length, comp, components, entry, i; me.invalidQueue = []; if (length) { components = []; for (i = 0; i < length; ++i) { comp = (entry = queue[i]).item.target; if (!comp.container.isDetachedBody) { components.push(comp); if (entry.options) { me.invalidateData[comp.id] = entry.options; } } } me.invalidate(components, null); } }, flushLayouts: function (queueName, methodName, dontClear) { var me = this, layouts = dontClear ? me[queueName].items : me[queueName].clear(), length = layouts.length, i, layout; if (length) { for (i = 0; i < length; ++i) { layout = layouts[i]; if (!layout.running) { me.callLayout(layout, methodName); } } me.currentLayout = null; } }, getCmp: function (cmp) { return this.getItem(cmp, cmp.el); }, getEl: function (parent, el) { var item = this.getItem(el, el); if (!item.parent) { item.parent = parent; if (parent.children.length) { parent.children.push(item); } else { parent.children = [ item ]; } } return item; }, getItem: function (target, el) { var id = el.id, items = this.items, item = items[id] || (items[id] = new Ext.layout.ContextItem({ context: this, target: target, el: el })); return item; }, handleFailure: function () { var layouts = this.layouts, layout, key; Ext.failedLayouts = (Ext.failedLayouts || 0) + 1; for (key in layouts) { layout = layouts[key]; if (layouts.hasOwnProperty(key)) { layout.running = false; layout.ownerContext = null; } } }, invalidate: function (components, full) { var me = this, isArray = !components.isComponent, containerLayoutDone, firstTime, i, comp, item, items, length, componentLayout, layout, invalidateOptions, token; for (i = 0, length = isArray ? components.length : 1; i < length; ++i) { comp = isArray ? components[i] : components; if (comp.rendered && !comp.hidden) { item = me.getCmp(comp); componentLayout = comp.componentLayout; firstTime = !componentLayout.ownerContext; layout = (comp.isContainer && !comp.collapsed) ? comp.layout : null; invalidateOptions = me.invalidateData[item.id]; delete me.invalidateData[item.id]; token = item.init(full, invalidateOptions); if (invalidateOptions) { me.processInvalidate(invalidateOptions, item, 'before'); } if (componentLayout.beforeLayoutCycle) { componentLayout.beforeLayoutCycle(item); } if (layout && layout.beforeLayoutCycle) { layout.beforeLayoutCycle(item); } token = item.initContinue(token); containerLayoutDone = true; if (componentLayout.getLayoutItems) { componentLayout.renderChildren(); items = componentLayout.getLayoutItems(); if (items.length) { me.invalidate(items, true); } } if (layout) { containerLayoutDone = false; layout.renderChildren(); items = layout.getVisibleItems(); if (items.length) { me.invalidate(items, true); } } item.initDone(containerLayoutDone); me.resetLayout(componentLayout, item, firstTime); if (layout) { me.resetLayout(layout, item, firstTime); } item.initAnimation(); if (invalidateOptions) { me.processInvalidate(invalidateOptions, item, 'after'); } } } me.currentLayout = null; }, layoutDone: function (layout) { var ownerContext = layout.ownerContext; layout.running = false; if (layout.isComponentLayout) { if (ownerContext.measuresBox) { ownerContext.onBoxMeasured(); } ownerContext.setProp('done', true); } else { ownerContext.setProp('containerLayoutDone', true); } --this.remainingLayouts; ++this.progressCount; }, newQueue: function () { return new Ext.util.Queue(); }, processInvalidate: function (options, item, name) { if (options[name]) { var me = this, currentLayout = me.currentLayout; me.currentLayout = options.layout || null; options[name](item, options); me.currentLayout = currentLayout; } }, queueAnimation: function (item) { this.animateQueue.add(item); }, queueCompletion: function (layout) { this.completionQueue.add(layout); }, queueFinalize: function (layout) { this.finalizeQueue.add(layout); }, queueFlush: function (item) { this.flushQueue.add(item); }, chainFns: function (oldOptions, newOptions, funcName) { var me = this, oldLayout = oldOptions.layout, newLayout = newOptions.layout, oldFn = oldOptions[funcName], newFn = newOptions[funcName]; return function (contextItem) { var prev = me.currentLayout; if (oldFn) { me.currentLayout = oldLayout; oldFn.call(oldOptions.scope || oldOptions, contextItem, oldOptions); } me.currentLayout = newLayout; newFn.call(newOptions.scope || newOptions, contextItem, newOptions); me.currentLayout = prev; }; }, queueInvalidate: function (item, options) { var me = this, newQueue = [], oldQueue = me.invalidQueue, index = oldQueue.length, comp, old, oldComp, oldOptions, oldState; if (item.isComponent) { item = me.getCmp(comp = item); } else { comp = item.target; } item.invalid = true; while (index--) { old = oldQueue[index]; oldComp = old.item.target; if (comp.isDescendant(oldComp)) { return; } if (oldComp == comp) { if (!(oldOptions = old.options)) { old.options = options; } else if (options) { if (options.widthModel) { oldOptions.widthModel = options.widthModel; } if (options.heightModel) { oldOptions.heightModel = options.heightModel; } if (!(oldState = oldOptions.state)) { oldOptions.state = options.state; } else if (options.state) { Ext.apply(oldState, options.state); } if (options.before) { oldOptions.before = me.chainFns(oldOptions, options, 'before'); } if (options.after) { oldOptions.after = me.chainFns(oldOptions, options, 'after'); } } return; } if (!oldComp.isDescendant(comp)) { newQueue.push(old); } } newQueue.push({ item: item, options: options }); me.invalidQueue = newQueue; }, queueItemLayouts: function (item) { var comp = item.isComponent ? item : item.target, layout = comp.componentLayout; if (!layout.pending && !layout.invalid && !layout.done) { this.queueLayout(layout); } layout = comp.layout; if (layout && !layout.pending && !layout.invalid && !layout.done) { this.queueLayout(layout); } }, queueLayout: function (layout) { this.layoutQueue.add(layout); layout.pending = true; }, removeEl: function (parent, el) { var id = el.id, children = parent.children, items = this.items; if(children) { Ext.Array.remove(children, items[id]); } delete items[id]; }, resetLayout: function (layout, ownerContext, firstTime) { var me = this; me.currentLayout = layout; layout.done = false; layout.pending = true; layout.firedTriggers = 0; me.layoutQueue.add(layout); if (firstTime) { me.layouts[layout.id] = layout; layout.running = true; if (layout.finishedLayout) { me.finishQueue.add(layout); } ++me.remainingLayouts; ++layout.layoutCount; layout.ownerContext = ownerContext; layout.beginCount = 0; layout.blockCount = 0; layout.calcCount = 0; layout.triggerCount = 0; if (!layout.initialized) { layout.initLayout(); } layout.beginLayout(ownerContext); } else { ++layout.beginCount; if (!layout.running) { ++me.remainingLayouts; layout.running = true; if (layout.isComponentLayout) { ownerContext.unsetProp('done'); } me.completionQueue.remove(layout); me.finalizeQueue.remove(layout); } } layout.beginLayoutCycle(ownerContext, firstTime); }, run: function () { var me = this, flushed = false, watchDog = 100; me.flushInvalidates(); me.state = 1; me.totalCount = me.layoutQueue.getCount(); me.flush(); while ((me.remainingLayouts || me.invalidQueue.length) && watchDog--) { if (me.invalidQueue.length) { me.flushInvalidates(); } if (me.runCycle()) { flushed = false; } else if (!flushed) { me.flush(); flushed = true; me.flushLayouts('completionQueue', 'completeLayout'); } else if (!me.invalidQueue.length) { me.state = 2; break; } if (!(me.remainingLayouts || me.invalidQueue.length)) { me.flush(); me.flushLayouts('completionQueue', 'completeLayout'); me.flushLayouts('finalizeQueue', 'finalizeLayout'); } } return me.runComplete(); }, runComplete: function () { var me = this; me.state = 2; if (me.remainingLayouts) { me.handleFailure(); return false; } me.flush(); me.flushLayouts('finishQueue', 'finishedLayout', true); me.flushLayouts('finishQueue', 'notifyOwner'); me.flush(); me.flushAnimations(); return true; }, runCycle: function () { var me = this, layouts = me.layoutQueue.clear(), length = layouts.length, i; ++me.cycleCount; me.progressCount = 0; for (i = 0; i < length; ++i) { me.runLayout(me.currentLayout = layouts[i]); } me.currentLayout = null; return me.progressCount > 0; }, runLayout: function (layout) { var me = this, ownerContext = me.getCmp(layout.owner); layout.pending = false; if (ownerContext.state.blocks) { return; } layout.done = true; ++layout.calcCount; ++me.calcCount; layout.calculate(ownerContext); if (layout.done) { me.layoutDone(layout); if (layout.completeLayout) { me.queueCompletion(layout); } if (layout.finalizeLayout) { me.queueFinalize(layout); } } else if (!layout.pending && !layout.invalid && !(layout.blockCount + layout.triggerCount - layout.firedTriggers)) { me.queueLayout(layout); } }, setItemSize: function(item, width, height) { var items = item, len = 1, contextItem, i; if (item.isComposite) { items = item.elements; len = items.length; item = items[0]; } else if (!item.dom && !item.el) { len = items.length; item = items[0]; } for (i = 0; i < len; ) { contextItem = this.get(item); contextItem.setSize(width, height); item = items[++i]; } } }); Ext.define('Ext.layout.component.Body', { alias: ['layout.body'], extend: Ext.layout.component.Auto , type: 'body', beginLayout: function (ownerContext) { this.callParent(arguments); ownerContext.bodyContext = ownerContext.getEl('body'); }, beginLayoutCycle: function(ownerContext, firstCycle){ var me = this, lastWidthModel = me.lastWidthModel, lastHeightModel = me.lastHeightModel, body = me.owner.body; me.callParent(arguments); if (lastWidthModel && lastWidthModel.fixed && ownerContext.widthModel.shrinkWrap) { body.setWidth(null); } if (lastHeightModel && lastHeightModel.fixed && ownerContext.heightModel.shrinkWrap) { body.setHeight(null); } }, calculateOwnerHeightFromContentHeight: function (ownerContext, contentHeight) { var height = this.callParent(arguments); if (ownerContext.targetContext != ownerContext) { height += ownerContext.getPaddingInfo().height; } return height; }, calculateOwnerWidthFromContentWidth: function (ownerContext, contentWidth) { var width = this.callParent(arguments); if (ownerContext.targetContext != ownerContext) { width += ownerContext.getPaddingInfo().width; } return width; }, measureContentWidth: function (ownerContext) { return ownerContext.bodyContext.setWidth(ownerContext.bodyContext.el.dom.offsetWidth, false); }, measureContentHeight: function (ownerContext) { return ownerContext.bodyContext.setHeight(ownerContext.bodyContext.el.dom.offsetHeight, false); }, publishInnerHeight: function (ownerContext, height) { var innerHeight = height - ownerContext.getFrameInfo().height, targetContext = ownerContext.targetContext; if (targetContext != ownerContext) { innerHeight -= ownerContext.getPaddingInfo().height; } return ownerContext.bodyContext.setHeight(innerHeight, !ownerContext.heightModel.natural); }, publishInnerWidth: function (ownerContext, width) { var innerWidth = width - ownerContext.getFrameInfo().width, targetContext = ownerContext.targetContext; if (targetContext != ownerContext) { innerWidth -= ownerContext.getPaddingInfo().width; } ownerContext.bodyContext.setWidth(innerWidth, !ownerContext.widthModel.natural); } }); Ext.define('Ext.layout.component.FieldSet', { extend: Ext.layout.component.Body , alias: ['layout.fieldset'], type: 'fieldset', defaultCollapsedWidth: 100, beforeLayoutCycle: function (ownerContext) { if (ownerContext.target.collapsed) { ownerContext.heightModel = this.sizeModels.shrinkWrap; } }, beginLayoutCycle: function (ownerContext) { var target = ownerContext.target, lastSize; this.callParent(arguments); if (target.collapsed) { ownerContext.setContentHeight(0); ownerContext.restoreMinHeight = target.minHeight; delete target.minHeight; if (ownerContext.widthModel.shrinkWrap) { lastSize = target.lastComponentSize; ownerContext.setContentWidth((lastSize && lastSize.contentWidth) || this.defaultCollapsedWidth); } } }, finishedLayout: function(ownerContext) { var owner = this.owner, restore = ownerContext.restoreMinHeight; this.callParent(arguments); if (restore) { owner.minHeight = restore; } }, calculateOwnerHeightFromContentHeight: function (ownerContext, contentHeight) { var border = ownerContext.getBorderInfo(), legend = ownerContext.target.legend; return ownerContext.getProp('contentHeight') + ownerContext.getPaddingInfo().height + ((Ext.isIEQuirks || Ext.isIE8m) ? ownerContext.bodyContext.getPaddingInfo().top : 0) + (legend ? legend.getHeight() : border.top) + border.bottom; }, publishInnerHeight: function (ownerContext, height) { var legend = ownerContext.target.legend; if (legend) { height -= legend.getHeight(); } this.callParent([ownerContext, height]); }, getLayoutItems : function() { var legend = this.owner.legend; return legend ? [legend] : []; } }); Ext.define('Ext.layout.component.field.Slider', { alias: ['layout.sliderfield'], extend: Ext.layout.component.field.Field , type: 'sliderfield', beginLayout: function(ownerContext) { this.callParent(arguments); ownerContext.endElContext = ownerContext.getEl('endEl'); ownerContext.innerElContext = ownerContext.getEl('innerEl'); ownerContext.bodyElContext = ownerContext.getEl('bodyEl'); }, publishInnerHeight: function (ownerContext, height) { var innerHeight = height - this.measureLabelErrorHeight(ownerContext), endElPad, inputPad; if (this.owner.vertical) { endElPad = ownerContext.endElContext.getPaddingInfo(); inputPad = ownerContext.inputContext.getPaddingInfo(); ownerContext.innerElContext.setHeight(innerHeight - inputPad.height - endElPad.height); } else { ownerContext.bodyElContext.setHeight(innerHeight); } }, publishInnerWidth: function (ownerContext, width) { if (!this.owner.vertical) { var endElPad = ownerContext.endElContext.getPaddingInfo(), inputPad = ownerContext.inputContext.getPaddingInfo(); ownerContext.innerElContext.setWidth(width - inputPad.left - endElPad.right - ownerContext.labelContext.getProp('width')); } }, beginLayoutFixed: function(ownerContext, width, suffix) { var me = this, ieInputWidthAdjustment = me.ieInputWidthAdjustment; if (ieInputWidthAdjustment) { me.owner.bodyEl.setStyle('padding-right', ieInputWidthAdjustment + 'px'); } me.callParent(arguments); } }); Ext.define('Ext.layout.container.Absolute', { alias: 'layout.absolute', extend: Ext.layout.container.Anchor , alternateClassName: 'Ext.layout.AbsoluteLayout', targetCls: Ext.baseCSSPrefix + 'abs-layout-ct', itemCls: Ext.baseCSSPrefix + 'abs-layout-item', ignoreOnContentChange: true, type: 'absolute', adjustWidthAnchor: function(value, childContext) { var padding = this.targetPadding, x = childContext.getStyle('left'); return value - x + padding.left; }, adjustHeightAnchor: function(value, childContext) { var padding = this.targetPadding, y = childContext.getStyle('top'); return value - y + padding.top; }, isItemLayoutRoot: function (item) { return this.ignoreOnContentChange || this.callParent(arguments); }, isItemShrinkWrap: function (item) { return true; }, beginLayout: function (ownerContext) { var me = this, target = me.getTarget(); me.callParent(arguments); if (target.dom !== document.body) { target.position(); } me.targetPadding = ownerContext.targetContext.getPaddingInfo(); }, isItemBoxParent: function (itemContext) { return true; }, onContentChange: function () { if (this.ignoreOnContentChange) { return false; } return this.callParent(arguments); }, calculateContentSize: function (ownerContext, dimensions) { var me = this, containerDimensions = (dimensions || 0) | ((ownerContext.widthModel.shrinkWrap ? 1 : 0) | (ownerContext.heightModel.shrinkWrap ? 2 : 0)), calcWidth = (containerDimensions & 1) || undefined, calcHeight = (containerDimensions & 2) || undefined, childItems = ownerContext.childItems, length = childItems.length, contentHeight = 0, contentWidth = 0, needed = 0, props = ownerContext.props, targetPadding, child, childContext, height, i, margins, width; if (calcWidth) { if (isNaN(props.contentWidth)) { ++needed; } else { calcWidth = undefined; } } if (calcHeight) { if (isNaN(props.contentHeight)) { ++needed; } else { calcHeight = undefined; } } if (needed) { for (i = 0; i < length; ++i) { childContext = childItems[i]; child = childContext.target; height = calcHeight && childContext.getProp('height'); width = calcWidth && childContext.getProp('width'); margins = childContext.getMarginInfo(); height += margins.bottom; width += margins.right; contentHeight = Math.max(contentHeight, (child.y || 0) + height); contentWidth = Math.max(contentWidth, (child.x || 0) + width); if (isNaN(contentHeight) && isNaN(contentWidth)) { me.done = false; return; } } if (calcWidth || calcHeight) { targetPadding = ownerContext.targetContext.getPaddingInfo(); } if (calcWidth && !ownerContext.setContentWidth(contentWidth + targetPadding.width)) { me.done = false; } if (calcHeight && !ownerContext.setContentHeight(contentHeight + targetPadding.height)) { me.done = false; } } } }); Ext.define('Ext.layout.container.Accordion', { extend: Ext.layout.container.VBox , alias: ['layout.accordion'], alternateClassName: 'Ext.layout.AccordionLayout', targetCls: Ext.baseCSSPrefix + 'accordion-layout-ct', itemCls: [Ext.baseCSSPrefix + 'box-item', Ext.baseCSSPrefix + 'accordion-item'], align: 'stretch', fill : true, titleCollapse : true, hideCollapseTool : false, collapseFirst : undefined, animate : true, activeOnTop : false, multi: false, defaultAnimatePolicy: { y: true, height: true }, constructor: function() { var me = this; me.callParent(arguments); if (!me.multi && me.animate) { me.animatePolicy = Ext.apply({}, me.defaultAnimatePolicy); } else { me.animatePolicy = null; } }, beforeRenderItems: function (items) { var me = this, ln = items.length, i = 0, owner = me.owner, collapseFirst = me.collapseFirst, hasCollapseFirst = Ext.isDefined(collapseFirst), expandedItem = me.getExpanded(true)[0], multi = me.multi, comp; for (; i < ln; i++) { comp = items[i]; if (!comp.rendered) { if (!multi || comp.collapsible !== false) { comp.collapsible = true; } if (comp.collapsible) { if (hasCollapseFirst) { comp.collapseFirst = collapseFirst; } if (me.hideCollapseTool) { comp.hideCollapseTool = me.hideCollapseTool; comp.titleCollapse = true; } else if (me.titleCollapse && comp.titleCollapse === undefined) { comp.titleCollapse = me.titleCollapse; } } delete comp.hideHeader; delete comp.width; comp.title = comp.title || ' '; comp.addBodyCls(Ext.baseCSSPrefix + 'accordion-body'); if (!multi) { if (expandedItem) { comp.collapsed = expandedItem !== comp; } else if (comp.hasOwnProperty('collapsed') && comp.collapsed === false) { expandedItem = comp; } else { comp.collapsed = true; } owner.mon(comp, 'show', me.onComponentShow, me); } comp.headerOverCls = Ext.baseCSSPrefix + 'accordion-hd-over'; } } if (!me.processing && !multi) { if (!expandedItem) { if (ln) { items[0].collapsed = false; } } else if (me.activeOnTop) { expandedItem.collapsed = false; me.configureItem(expandedItem); if (owner.items.indexOf(expandedItem) > 0) { owner.insert(0, expandedItem); } } } }, getItemsRenderTree: function(items) { this.beforeRenderItems(items); return this.callParent(arguments); }, renderItems : function(items, target) { this.beforeRenderItems(items); this.callParent(arguments); }, configureItem: function(item) { this.callParent(arguments); item.animCollapse = item.border = false; if (this.fill) { item.flex = 1; } }, beginLayout: function (ownerContext) { this.callParent(arguments); this.updatePanelClasses(ownerContext); }, updatePanelClasses: function(ownerContext) { var children = ownerContext.visibleItems, ln = children.length, siblingCollapsed = true, i, child, header; for (i = 0; i < ln; i++) { child = children[i]; header = child.header; header.addCls(Ext.baseCSSPrefix + 'accordion-hd'); if (siblingCollapsed) { header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded'); } else { header.addCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded'); } if (i + 1 == ln && child.collapsed) { header.addCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed'); } else { header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed'); } siblingCollapsed = child.collapsed; } }, onBeforeComponentExpand: function(toExpand) { var me = this, owner = me.owner, multi = me.multi, animate = me.animate, moveToTop = !multi && !me.animate && me.activeOnTop, expanded, previousValue; if (!me.processing) { me.processing = true; previousValue = owner.deferLayouts; owner.deferLayouts = true; if (!multi) { expanded = me.getExpanded()[0]; if (expanded && expanded !== toExpand) { expanded.collapse(); } } if (moveToTop) { Ext.suspendLayouts(); owner.insert(0, toExpand); Ext.resumeLayouts(); } owner.deferLayouts = previousValue; me.processing = false; } }, onBeforeComponentCollapse: function(comp) { var me = this, owner = me.owner, toExpand, expanded, previousValue; if (me.owner.items.getCount() === 1) { return false; } if (!me.processing) { me.processing = true; previousValue = owner.deferLayouts; owner.deferLayouts = true; toExpand = comp.next() || comp.prev(); if (me.multi) { expanded = me.getExpanded(); if (expanded.length === 1) { toExpand.expand(); } } else if (toExpand) { toExpand.expand(); } owner.deferLayouts = previousValue; me.processing = false; } }, onComponentShow: function(comp) { this.onBeforeComponentExpand(comp); }, onRemove: function(panel, isDestroying){ var me = this, item; me.callParent(arguments); if (!me.owner.destroying && !me.multi && !panel.collapsed) { item = me.owner.items.first(); if (item) { item.expand(); } } }, getExpanded: function(explicitCheck){ var items = this.owner.items.items, len = items.length, i = 0, out = [], add, item; for (; i < len; ++i) { item = items[i]; if (!item.hidden) { if (explicitCheck) { add = item.hasOwnProperty('collapsed') && item.collapsed === false; } else { add = !item.collapsed; } if (add) { out.push(item); } } } return out; } }); Ext.define('Ext.resizer.Splitter', { extend: Ext.Component , alias: 'widget.splitter', childEls: [ 'collapseEl' ], renderTpl: [ '', '', '' ], baseCls: Ext.baseCSSPrefix + 'splitter', collapsedClsInternal: Ext.baseCSSPrefix + 'splitter-collapsed', canResize: true, collapsible: false, collapseOnDblClick: true, defaultSplitMin: 40, defaultSplitMax: 1000, collapseTarget: 'next', horizontal: false, vertical: false, size: 5, ariaRole: 'separator', getTrackerConfig: function () { return { xclass: 'Ext.resizer.SplitterTracker', el: this.el, splitter: this }; }, beforeRender: function() { var me = this, target = me.getCollapseTarget(); me.callParent(); if (target.collapsed) { me.addCls(me.collapsedClsInternal); } if (!me.canResize) { me.addCls(me.baseCls + '-noresize'); } Ext.applyIf(me.renderData, { collapseDir: me.getCollapseDirection(), collapsible: me.collapsible || target.collapsible }); me.protoEl.unselectable(); }, onRender: function() { var me = this, collapseEl; me.callParent(arguments); if (me.performCollapse !== false) { if (me.renderData.collapsible) { me.mon(me.collapseEl, 'click', me.toggleTargetCmp, me); } if (me.collapseOnDblClick) { me.mon(me.el, 'dblclick', me.toggleTargetCmp, me); } } me.mon(me.getCollapseTarget(), { collapse: me.onTargetCollapse, expand: me.onTargetExpand, beforeexpand: me.onBeforeTargetExpand, beforecollapse: me.onBeforeTargetCollapse, scope: me }); if (me.canResize) { me.tracker = Ext.create(me.getTrackerConfig()); me.relayEvents(me.tracker, [ 'beforedragstart', 'dragstart', 'dragend' ]); } collapseEl = me.collapseEl; if (collapseEl) { collapseEl.lastCollapseDirCls = me.collapseDirProps[me.collapseDirection].cls; } }, getCollapseDirection: function() { var me = this, dir = me.collapseDirection, collapseTarget, idx, items, type; if (!dir) { collapseTarget = me.collapseTarget; if (collapseTarget.isComponent) { dir = collapseTarget.collapseDirection; } if (!dir) { type = me.ownerCt.layout.type; if (collapseTarget.isComponent) { items = me.ownerCt.items; idx = Number(items.indexOf(collapseTarget) === items.indexOf(me) - 1) << 1 | Number(type === 'hbox'); } else { idx = Number(me.collapseTarget === 'prev') << 1 | Number(type === 'hbox'); } dir = ['bottom', 'right', 'top', 'left'][idx]; } me.collapseDirection = dir; } me.setOrientation((dir === 'top' || dir === 'bottom') ? 'horizontal' : 'vertical'); return dir; }, getCollapseTarget: function() { var me = this; return me.collapseTarget.isComponent ? me.collapseTarget : me.collapseTarget === 'prev' ? me.previousSibling() : me.nextSibling(); }, setCollapseEl: function(display){ var el = this.collapseEl; if (el) { el.setDisplayed(display); } }, onBeforeTargetExpand: function(target) { this.setCollapseEl('none'); }, onBeforeTargetCollapse: function(){ this.setCollapseEl('none'); }, onTargetCollapse: function(target) { this.el.addCls([this.collapsedClsInternal, this.collapsedCls]); this.setCollapseEl(''); }, onTargetExpand: function(target) { this.el.removeCls([this.collapsedClsInternal, this.collapsedCls]); this.setCollapseEl(''); }, collapseDirProps: { top: { cls: Ext.baseCSSPrefix + 'layout-split-top' }, right: { cls: Ext.baseCSSPrefix + 'layout-split-right' }, bottom: { cls: Ext.baseCSSPrefix + 'layout-split-bottom' }, left: { cls: Ext.baseCSSPrefix + 'layout-split-left' } }, orientationProps: { horizontal: { opposite: 'vertical', fixedAxis: 'height', stretchedAxis: 'width' }, vertical: { opposite: 'horizontal', fixedAxis: 'width', stretchedAxis: 'height' } }, applyCollapseDirection: function () { var me = this, collapseEl = me.collapseEl, collapseDirProps = me.collapseDirProps[me.collapseDirection], cls; if (collapseEl) { cls = collapseEl.lastCollapseDirCls; if (cls) { collapseEl.removeCls(cls); } collapseEl.addCls(collapseEl.lastCollapseDirCls = collapseDirProps.cls); } }, applyOrientation: function () { var me = this, orientation = me.orientation, orientationProps = me.orientationProps[orientation], defaultSize = me.size, fixedSizeProp = orientationProps.fixedAxis, stretchSizeProp = orientationProps.stretchedAxis, cls = me.baseCls + '-'; me[orientation] = true; me[orientationProps.opposite] = false; if (!me.hasOwnProperty(fixedSizeProp) || me[fixedSizeProp] === '100%') { me[fixedSizeProp] = defaultSize; } if (!me.hasOwnProperty(stretchSizeProp) || me[stretchSizeProp] === defaultSize) { me[stretchSizeProp] = '100%'; } me.removeCls(cls + orientationProps.opposite); me.addCls(cls + orientation); }, setOrientation: function (orientation) { var me = this; if (me.orientation !== orientation) { me.orientation = orientation; me.applyOrientation(); } }, updateOrientation: function () { delete this.collapseDirection; this.getCollapseDirection(); this.applyCollapseDirection(); }, toggleTargetCmp: function(e, t) { var cmp = this.getCollapseTarget(), placeholder = cmp.placeholder, toggle; if (Ext.isFunction(cmp.expand) && Ext.isFunction(cmp.collapse)) { if (placeholder && !placeholder.hidden) { toggle = true; } else { toggle = !cmp.hidden; } if (toggle) { if (cmp.collapsed) { cmp.expand(); } else if (cmp.collapseDirection) { cmp.collapse(); } else { cmp.collapse(this.renderData.collapseDir); } } } }, setSize: function() { var me = this; me.callParent(arguments); if (Ext.isIE && me.el) { me.el.repaint(); } }, beforeDestroy: function(){ Ext.destroy(this.tracker); this.callParent(); } }); Ext.define('Ext.resizer.BorderSplitter', { extend: Ext.resizer.Splitter , alias: 'widget.bordersplitter', collapseTarget: null, getTrackerConfig: function () { var trackerConfig = this.callParent(); trackerConfig.xclass = 'Ext.resizer.BorderSplitterTracker'; return trackerConfig; } }); Ext.define('Ext.layout.container.Border', { extend: Ext.layout.container.Container , alias: 'layout.border', alternateClassName: 'Ext.layout.BorderLayout', targetCls: Ext.baseCSSPrefix + 'border-layout-ct', itemCls: [Ext.baseCSSPrefix + 'border-item', Ext.baseCSSPrefix + 'box-item'], type: 'border', isBorderLayout: true, padding: undefined, percentageRe: /(\d+)%/, horzPositionProp: 'left', padOnContainerProp: 'left', padNotOnContainerProp: 'right', axisProps: { horz: { borderBegin: 'west', borderEnd: 'east', horizontal: true, posProp: 'x', sizeProp: 'width', sizePropCap: 'Width' }, vert: { borderBegin: 'north', borderEnd: 'south', horizontal: false, posProp: 'y', sizeProp: 'height', sizePropCap: 'Height' } }, centerRegion: null, manageMargins: true, panelCollapseAnimate: true, panelCollapseMode: 'placeholder', regionWeights: { north: 20, south: 10, center: 0, west: -10, east: -20 }, beginAxis: function (ownerContext, regions, name) { var me = this, props = me.axisProps[name], isVert = !props.horizontal, sizeProp = props.sizeProp, totalFlex = 0, childItems = ownerContext.childItems, length = childItems.length, center, i, childContext, centerFlex, comp, region, match, size, type, target, placeholder; for (i = 0; i < length; ++i) { childContext = childItems[i]; comp = childContext.target; childContext.layoutPos = {}; if (comp.region) { childContext.region = region = comp.region; childContext.isCenter = comp.isCenter; childContext.isHorz = comp.isHorz; childContext.isVert = comp.isVert; childContext.weight = comp.weight || me.regionWeights[region] || 0; regions[comp.id] = childContext; if (comp.isCenter) { center = childContext; centerFlex = comp.flex; ownerContext.centerRegion = center; continue; } if (isVert !== childContext.isVert) { continue; } childContext.reverseWeighting = (region == props.borderEnd); size = comp[sizeProp]; type = typeof size; if (!comp.collapsed) { if (type == 'string' && (match = me.percentageRe.exec(size))) { childContext.percentage = parseInt(match[1], 10); } else if (comp.flex) { totalFlex += childContext.flex = comp.flex; } } } } if (center) { target = center.target; if ((placeholder = target.placeholderFor)) { if (!centerFlex && isVert === placeholder.collapsedVertical()) { centerFlex = 0; center.collapseAxis = name; } } else if (target.collapsed && (isVert === target.collapsedVertical())) { centerFlex = 0; center.collapseAxis = name; } } if (centerFlex == null) { centerFlex = 1; } totalFlex += centerFlex; return Ext.apply({ before : isVert ? 'top' : 'left', totalFlex : totalFlex }, props); }, beginLayout: function (ownerContext) { var me = this, items = me.getLayoutItems(), pad = me.padding, type = typeof pad, padOnContainer = false, childContext, item, length, i, regions, collapseTarget, doShow, hidden, region; if (pad) { if (type == 'string' || type == 'number') { pad = Ext.util.Format.parseBox(pad); } } else { pad = ownerContext.getEl('getTargetEl').getPaddingInfo(); padOnContainer = true; } ownerContext.outerPad = pad; ownerContext.padOnContainer = padOnContainer; for (i = 0, length = items.length; i < length; ++i) { item = items[i]; collapseTarget = me.getSplitterTarget(item); if (collapseTarget) { doShow = undefined; hidden = !!item.hidden; if (!collapseTarget.split) { if (collapseTarget.isCollapsingOrExpanding) { doShow = !!collapseTarget.collapsed; } } else if (hidden !== collapseTarget.hidden) { doShow = !collapseTarget.hidden; } if (doShow) { item.show(); } else if (doShow === false) { item.hide(); } } } me.callParent(arguments); items = ownerContext.childItems; length = items.length; regions = {}; ownerContext.borderAxisHorz = me.beginAxis(ownerContext, regions, 'horz'); ownerContext.borderAxisVert = me.beginAxis(ownerContext, regions, 'vert'); for (i = 0; i < length; ++i) { childContext = items[i]; collapseTarget = me.getSplitterTarget(childContext.target); if (collapseTarget) { region = regions[collapseTarget.id] if (!region) { region = ownerContext.getEl(collapseTarget.el, me); region.region = collapseTarget.region; } childContext.collapseTarget = collapseTarget = region; childContext.weight = collapseTarget.weight; childContext.reverseWeighting = collapseTarget.reverseWeighting; collapseTarget.splitter = childContext; childContext.isHorz = collapseTarget.isHorz; childContext.isVert = collapseTarget.isVert; } } me.sortWeightedItems(items, 'reverseWeighting'); me.setupSplitterNeighbors(items); }, calculate: function (ownerContext) { var me = this, containerSize = me.getContainerSize(ownerContext), childItems = ownerContext.childItems, length = childItems.length, horz = ownerContext.borderAxisHorz, vert = ownerContext.borderAxisVert, pad = ownerContext.outerPad, padOnContainer = ownerContext.padOnContainer, i, childContext, childMargins, size, horzPercentTotal, vertPercentTotal; horz.begin = pad[me.padOnContainerProp]; vert.begin = pad.top; horzPercentTotal = horz.end = horz.flexSpace = containerSize.width + (padOnContainer ? pad[me.padOnContainerProp] : -pad[me.padNotOnContainerProp]); vertPercentTotal = vert.end = vert.flexSpace = containerSize.height + (padOnContainer ? pad.top : -pad.bottom); for (i = 0; i < length; ++i) { childContext = childItems[i]; childMargins = childContext.getMarginInfo(); if (childContext.isHorz || childContext.isCenter) { horz.addUnflexed(childMargins.width); horzPercentTotal -= childMargins.width; } if (childContext.isVert || childContext.isCenter) { vert.addUnflexed(childMargins.height); vertPercentTotal -= childMargins.height; } if (!childContext.flex && !childContext.percentage) { if (childContext.isHorz || (childContext.isCenter && childContext.collapseAxis === 'horz')) { size = childContext.getProp('width'); horz.addUnflexed(size); if (childContext.collapseTarget) { horzPercentTotal -= size; } } else if (childContext.isVert || (childContext.isCenter && childContext.collapseAxis === 'vert')) { size = childContext.getProp('height'); vert.addUnflexed(size); if (childContext.collapseTarget) { vertPercentTotal -= size; } } } } for (i = 0; i < length; ++i) { childContext = childItems[i]; childMargins = childContext.getMarginInfo(); if (childContext.percentage) { if (childContext.isHorz) { size = Math.ceil(horzPercentTotal * childContext.percentage / 100); size = childContext.setWidth(size); horz.addUnflexed(size); } else if (childContext.isVert) { size = Math.ceil(vertPercentTotal * childContext.percentage / 100); size = childContext.setHeight(size); vert.addUnflexed(size); } } } for (i = 0; i < length; ++i) { childContext = childItems[i]; if (!childContext.isCenter) { me.calculateChildAxis(childContext, horz); me.calculateChildAxis(childContext, vert); } } if (me.finishAxis(ownerContext, vert) + me.finishAxis(ownerContext, horz) < 2) { me.done = false; } else { me.finishPositions(childItems); } }, calculateChildAxis: function (childContext, axis) { var collapseTarget = childContext.collapseTarget, setSizeMethod = 'set' + axis.sizePropCap, sizeProp = axis.sizeProp, childMarginSize = childContext.getMarginInfo()[sizeProp], region, isBegin, flex, pos, size; if (collapseTarget) { region = collapseTarget.region; } else { region = childContext.region; flex = childContext.flex; } isBegin = region == axis.borderBegin; if (!isBegin && region != axis.borderEnd) { childContext[setSizeMethod](axis.end - axis.begin - childMarginSize); pos = axis.begin; } else { if (flex) { size = Math.ceil(axis.flexSpace * (flex / axis.totalFlex)); size = childContext[setSizeMethod](size); } else if (childContext.percentage) { size = childContext.peek(sizeProp); } else { size = childContext.getProp(sizeProp); } size += childMarginSize; if (isBegin) { pos = axis.begin; axis.begin += size; } else { axis.end = pos = axis.end - size; } } childContext.layoutPos[axis.posProp] = pos; }, finishAxis: function (ownerContext, axis) { var size = axis.end - axis.begin, center = ownerContext.centerRegion; if (center) { center['set' + axis.sizePropCap](size - center.getMarginInfo()[axis.sizeProp]); center.layoutPos[axis.posProp] = axis.begin; } return Ext.isNumber(size) ? 1 : 0; }, finishPositions: function (childItems) { var length = childItems.length, index, childContext, marginProp = this.horzPositionProp; for (index = 0; index < length; ++index) { childContext = childItems[index]; childContext.setProp('x', childContext.layoutPos.x + childContext.marginInfo[marginProp]); childContext.setProp('y', childContext.layoutPos.y + childContext.marginInfo.top); } }, getLayoutItems: function() { var owner = this.owner, ownerItems = (owner && owner.items && owner.items.items) || [], length = ownerItems.length, items = [], i = 0, ownerItem, placeholderFor; for (; i < length; i++) { ownerItem = ownerItems[i]; placeholderFor = ownerItem.placeholderFor; if (ownerItem.hidden || ((!ownerItem.floated || ownerItem.isCollapsingOrExpanding === 2) && !(placeholderFor && placeholderFor.isCollapsingOrExpanding === 2))) { items.push(ownerItem); } } return items; }, getPlaceholder: function (comp) { return comp.getPlaceholder && comp.getPlaceholder(); }, getSplitterTarget: function (splitter) { var collapseTarget = splitter.collapseTarget; if (collapseTarget && collapseTarget.collapsed) { return collapseTarget.placeholder || collapseTarget; } return collapseTarget; }, isItemBoxParent: function (itemContext) { return true; }, isItemShrinkWrap: function (item) { return true; }, insertSplitter: function (item, index, hidden, splitterCfg) { var region = item.region, splitter = Ext.apply({ xtype: 'bordersplitter', collapseTarget: item, id: item.id + '-splitter', hidden: hidden, canResize: item.splitterResize !== false, splitterFor: item }, splitterCfg), at = index + ((region === 'south' || region === 'east') ? 0 : 1); if (item.collapseMode === 'mini') { splitter.collapsedCls = item.collapsedCls; } item.splitter = this.owner.add(at, splitter); }, onAdd: function (item, index) { var me = this, placeholderFor = item.placeholderFor, region = item.region, split, hidden, cfg; me.callParent(arguments); if (region) { Ext.apply(item, me.regionFlags[region]); if (item.initBorderRegion) { item.initBorderRegion(); } if (region === 'center') { me.centerRegion = item; } else { split = item.split; hidden = !!item.hidden; if (typeof split === 'object') { cfg = split; split = true; } if ((item.isHorz || item.isVert) && (split || item.collapseMode == 'mini')) { me.insertSplitter(item, index, hidden || !split, cfg); } } if (!item.hasOwnProperty('collapseMode')) { item.collapseMode = me.panelCollapseMode; } if (!item.hasOwnProperty('animCollapse')) { if (item.collapseMode !== 'placeholder') { item.animCollapse = false; } else { item.animCollapse = me.panelCollapseAnimate; } } } else if (placeholderFor) { Ext.apply(item, me.regionFlags[placeholderFor.region]); item.region = placeholderFor.region; item.weight = placeholderFor.weight; } }, onDestroy: function() { this.centerRegion = null; this.callParent(); }, onRemove: function (comp, isDestroying) { var me = this, region = comp.region, splitter = comp.splitter, owner = me.owner, destroying = owner.destroying, el; if (region) { if (comp.isCenter) { me.centerRegion = null; } delete comp.isCenter; delete comp.isHorz; delete comp.isVert; if (splitter && !owner.destroying) { owner.doRemove(splitter, true); } delete comp.splitter; } me.callParent(arguments); if (!destroying && !isDestroying && comp.rendered) { el = comp.getEl(); el.setStyle('top', ''); el.setStyle(me.horzPositionProp, ''); } }, regionMeta: { center: { splitterDelta: 0 }, north: { splitterDelta: 1 }, south: { splitterDelta: -1 }, west: { splitterDelta: 1 }, east: { splitterDelta: -1 } }, regionFlags: { center: { isCenter: true, isHorz: false, isVert: false }, north: { isCenter: false, isHorz: false, isVert: true, collapseDirection: 'top' }, south: { isCenter: false, isHorz: false, isVert: true, collapseDirection: 'bottom' }, west: { isCenter: false, isHorz: true, isVert: false, collapseDirection: 'left' }, east: { isCenter: false, isHorz: true, isVert: false, collapseDirection: 'right' } }, setupSplitterNeighbors: function (items) { var edgeRegions = { }, length = items.length, touchedRegions = this.touchedRegions, i, j, center, count, edge, comp, region, splitter, touched; for (i = 0; i < length; ++i) { comp = items[i].target; region = comp.region; if (comp.isCenter) { center = comp; } else if (region) { touched = touchedRegions[region]; for (j = 0, count = touched.length; j < count; ++j) { edge = edgeRegions[touched[j]]; if (edge) { edge.neighbors.push(comp); } } if (comp.placeholderFor) { splitter = comp.placeholderFor.splitter; } else { splitter = comp.splitter; } if (splitter) { splitter.neighbors = []; } edgeRegions[region] = splitter; } } if (center) { touched = touchedRegions.center; for (j = 0, count = touched.length; j < count; ++j) { edge = edgeRegions[touched[j]]; if (edge) { edge.neighbors.push(center); } } } }, touchedRegions: { center: [ 'north', 'south', 'east', 'west' ], north: [ 'north', 'east', 'west' ], south: [ 'south', 'east', 'west' ], east: [ 'east', 'north', 'south' ], west: [ 'west', 'north', 'south' ] }, sizePolicies: { vert: { readsWidth: 0, readsHeight: 1, setsWidth: 1, setsHeight: 0 }, horz: { readsWidth: 1, readsHeight: 0, setsWidth: 0, setsHeight: 1 }, flexAll: { readsWidth: 0, readsHeight: 0, setsWidth: 1, setsHeight: 1 } }, getItemSizePolicy: function (item) { var me = this, policies = this.sizePolicies, collapseTarget, size, policy, placeholderFor; if (item.isCenter) { placeholderFor = item.placeholderFor; if (placeholderFor) { if (placeholderFor.collapsedVertical()) { return policies.vert; } return policies.horz; } if (item.collapsed) { if (item.collapsedVertical()) { return policies.vert; } return policies.horz; } return policies.flexAll; } collapseTarget = item.collapseTarget; if (collapseTarget) { return collapseTarget.isVert ? policies.vert : policies.horz; } if (item.region) { if (item.isVert) { size = item.height; policy = policies.vert; } else { size = item.width; policy = policies.horz; } if (item.flex || (typeof size == 'string' && me.percentageRe.test(size))) { return policies.flexAll; } return policy; } return me.autoSizePolicy; } }, function () { var methods = { addUnflexed: function (px) { this.flexSpace = Math.max(this.flexSpace - px, 0); } }, props = this.prototype.axisProps; Ext.apply(props.horz, methods); Ext.apply(props.vert, methods); }); Ext.define('Ext.layout.container.Card', { extend: Ext.layout.container.Fit , alternateClassName: 'Ext.layout.CardLayout', alias: 'layout.card', type: 'card', hideInactive: true, deferredRender : false, getRenderTree: function () { var me = this, activeItem = me.getActiveItem(); if (activeItem) { if (activeItem.hasListeners.beforeactivate && activeItem.fireEvent('beforeactivate', activeItem) === false) { activeItem = me.activeItem = me.owner.activeItem = null; } else if (activeItem.hasListeners.activate) { activeItem.on({ boxready: function() { activeItem.fireEvent('activate', activeItem); }, single: true }); } if (me.deferredRender) { if (activeItem) { return me.getItemsRenderTree([activeItem]); } } else { return me.callParent(arguments); } } }, renderChildren: function () { var me = this, active = me.getActiveItem(); if (!me.deferredRender) { me.callParent(); } else if (active) { me.renderItems([active], me.getRenderTarget()); } }, isValidParent : function(item, target, position) { var itemEl = item.el ? item.el.dom : Ext.getDom(item); return (itemEl && itemEl.parentNode === (target.dom || target)) || false; }, getActiveItem: function() { var me = this, result = me.parseActiveItem(me.activeItem || (me.owner && me.owner.activeItem)); if (result && me.owner.items.indexOf(result) != -1) { me.activeItem = result; } else { me.activeItem = null; } return me.activeItem; }, parseActiveItem: function(item) { if (item && item.isComponent) { return item; } else if (typeof item == 'number' || item === undefined) { return this.getLayoutItems()[item || 0]; } else { return this.owner.getComponent(item); } }, configureItem: function(item) { if (item === this.getActiveItem()) { item.hidden = false; } else { item.hidden = true; } this.callParent(arguments); }, onRemove: function(component) { this.callParent(arguments); if (component === this.activeItem) { this.activeItem = null; } }, getAnimation: function(newCard, owner) { var newAnim = (newCard || {}).cardSwitchAnimation; if (newAnim === false) { return false; } return newAnim || owner.cardSwitchAnimation; }, getNext: function() { var wrap = arguments[0], items = this.getLayoutItems(), index = Ext.Array.indexOf(items, this.activeItem); return items[index + 1] || (wrap ? items[0] : false); }, next: function() { var anim = arguments[0], wrap = arguments[1]; return this.setActiveItem(this.getNext(wrap), anim); }, getPrev: function() { var wrap = arguments[0], items = this.getLayoutItems(), index = Ext.Array.indexOf(items, this.activeItem); return items[index - 1] || (wrap ? items[items.length - 1] : false); }, prev: function() { var anim = arguments[0], wrap = arguments[1]; return this.setActiveItem(this.getPrev(wrap), anim); }, setActiveItem: function(newCard) { var me = this, owner = me.owner, oldCard = me.activeItem, rendered = owner.rendered, newIndex; newCard = me.parseActiveItem(newCard); newIndex = owner.items.indexOf(newCard); if (newIndex == -1) { newIndex = owner.items.items.length; Ext.suspendLayouts(); newCard = owner.add(newCard); Ext.resumeLayouts(); } if (newCard && oldCard != newCard) { if (newCard.fireEvent('beforeactivate', newCard, oldCard) === false) { return false; } if (oldCard && oldCard.fireEvent('beforedeactivate', oldCard, newCard) === false) { return false; } if (rendered) { Ext.suspendLayouts(); if (!newCard.rendered) { me.renderItem(newCard, me.getRenderTarget(), owner.items.length); } if (oldCard) { if (me.hideInactive) { oldCard.hide(); oldCard.hiddenByLayout = true; } oldCard.fireEvent('deactivate', oldCard, newCard); } if (newCard.hidden) { newCard.show(); } if (!newCard.hidden) { me.activeItem = newCard; } Ext.resumeLayouts(true); } else { me.activeItem = newCard; } newCard.fireEvent('activate', newCard, oldCard); return me.activeItem; } return false; } }); Ext.define('Ext.layout.container.Column', { extend: Ext.layout.container.Auto , alias: ['layout.column'], alternateClassName: 'Ext.layout.ColumnLayout', type: 'column', itemCls: Ext.baseCSSPrefix + 'column', targetCls: Ext.baseCSSPrefix + 'column-layout-ct', columnWidthSizePolicy: { readsWidth: 0, readsHeight: 1, setsWidth: 1, setsHeight: 0 }, createsInnerCt: true, manageOverflow: true, isItemShrinkWrap: function(ownerContext){ return true; }, getItemSizePolicy: function (item, ownerSizeModel) { if (item.columnWidth) { if (!ownerSizeModel) { ownerSizeModel = this.owner.getSizeModel(); } if (!ownerSizeModel.width.shrinkWrap) { return this.columnWidthSizePolicy; } } return this.autoSizePolicy; }, calculateItems: function (ownerContext, containerSize) { var me = this, targetContext = ownerContext.targetContext, items = ownerContext.childItems, len = items.length, contentWidth = 0, gotWidth = containerSize.gotWidth, blocked, availableWidth, i, itemContext, itemMarginWidth, itemWidth; if (gotWidth === false) { targetContext.domBlock(me, 'width'); blocked = true; } else if (gotWidth) { availableWidth = containerSize.width; } else { return true; } for (i = 0; i < len; ++i) { itemContext = items[i]; itemMarginWidth = itemContext.getMarginInfo().width; if (!itemContext.widthModel.calculated) { itemWidth = itemContext.getProp('width'); if (typeof itemWidth != 'number') { itemContext.block(me, 'width'); blocked = true; } contentWidth += itemWidth + itemMarginWidth; } } if (!blocked) { availableWidth = (availableWidth < contentWidth) ? 0 : availableWidth - contentWidth; for (i = 0; i < len; ++i) { itemContext = items[i]; if (itemContext.widthModel.calculated) { itemMarginWidth = itemContext.marginInfo.width; itemWidth = itemContext.target.columnWidth; itemWidth = Math.floor(itemWidth * availableWidth) - itemMarginWidth; itemWidth = itemContext.setWidth(itemWidth); contentWidth += itemWidth + itemMarginWidth; } } ownerContext.setContentWidth(contentWidth + ownerContext.paddingContext.getPaddingInfo().width); } return !blocked; }, setCtSizeIfNeeded: function(ownerContext, containerSize) { var me = this, padding = ownerContext.paddingContext.getPaddingInfo(); me.callParent(arguments); if ((Ext.isIEQuirks || Ext.isIE7m) && me.isShrinkWrapTpl && padding.right) { ownerContext.outerCtContext.setProp('width', containerSize.width + padding.left); } } }); Ext.define('Ext.layout.container.Form', { alias: 'layout.form', extend: Ext.layout.container.Container , alternateClassName: 'Ext.layout.FormLayout', tableCls: Ext.baseCSSPrefix + 'form-layout-table', type: 'form', createsInnerCt: true, manageOverflow: true, lastOverflowAdjust: { width: 0, height: 0 }, childEls: ['formTable'], padRow: '', renderTpl: [ '', '{%this.renderBody(out,values)%}', '', '{%this.renderPadder(out,values)%}' ], getRenderData: function(){ var data = this.callParent(); data.tableCls = this.tableCls; return data; }, calculate : function (ownerContext) { var me = this, containerSize = me.getContainerSize(ownerContext, true), tableWidth, childItems, i = 0, length, shrinkwrapHeight = ownerContext.sizeModel.height.shrinkWrap; if (shrinkwrapHeight) { if (ownerContext.hasDomProp('containerChildrenSizeDone')) { ownerContext.setProp('contentHeight', me.formTable.dom.offsetHeight + ownerContext.targetContext.getPaddingInfo().height); } else { me.done = false; } } if (containerSize.gotWidth) { tableWidth = me.formTable.dom.offsetWidth; childItems = ownerContext.childItems; for (length = childItems.length; i < length; ++i) { childItems[i].setWidth(tableWidth, false); } } else { me.done = false; } }, getRenderTarget: function() { return this.formTable; }, getRenderTree: function() { var me = this, result = me.callParent(arguments), i, len; for (i = 0, len = result.length; i < len; i++) { result[i] = me.transformItemRenderTree(result[i]); } return result; }, transformItemRenderTree: function(item) { if (item.tag && item.tag == 'table') { item.tag = 'tbody'; item.role = 'presentation'; delete item.cellspacing; delete item.cellpadding; if (Ext.isIE6) { item.cn = this.padRow; } return item; } return { tag: 'tbody', role: 'presentation', cn: { tag: 'tr', role: 'presentation', cn: { tag: 'td', role: 'presentation', colspan: 3, style: 'width:100%', cn: item } } }; }, isValidParent: function(item, target, position) { return true; }, isItemShrinkWrap: function(item) { return ((item.shrinkWrap === true) ? 3 : item.shrinkWrap||0) & 2; }, getItemSizePolicy: function(item) { return { setsWidth: 1, setsHeight: 0 }; }, beginLayoutCycle: function (ownerContext, firstCycle) { var padEl = this.overflowPadderEl; if (padEl) { padEl.setStyle('display', 'none'); } if (!ownerContext.state.overflowAdjust) { ownerContext.state.overflowAdjust = this.lastOverflowAdjust; } }, calculateOverflow: function (ownerContext, containerSize, dimensions) { var me = this, targetContext = ownerContext.targetContext, manageOverflow = me.manageOverflow, state = ownerContext.state, overflowAdjust = state.overflowAdjust, padWidth, padHeight, padElContext, padding, scrollRangeFlags, scrollbarSize, contentW, contentH, ownerW, ownerH, scrollbars, xauto, yauto; if (manageOverflow && !state.secondPass && !me.reserveScrollbar) { xauto = (me.getOverflowXStyle(ownerContext) === 'auto'); yauto = (me.getOverflowYStyle(ownerContext) === 'auto'); if (!containerSize.gotWidth) { xauto = false; } if (!containerSize.gotHeight) { yauto = false; } if (xauto || yauto) { scrollbarSize = Ext.getScrollbarSize(); contentW = ownerContext.peek('contentWidth'); contentH = ownerContext.peek('contentHeight'); padding = targetContext.getPaddingInfo(); contentW -= padding.width; contentH -= padding.height; ownerW = containerSize.width; ownerH = containerSize.height; scrollbars = me.getScrollbarsNeeded(ownerW, ownerH, contentW, contentH); state.overflowState = scrollbars; if (typeof dimensions == 'number') { scrollbars &= ~dimensions; } overflowAdjust = { width: (xauto && (scrollbars & 2)) ? scrollbarSize.width : 0, height: (yauto && (scrollbars & 1)) ? scrollbarSize.height : 0 }; if (overflowAdjust.width !== me.lastOverflowAdjust.width || overflowAdjust.height !== me.lastOverflowAdjust.height) { me.done = false; ownerContext.invalidate({ state: { overflowAdjust: overflowAdjust, overflowState: state.overflowState, secondPass: true } }); } } } if (!me.done) { return; } padElContext = ownerContext.padElContext || (ownerContext.padElContext = ownerContext.getEl('overflowPadderEl', me)); if (padElContext) { scrollbars = state.overflowState; padWidth = ownerContext.peek('contentWidth'); padHeight = 1; if (scrollbars) { padding = targetContext.getPaddingInfo(); scrollRangeFlags = me.scrollRangeFlags; if ((scrollbars & 2) && (scrollRangeFlags & 1)) { padHeight += padding.bottom; } if ((scrollbars & 1) && (scrollRangeFlags & 4)) { padWidth += padding.right; } padElContext.setProp('display', ''); padElContext.setSize(padWidth, padHeight); } else { padElContext.setProp('display', 'none'); } } }, completeLayout: function (ownerContext) { this.lastOverflowAdjust = ownerContext.state.overflowAdjust; }, doRenderPadder: function (out, renderData) { var me = renderData.$layout, owner = me.owner, scrollRangeFlags = me.getScrollRangeFlags(); if (me.manageOverflow) { if (scrollRangeFlags & 5) { out.push(''); me.scrollRangeFlags = scrollRangeFlags; } } }, getContainerSize : function(ownerContext, inDom, ignoreOverflow) { var targetContext = ownerContext.targetContext, frameInfo = targetContext.getFrameInfo(), padding = targetContext.getPaddingInfo(), got = 0, needed = 0, overflowAdjust = ignoreOverflow ? null : ownerContext.state.overflowAdjust, gotWidth, gotHeight, width, height; if (!ownerContext.widthModel.shrinkWrap) { ++needed; width = inDom ? targetContext.getDomProp('width') : targetContext.getProp('width'); gotWidth = (typeof width == 'number'); if (gotWidth) { ++got; width -= frameInfo.width + padding.width; if (overflowAdjust) { width -= overflowAdjust.width; } } } if (!ownerContext.heightModel.shrinkWrap) { ++needed; height = inDom ? targetContext.getDomProp('height') : targetContext.getProp('height'); gotHeight = (typeof height == 'number'); if (gotHeight) { ++got; height -= frameInfo.height + padding.height; if (overflowAdjust) { height -= overflowAdjust.height; } } } return { width: width, height: height, needed: needed, got: got, gotAll: got == needed, gotWidth: gotWidth, gotHeight: gotHeight }; }, getOverflowXStyle: function(ownerContext) { var me = this; return me.overflowXStyle || (me.overflowXStyle = me.owner.scrollFlags.overflowX || ownerContext.targetContext.getStyle('overflow-x')); }, getOverflowYStyle: function(ownerContext) { var me = this; return me.overflowYStyle || (me.overflowYStyle = me.owner.scrollFlags.overflowY || ownerContext.targetContext.getStyle('overflow-y')); }, getScrollRangeFlags: (function () { var flags = -1; return function () { if (flags < 0) { var div = Ext.getBody().createChild({ cls: Ext.baseCSSPrefix + 'border-box', role: 'presentation', style: { width: '100px', height: '100px', padding: '10px', overflow: 'auto' }, children: [{ role: 'presentation', style: { border: '1px solid red', width: '150px', height: '150px', margin: '0 5px 5px 0' } }] }), scrollHeight = div.dom.scrollHeight, scrollWidth = div.dom.scrollWidth, heightFlags = { 175: 0, 165: 1, 170: 2, 160: 3 }, widthFlags = { 175: 0, 165: 4, 170: 8, 160: 12 }; flags = (heightFlags[scrollHeight] || 0) | (widthFlags[scrollWidth] || 0); div.remove(); } return flags; }; }()), initLayout: function() { var me = this, scrollbarWidth = Ext.getScrollbarSize().width; me.callParent(); if (scrollbarWidth && me.manageOverflow && !me.hasOwnProperty('lastOverflowAdjust')) { if (me.owner.scrollFlags.y || me.reserveScrollbar) { me.lastOverflowAdjust = { width: scrollbarWidth, height: 0 }; } } }, setupRenderTpl: function (renderTpl) { this.callParent(arguments); renderTpl.renderPadder = this.doRenderPadder; } }); Ext.define('Ext.menu.Item', { extend: Ext.Component , alias: 'widget.menuitem', alternateClassName: 'Ext.menu.TextItem', isMenuItem: true, mixins: { queryable: Ext.Queryable }, activeCls: Ext.baseCSSPrefix + 'menu-item-active', ariaRole: 'menuitem', canActivate: true, clickHideDelay: 0, destroyMenu: true, disabledCls: Ext.baseCSSPrefix + 'menu-item-disabled', hideOnClick: true, menuAlign: 'tl-tr?', menuExpandDelay: 200, menuHideDelay: 200, tooltipType: 'qtip', arrowCls: Ext.baseCSSPrefix + 'menu-item-arrow', baseIconCls: Ext.baseCSSPrefix + 'menu-item-icon', textCls: Ext.baseCSSPrefix + 'menu-item-text', indentCls: Ext.baseCSSPrefix + 'menu-item-indent', indentNoSeparatorCls: Ext.baseCSSPrefix + 'menu-item-indent-no-separator', indentRightIconCls: Ext.baseCSSPrefix + 'menu-item-indent-right-icon', indentRightArrowCls: Ext.baseCSSPrefix + 'menu-item-indent-right-arrow', linkCls: Ext.baseCSSPrefix + 'menu-item-link', childEls: [ 'itemEl', 'iconEl', 'textEl', 'arrowEl' ], renderTpl: [ '', '{text}', '', ' target="{hrefTarget}"', ' hidefocus="true"', ' unselectable="on"', '', ' tabIndex="{tabIndex}"', '', '>', '{text}', '', '', '', '', '', '', '', '', '', '', '' ], maskOnDisable: false, iconAlign: 'left', activate: function(skipCheck) { var me = this; if (skipCheck || (!me.activated && me.canActivate && me.rendered && !me.isDisabled() && me.isVisible())) { if (!me.plain) { me.el.addCls(me.activeCls); } me.focus(false, true); me.activated = true; if (me.hasListeners.activate) { me.fireEvent('activate', me); } } }, getFocusEl: function() { return this.itemEl; }, deactivate: function() { var me = this, parent; if (me.activated) { parent = me.up(''); if (!me.plain) { me.el.removeCls(me.activeCls); } if (parent) { parent.focus(false, true); } me.hideMenu(); me.activated = false; if (me.hasListeners.deactivate) { me.fireEvent('deactivate', me); } } }, deferHideMenu: function() { if (this.menu.isVisible()) { this.menu.hide(); } }, cancelDeferHide: function(){ clearTimeout(this.hideMenuTimer); }, deferHideParentMenus: function() { var ancestor; Ext.menu.Manager.hideAll(); if (!Ext.Element.getActiveElement()) { ancestor = this.up(':not([hidden])'); if (ancestor) { ancestor.focus(); } } }, expandMenu: function(delay) { var me = this; if (me.menu) { me.cancelDeferHide(); if (delay === 0) { me.doExpandMenu(); } else { clearTimeout(me.expandMenuTimer); me.expandMenuTimer = Ext.defer(me.doExpandMenu, Ext.isNumber(delay) ? delay : me.menuExpandDelay, me); } } }, doExpandMenu: function() { var me = this, menu = me.menu; if (me.activated && (!menu.rendered || !menu.isVisible())) { me.parentMenu.activeChild = menu; menu.parentItem = me; menu.parentMenu = me.parentMenu; menu.showBy(me, me.menuAlign); } }, getRefItems: function(deep) { var menu = this.menu, items; if (menu) { items = menu.getRefItems(deep); items.unshift(menu); } return items || []; }, hideMenu: function(delay) { var me = this; if (me.menu) { clearTimeout(me.expandMenuTimer); me.hideMenuTimer = Ext.defer(me.deferHideMenu, Ext.isNumber(delay) ? delay : me.menuHideDelay, me); } }, initComponent: function() { var me = this, prefix = Ext.baseCSSPrefix, cls = [prefix + 'menu-item'], menu; me.addEvents( 'activate', 'click', 'deactivate', 'textchange', 'iconchange' ); if (me.plain) { cls.push(prefix + 'menu-item-plain'); } if (me.cls) { cls.push(me.cls); } me.cls = cls.join(' '); if (me.menu) { menu = me.menu; delete me.menu; me.setMenu(menu); } me.callParent(arguments); }, onClick: function(e) { var me = this, clickHideDelay = me.clickHideDelay; if (!me.href) { e.stopEvent(); } if (me.disabled) { return; } if (me.hideOnClick) { if (!clickHideDelay) { me.deferHideParentMenus(); } else { me.deferHideParentMenusTimer = Ext.defer(me.deferHideParentMenus, clickHideDelay, me); } } Ext.callback(me.handler, me.scope || me, [me, e]); me.fireEvent('click', me, e); if (!me.hideOnClick) { me.focus(); } }, onRemoved: function() { var me = this; if (me.activated && me.parentMenu.activeItem === me) { me.parentMenu.deactivateActiveItem(); } me.callParent(arguments); me.parentMenu = me.ownerButton = null; }, beforeDestroy: function() { var me = this; if (me.rendered) { me.clearTip(); } me.callParent(); }, onDestroy: function() { var me = this; clearTimeout(me.expandMenuTimer); me.cancelDeferHide(); clearTimeout(me.deferHideParentMenusTimer); me.setMenu(null); me.callParent(arguments); }, beforeRender: function() { var me = this, glyph = me.glyph, glyphFontFamily = Ext._glyphFontFamily, hasIcon = !!(me.icon || me.iconCls || glyph), hasMenu = !!me.menu, rightIcon = ((me.iconAlign === 'right') && !hasMenu), isCheckItem = me.isMenuCheckItem, indentCls = [], ownerCt = me.ownerCt, isOwnerPlain = ownerCt.plain, glyphParts; me.callParent(); if (hasIcon) { if (hasMenu && me.showCheckbox) { hasIcon = false; } } if (typeof glyph === 'string') { glyphParts = glyph.split('@'); glyph = glyphParts[0]; glyphFontFamily = glyphParts[1]; } if (!isOwnerPlain || (hasIcon && !rightIcon) || isCheckItem) { if (ownerCt.showSeparator && !isOwnerPlain) { indentCls.push(me.indentCls); } else { indentCls.push(me.indentNoSeparatorCls); } } if (hasMenu) { indentCls.push(me.indentRightArrowCls); } else if (hasIcon && (rightIcon || isCheckItem)) { indentCls.push(me.indentRightIconCls); } Ext.applyIf(me.renderData, { href: me.href || '#', hrefTarget: me.hrefTarget, icon: me.icon, iconCls: me.iconCls, glyph: glyph, glyphCls: glyph ? Ext.baseCSSPrefix + 'menu-item-glyph' : undefined, glyphFontFamily: glyphFontFamily, hasIcon: hasIcon, hasMenu: hasMenu, indent: !isOwnerPlain || hasIcon || isCheckItem, isCheckItem: isCheckItem, rightIcon: rightIcon, plain: me.plain, text: me.text, arrowCls: me.arrowCls, baseIconCls: me.baseIconCls, textCls: me.textCls, indentCls: indentCls.join(' '), linkCls: me.linkCls, groupCls: me.group ? me.groupCls : '', tabIndex: me.tabIndex }); }, onRender: function() { var me = this; me.callParent(arguments); if (me.tooltip) { me.setTooltip(me.tooltip, true); } }, setMenu: function(menu, destroyMenu) { var me = this, oldMenu = me.menu, arrowEl = me.arrowEl; if (oldMenu) { delete oldMenu.parentItem; delete oldMenu.parentMenu; delete oldMenu.ownerItem; if (destroyMenu === true || (destroyMenu !== false && me.destroyMenu)) { Ext.destroy(oldMenu); } } if (menu) { me.menu = Ext.menu.Manager.get(menu); me.menu.ownerItem = me; } else { me.menu = null; } if (me.rendered && !me.destroying && arrowEl) { arrowEl[me.menu ? 'addCls' : 'removeCls'](me.arrowCls); } }, setHandler: function(fn, scope) { this.handler = fn || null; this.scope = scope; }, setIcon: function(icon){ var iconEl = this.iconEl, oldIcon = this.icon; if (iconEl) { iconEl.src = icon || Ext.BLANK_IMAGE_URL; } this.icon = icon; this.fireEvent('iconchange', this, oldIcon, icon); }, setIconCls: function(iconCls) { var me = this, iconEl = me.iconEl, oldCls = me.iconCls; if (iconEl) { if (me.iconCls) { iconEl.removeCls(me.iconCls); } if (iconCls) { iconEl.addCls(iconCls); } } me.iconCls = iconCls; me.fireEvent('iconchange', me, oldCls, iconCls); }, setText: function(text) { var me = this, el = me.textEl || me.el, oldText = me.text; me.text = text; if (me.rendered) { el.update(text || ''); me.ownerCt.updateLayout(); } me.fireEvent('textchange', me, oldText, text); }, getTipAttr: function(){ return this.tooltipType == 'qtip' ? 'data-qtip' : 'title'; }, clearTip: function() { if (Ext.quickTipsActive && Ext.isObject(this.tooltip)) { Ext.tip.QuickTipManager.unregister(this.itemEl); } }, setTooltip: function(tooltip, initial) { var me = this; if (me.rendered) { if (!initial) { me.clearTip(); } if (Ext.quickTipsActive && Ext.isObject(tooltip)) { Ext.tip.QuickTipManager.register(Ext.apply({ target: me.itemEl.id }, tooltip)); me.tooltip = tooltip; } else { me.itemEl.dom.setAttribute(me.getTipAttr(), tooltip); } } else { me.tooltip = tooltip; } return me; } }); Ext.define('Ext.menu.CheckItem', { extend: Ext.menu.Item , alias: 'widget.menucheckitem', checkedCls: Ext.baseCSSPrefix + 'menu-item-checked', uncheckedCls: Ext.baseCSSPrefix + 'menu-item-unchecked', groupCls: Ext.baseCSSPrefix + 'menu-group-icon', hideOnClick: false, checkChangeDisabled: false, ariaRole: 'menuitemcheckbox', childEls: [ 'itemEl', 'iconEl', 'textEl', 'checkEl' ], showCheckbox: true, isMenuCheckItem: true, checkboxCls: Ext.baseCSSPrefix + 'menu-item-checkbox', initComponent: function() { var me = this; me.checked = !!me.checked; me.addEvents( 'beforecheckchange', 'checkchange' ); me.callParent(arguments); Ext.menu.Manager.registerCheckable(me); if (me.group) { if (me.initialConfig.hideOnClick !== false) { me.hideOnClick = true; } } }, beforeRender: function() { var me = this; me.callParent(); Ext.apply(me.renderData, { checkboxCls: me.checkboxCls, showCheckbox: me.showCheckbox }); }, afterRender: function() { var me = this; me.callParent(); me.checked = !me.checked; me.setChecked(!me.checked, true); if (me.checkChangeDisabled) { me.disableCheckChange(); } }, disableCheckChange: function() { var me = this, checkEl = me.checkEl; if (checkEl) { checkEl.addCls(me.disabledCls); } if (!(Ext.isIE10p || (Ext.isIE9 && Ext.isStrict)) && me.rendered) { me.el.repaint(); } me.checkChangeDisabled = true; }, enableCheckChange: function() { var me = this, checkEl = me.checkEl; if (checkEl) { checkEl.removeCls(me.disabledCls); } me.checkChangeDisabled = false; }, onClick: function(e) { var me = this; if(!me.disabled && !me.checkChangeDisabled && !(me.checked && me.group)) { me.setChecked(!me.checked); } this.callParent([e]); }, onDestroy: function() { Ext.menu.Manager.unregisterCheckable(this); this.callParent(arguments); }, setChecked: function(checked, suppressEvents) { var me = this, checkedCls = me.checkedCls, uncheckedCls = me.uncheckedCls, el = me.el; if (me.checked !== checked && (suppressEvents || me.fireEvent('beforecheckchange', me, checked) !== false)) { if (el) { if (checked) { el.addCls(checkedCls); el.removeCls(uncheckedCls); } else { el.addCls(uncheckedCls); el.removeCls(checkedCls); } } me.checked = checked; Ext.menu.Manager.onCheckChange(me, checked); if (!suppressEvents) { Ext.callback(me.checkHandler, me.scope || me, [me, checked]); me.fireEvent('checkchange', me, checked); } } } }); Ext.define('Ext.menu.KeyNav', { extend: Ext.util.KeyNav , constructor: function(config) { var me = this; me.menu = config.target; me.callParent([Ext.apply({ down: me.down, enter: me.enter, esc: me.escape, left: me.left, right: me.right, space: me.enter, tab: me.tab, up: me.up }, config)]); }, down: function(e) { var me = this, fi = me.menu.focusedItem; if (fi && e.getKey() == Ext.EventObject.DOWN && me.isWhitelisted(fi)) { return true; } me.focusNextItem(1); }, enter: function(e) { var menu = this.menu, focused = menu.focusedItem; if (menu.activeItem) { menu.onClick(e); } else if (focused && focused.isFormField) { return true; } }, escape: function(e) { Ext.menu.Manager.hideAll(); }, focusNextItem: function(step) { var menu = this.menu, items = menu.items, focusedItem = menu.focusedItem, startIdx = focusedItem ? items.indexOf(focusedItem) : -1, idx = startIdx + step, len = items.length, count = 0, item; while (count < len && idx !== startIdx) { if (idx < 0) { idx = len - 1; } else if (idx >= len) { idx = 0; } item = items.getAt(idx); if (menu.canActivateItem(item)) { menu.setActiveItem(item); break; } idx += step; ++count; } }, isWhitelisted: function(item) { return Ext.FocusManager.isWhitelisted(item); }, left: function(e) { var menu = this.menu, fi = menu.focusedItem; if (fi && this.isWhitelisted(fi)) { return true; } menu.hide(); if (menu.parentMenu) { menu.parentMenu.focus(); } }, right: function(e) { var menu = this.menu, fi = menu.focusedItem, ai = menu.activeItem, am; if (fi && this.isWhitelisted(fi)) { return true; } if (ai) { am = menu.activeItem.menu; if (am) { ai.expandMenu(0); am.setActiveItem(am.child(':focusable')); } } }, tab: function(e) { var me = this; if (e.shiftKey) { me.up(e); } else { me.down(e); } }, up: function(e) { var me = this, fi = me.menu.focusedItem; if (fi && e.getKey() == Ext.EventObject.UP && me.isWhitelisted(fi)) { return true; } me.focusNextItem(-1); } }); Ext.define('Ext.menu.Separator', { extend: Ext.menu.Item , alias: 'widget.menuseparator', canActivate: false, focusable: false, hideOnClick: false, plain: true, separatorCls: Ext.baseCSSPrefix + 'menu-item-separator', text: ' ', ariaRole: 'separator', beforeRender: function(ct, pos) { var me = this; me.callParent(); me.addCls(me.separatorCls); } }); Ext.define('Ext.menu.Menu', { extend: Ext.panel.Panel , alias: 'widget.menu', enableKeyNav: true, allowOtherMenus: false, ariaRole: 'menu', floating: true, constrain: true, hidden: true, hideMode: 'visibility', ignoreParentClicks: false, isMenu: true, showSeparator : true, minWidth: undefined, defaultMinWidth: 120, initComponent: function() { var me = this, prefix = Ext.baseCSSPrefix, cls = [prefix + 'menu'], bodyCls = me.bodyCls ? [me.bodyCls] : [], isFloating = me.floating !== false; me.addEvents( 'click', 'mouseenter', 'mouseleave', 'mouseover' ); Ext.menu.Manager.register(me); if (me.plain) { cls.push(prefix + 'menu-plain'); } me.cls = cls.join(' '); bodyCls.push(prefix + 'menu-body', Ext.dom.Element.unselectableCls); me.bodyCls = bodyCls.join(' '); if (!me.layout) { me.layout = { type: 'vbox', align: 'stretchmax', overflowHandler: 'Scroller' }; } if (isFloating) { if (me.minWidth === undefined) { me.minWidth = me.defaultMinWidth; } } else { me.hidden = !!me.initialConfig.hidden; me.constrain = false; } me.callParent(arguments); }, registerWithOwnerCt: function() { if (this.floating) { this.ownerCt = null; Ext.WindowManager.register(this); } }, initHierarchyEvents: Ext.emptyFn, isVisible: function() { return this.callParent(); }, getHierarchyState: function() { var result = this.callParent(); result.hidden = this.hidden; return result; }, beforeRender: function() { this.callParent(arguments); if (!this.getSizeModel().width.shrinkWrap) { this.layout.align = 'stretch'; } }, onBoxReady: function() { var me = this; me.callParent(arguments); if (me.showSeparator) { me.iconSepEl = me.layout.getElementTarget().insertFirst({ role: 'presentation', cls: Ext.baseCSSPrefix + 'menu-icon-separator', html: ' ' }); } me.mon(me.el, { click: me.onClick, mouseover: me.onMouseOver, scope: me }); me.mouseMonitor = me.el.monitorMouseLeave(100, me.onMouseLeave, me); if (me.enableKeyNav) { me.keyNav = new Ext.menu.KeyNav({ target: me, keyMap: me.getKeyMap() }); } }, getRefOwner: function() { return this.parentMenu || this.ownerButton || this.callParent(arguments); }, canActivateItem: function(item) { return item && !item.isDisabled() && item.isVisible() && (item.canActivate || !item.isMenuItem); }, deactivateActiveItem: function(andBlurFocusedItem) { var me = this, activeItem = me.activeItem, focusedItem = me.focusedItem; if (activeItem) { activeItem.deactivate(); if (!activeItem.activated) { delete me.activeItem; } } if (focusedItem && andBlurFocusedItem) { focusedItem.blur(); delete me.focusedItem; } }, getFocusEl: function() { return this.focusedItem || this.el; }, hide: function() { this.deactivateActiveItem(true); this.callParent(arguments); }, getItemFromEvent: function(e) { var me = this, renderTarget = me.layout.getRenderTarget().dom, toEl = e.getTarget(); while (toEl.parentNode !== renderTarget) { toEl = toEl.parentNode; if (!toEl) { return; } } return Ext.getCmp(toEl.id); }, lookupComponent: function(cmp) { var me = this; if (typeof cmp == 'string') { cmp = me.lookupItemFromString(cmp); } else if (Ext.isObject(cmp)) { cmp = me.lookupItemFromObject(cmp); } cmp.minWidth = cmp.minWidth || me.minWidth; return cmp; }, lookupItemFromObject: function(cmp) { var me = this, prefix = Ext.baseCSSPrefix, cls; if (!cmp.isComponent) { if (!cmp.xtype) { cmp = Ext.create('Ext.menu.' + (Ext.isBoolean(cmp.checked) ? 'Check': '') + 'Item', cmp); } else { cmp = Ext.ComponentManager.create(cmp, cmp.xtype); } } if (cmp.isMenuItem) { cmp.parentMenu = me; } if (!cmp.isMenuItem && !cmp.dock) { cls = [prefix + 'menu-item-cmp']; if (!me.plain && (cmp.indent !== false || cmp.iconCls === 'no-icon')) { cls.push(prefix + 'menu-item-indent'); } if (cmp.rendered) { cmp.el.addCls(cls); } else { cmp.cls = (cmp.cls || '') + ' ' + cls.join(' '); } } return cmp; }, lookupItemFromString: function(cmp) { return (cmp == 'separator' || cmp == '-') ? new Ext.menu.Separator() : new Ext.menu.Item({ canActivate: false, hideOnClick: false, plain: true, text: cmp }); }, onClick: function(e) { var me = this, item; if (me.disabled) { e.stopEvent(); return; } item = (e.type === 'click') ? me.getItemFromEvent(e) : me.activeItem; if (item && item.isMenuItem) { if (!item.menu || !me.ignoreParentClicks) { item.onClick(e); } else { e.stopEvent(); } } if (!item || item.disabled) { item = undefined; } me.fireEvent('click', me, item, e); }, onDestroy: function() { var me = this; Ext.menu.Manager.unregister(me); me.parentMenu = me.ownerButton = null; if (me.rendered) { me.el.un(me.mouseMonitor); Ext.destroy(me.keyNav); me.keyNav = null; } me.callParent(arguments); }, onMouseLeave: function(e) { var me = this; me.deactivateActiveItem(); if (me.disabled) { return; } me.fireEvent('mouseleave', me, e); }, onMouseOver: function(e) { var me = this, fromEl = e.getRelatedTarget(), mouseEnter = !me.el.contains(fromEl), item = me.getItemFromEvent(e), parentMenu = me.parentMenu, parentItem = me.parentItem; if (mouseEnter && parentMenu) { parentMenu.setActiveItem(parentItem); parentItem.cancelDeferHide(); parentMenu.mouseMonitor.mouseenter(); } if (me.disabled) { return; } if (item && !item.activated) { me.setActiveItem(item); if (item.activated && item.expandMenu) { item.expandMenu(); } } if (mouseEnter) { me.fireEvent('mouseenter', me, e); } me.fireEvent('mouseover', me, item, e); }, setActiveItem: function(item) { var me = this; if (item && (item != me.activeItem)) { me.deactivateActiveItem(); if (me.canActivateItem(item)) { if (item.activate) { item.activate(true); if (item.activated) { me.activeItem = item; me.focusedItem = item; } } else { item.focus(); me.focusedItem = item; } } } }, showBy: function(cmp, pos, off) { var me = this; me.callParent(arguments); if (!me.hidden) { me.setVerticalPosition(); } return me; }, beforeShow: function() { var me = this, viewHeight; if (me.floating) { me.savedMaxHeight = me.maxHeight; viewHeight = me.container.getViewSize().height; me.maxHeight = Math.min(me.maxHeight || viewHeight, viewHeight); } me.callParent(arguments); }, afterShow: function() { var me = this; me.callParent(arguments); if (me.floating) { me.maxHeight = me.savedMaxHeight; } }, setVerticalPosition: function() { var me = this, max, y = me.getY(), returnY = y, height = me.getHeight(), viewportHeight = Ext.Element.getViewportHeight().height, parentEl = me.el.parent(), viewHeight = parentEl.getViewSize().height, normalY = y - parentEl.getScroll().top; parentEl = null; if (me.floating) { max = me.maxHeight ? me.maxHeight : viewHeight - normalY; if (height > viewHeight) { returnY = y - normalY; } else if (max < height) { returnY = y - (height - max); } else if((y + height) > viewportHeight){ returnY = viewportHeight - height; } } me.setY(returnY); } }); Ext.define('Ext.menu.ColorPicker', { extend: Ext.menu.Menu , alias: 'widget.colormenu', hideOnClick : true, pickerId : null, initComponent : function(){ var me = this, cfg = Ext.apply({}, me.initialConfig); delete cfg.listeners; Ext.apply(me, { plain: true, showSeparator: false, bodyPadding: 0, items: Ext.applyIf({ cls: Ext.baseCSSPrefix + 'menu-color-item', margin: 0, id: me.pickerId, xtype: 'colorpicker' }, cfg) }); me.callParent(arguments); me.picker = me.down('colorpicker'); me.relayEvents(me.picker, ['select']); if (me.hideOnClick) { me.on('select', me.hidePickerOnSelect, me); } }, hidePickerOnSelect: function() { Ext.menu.Manager.hideAll(); } }); Ext.define('Ext.menu.DatePicker', { extend: Ext.menu.Menu , alias: 'widget.datemenu', hideOnClick : true, pickerId : null, initComponent : function(){ var me = this, cfg = Ext.apply({}, me.initialConfig); delete cfg.listeners; Ext.apply(me, { showSeparator: false, plain: true, bodyPadding: 0, items: Ext.applyIf({ cls: Ext.baseCSSPrefix + 'menu-date-item', margin: 0, border: false, id: me.pickerId, xtype: 'datepicker' }, cfg) }); me.callParent(arguments); me.picker = me.down('datepicker'); me.relayEvents(me.picker, ['select']); if (me.hideOnClick) { me.on('select', me.hidePickerOnSelect, me); } }, hidePickerOnSelect: function() { Ext.menu.Manager.hideAll(); } }); Ext.define('Ext.panel.Tool', { extend: Ext.Component , alias: 'widget.tool', isTool: true, baseCls: Ext.baseCSSPrefix + 'tool', disabledCls: Ext.baseCSSPrefix + 'tool-disabled', toolPressedCls: Ext.baseCSSPrefix + 'tool-pressed', toolOverCls: Ext.baseCSSPrefix + 'tool-over', ariaRole: 'button', childEls: [ 'toolEl' ], renderTpl: [ '' ], toolOwner: null, tooltipType: 'qtip', stopEvent: true, height: 15, width: 15, initComponent: function() { var me = this; me.addEvents( 'click' ); me.type = me.type || me.id; Ext.applyIf(me.renderData, { baseCls: me.baseCls, blank: Ext.BLANK_IMAGE_URL, type: me.type }); me.tooltip = me.tooltip || me.qtip; me.callParent(); }, afterRender: function() { var me = this, attr; me.callParent(arguments); me.el.on({ click: me.onClick, mousedown: me.onMouseDown, mouseover: me.onMouseOver, mouseout: me.onMouseOut, scope: me }); if (me.tooltip) { if (Ext.quickTipsActive && Ext.isObject(me.tooltip)) { Ext.tip.QuickTipManager.register(Ext.apply({ target: me.id }, me.tooltip)); } else { attr = me.tooltipType == 'qtip' ? 'data-qtip' : 'title'; me.el.dom.setAttribute(attr, me.tooltip); } } }, getFocusEl: function() { return this.el; }, setType: function(type) { var me = this, oldType = me.type; me.type = type; if (me.rendered) { if (oldType) { me.toolEl.removeCls(me.baseCls + '-' + oldType); } me.toolEl.addCls(me.baseCls + '-' + type); } else { me.renderData.type = type; } return me; }, onClick: function(e, target) { var me = this; if (me.disabled) { return false; } me.el.removeCls(me.toolPressedCls); me.el.removeCls(me.toolOverCls); if (me.stopEvent !== false) { e.stopEvent(); } if (me.handler) { Ext.callback(me.handler, me.scope || me, [e, target, me.ownerCt, me]); } else if (me.callback) { Ext.callback(me.callback, me.scope || me, [me.toolOwner || me.ownerCt, me, e]); } me.fireEvent('click', me, e); return true; }, onDestroy: function(){ var me = this; if (Ext.quickTipsActive && Ext.isObject(me.tooltip)) { Ext.tip.QuickTipManager.unregister(me.id); } if (me.keyMap) { me.keyMap.destroy(); } me.callParent(); }, onMouseDown: function() { if (this.disabled) { return false; } this.el.addCls(this.toolPressedCls); }, onMouseOver: function() { if (this.disabled) { return false; } this.el.addCls(this.toolOverCls); }, onMouseOut: function() { this.el.removeCls(this.toolOverCls); } }); Ext.define('Ext.resizer.SplitterTracker', { extend: Ext.dd.DragTracker , enabled: true, overlayCls: Ext.baseCSSPrefix + 'resizable-overlay', createDragOverlay: function () { var overlay; overlay = this.overlay = Ext.getBody().createChild({ role: 'presentation', cls: this.overlayCls, html: ' ' }); overlay.unselectable(); overlay.setSize(Ext.Element.getViewWidth(true), Ext.Element.getViewHeight(true)); overlay.show(); }, getPrevCmp: function() { var splitter = this.getSplitter(); return splitter.previousSibling(':not([hidden])'); }, getNextCmp: function() { var splitter = this.getSplitter(); return splitter.nextSibling(':not([hidden])'); }, onBeforeStart: function(e) { var me = this, prevCmp = me.getPrevCmp(), nextCmp = me.getNextCmp(), collapseEl = me.getSplitter().collapseEl, target = e.getTarget(), box; if (!prevCmp || !nextCmp) { return false; } if (collapseEl && target === me.getSplitter().collapseEl.dom) { return false; } if (nextCmp.collapsed || prevCmp.collapsed) { return false; } me.prevBox = prevCmp.getEl().getBox(); me.nextBox = nextCmp.getEl().getBox(); me.constrainTo = box = me.calculateConstrainRegion(); if (!box) { return false; } return box; }, onStart: function(e) { var splitter = this.getSplitter(); this.createDragOverlay(); splitter.addCls(splitter.baseCls + '-active'); }, calculateConstrainRegion: function() { var me = this, splitter = me.getSplitter(), splitWidth = splitter.getWidth(), defaultMin = splitter.defaultSplitMin, orient = splitter.orientation, prevBox = me.prevBox, prevCmp = me.getPrevCmp(), nextBox = me.nextBox, nextCmp = me.getNextCmp(), prevConstrainRegion, nextConstrainRegion, constrainOptions; if (orient === 'vertical') { constrainOptions = { prevCmp: prevCmp, nextCmp: nextCmp, prevBox: prevBox, nextBox: nextBox, defaultMin: defaultMin, splitWidth: splitWidth }; prevConstrainRegion = new Ext.util.Region( prevBox.y, me.getVertPrevConstrainRight(constrainOptions), prevBox.bottom, me.getVertPrevConstrainLeft(constrainOptions) ); nextConstrainRegion = new Ext.util.Region( nextBox.y, me.getVertNextConstrainRight(constrainOptions), nextBox.bottom, me.getVertNextConstrainLeft(constrainOptions) ); } else { prevConstrainRegion = new Ext.util.Region( prevBox.y + (prevCmp.minHeight || defaultMin), prevBox.right, (prevCmp.maxHeight ? prevBox.y + prevCmp.maxHeight : nextBox.bottom - (nextCmp.minHeight || defaultMin)) + splitWidth, prevBox.x ); nextConstrainRegion = new Ext.util.Region( (nextCmp.maxHeight ? nextBox.bottom - nextCmp.maxHeight : prevBox.y + (prevCmp.minHeight || defaultMin)) - splitWidth, nextBox.right, nextBox.bottom - (nextCmp.minHeight || defaultMin), nextBox.x ); } return prevConstrainRegion.intersect(nextConstrainRegion); }, performResize: function(e, offset) { var me = this, splitter = me.getSplitter(), orient = splitter.orientation, prevCmp = me.getPrevCmp(), nextCmp = me.getNextCmp(), owner = splitter.ownerCt, flexedSiblings = owner.query('>[flex]'), len = flexedSiblings.length, vertical = orient === 'vertical', i = 0, dimension = vertical ? 'width' : 'height', totalFlex = 0, item, size; for (; i < len; i++) { item = flexedSiblings[i]; size = vertical ? item.getWidth() : item.getHeight(); totalFlex += size; item.flex = size; } offset = vertical ? offset[0] : offset[1]; if (prevCmp) { size = me.prevBox[dimension] + offset; if (prevCmp.flex) { prevCmp.flex = size; } else { prevCmp[dimension] = size; } } if (nextCmp) { size = me.nextBox[dimension] - offset; if (nextCmp.flex) { nextCmp.flex = size; } else { nextCmp[dimension] = size; } } owner.updateLayout(); }, endDrag: function () { var me = this; if (me.overlay) { me.overlay.remove(); delete me.overlay; } me.callParent(arguments); }, onEnd: function(e) { var me = this, splitter = me.getSplitter(); splitter.removeCls(splitter.baseCls + '-active'); me.performResize(e, me.getResizeOffset()); }, onDrag: function(e) { var me = this, offset = me.getOffset('dragTarget'), splitter = me.getSplitter(), splitEl = splitter.getEl(), orient = splitter.orientation; if (orient === "vertical") { splitEl.setX(me.startRegion.left + offset[0]); } else { splitEl.setY(me.startRegion.top + offset[1]); } }, getSplitter: function() { return this.splitter; }, getVertPrevConstrainRight: function(o) { return (o.prevCmp.maxWidth ? o.prevBox.x + o.prevCmp.maxWidth : o.nextBox.right - (o.nextCmp.minWidth || o.defaultMin)) + o.splitWidth; }, getVertPrevConstrainLeft: function(o) { return o.prevBox.x + (o.prevCmp.minWidth || o.defaultMin); }, getVertNextConstrainRight: function(o) { return o.nextBox.right - (o.nextCmp.minWidth || o.defaultMin); }, getVertNextConstrainLeft: function(o) { return (o.nextCmp.maxWidth ? o.nextBox.right - o.nextCmp.maxWidth : o.prevBox.x + (o.prevBox.minWidth || o.defaultMin)) - o.splitWidth; }, getResizeOffset: function() { return this.getOffset('dragTarget'); } }); Ext.define('Ext.resizer.BorderSplitterTracker', { extend: Ext.resizer.SplitterTracker , getPrevCmp: null, getNextCmp: null, calculateConstrainRegion: function() { var me = this, splitter = me.splitter, collapseTarget = splitter.collapseTarget, defaultSplitMin = splitter.defaultSplitMin, sizePropCap = splitter.vertical ? 'Width' : 'Height', minSizeProp = 'min' + sizePropCap, maxSizeProp = 'max' + sizePropCap, getSizeMethod = 'get' + sizePropCap, neighbors = splitter.neighbors, length = neighbors.length, box = collapseTarget.el.getBox(), left = box.x, top = box.y, right = box.right, bottom = box.bottom, size = splitter.vertical ? (right - left) : (bottom - top), i, neighbor, minRange, maxRange, maxGrowth, maxShrink, targetSize; minRange = (collapseTarget[minSizeProp] || Math.min(size,defaultSplitMin)) - size; maxRange = collapseTarget[maxSizeProp]; if (!maxRange) { maxRange = 1e9; } else { maxRange -= size; } targetSize = size; for (i = 0; i < length; ++i) { neighbor = neighbors[i]; size = neighbor[getSizeMethod](); maxGrowth = size - neighbor[maxSizeProp]; maxShrink = size - (neighbor[minSizeProp] || Math.min(size,defaultSplitMin)); if (!isNaN(maxGrowth)) { if (minRange < maxGrowth) { minRange = maxGrowth; } } if (maxRange > maxShrink) { maxRange = maxShrink; } } if (maxRange - minRange < 2) { return null; } box = new Ext.util.Region(top, right, bottom, left); me.constraintAdjusters[me.getCollapseDirection()](box, minRange, maxRange, splitter); me.dragInfo = { minRange: minRange, maxRange: maxRange, targetSize: targetSize }; return box; }, constraintAdjusters: { left: function (box, minRange, maxRange, splitter) { box[0] = box.x = box.left = box.right + minRange; box.right += maxRange + splitter.getWidth(); }, top: function (box, minRange, maxRange, splitter) { box[1] = box.y = box.top = box.bottom + minRange; box.bottom += maxRange + splitter.getHeight(); }, bottom: function (box, minRange, maxRange, splitter) { box.bottom = box.top - minRange; box.top -= maxRange + splitter.getHeight(); }, right: function (box, minRange, maxRange, splitter) { box.right = box.left - minRange; box[0] = box.x = box.left = box.x - maxRange + splitter.getWidth(); } }, onBeforeStart: function(e) { var me = this, splitter = me.splitter, collapseTarget = splitter.collapseTarget, neighbors = splitter.neighbors, collapseEl = me.getSplitter().collapseEl, target = e.getTarget(), length = neighbors.length, i, neighbor; if (collapseEl && target === splitter.collapseEl.dom) { return false; } if (collapseTarget.collapsed) { return false; } for (i = 0; i < length; ++i) { neighbor = neighbors[i]; if (neighbor.collapsed && neighbor.isHorz === collapseTarget.isHorz) { return false; } } if (!(me.constrainTo = me.calculateConstrainRegion())) { return false; } return true; }, performResize: function(e, offset) { var me = this, splitter = me.splitter, collapseDirection = splitter.getCollapseDirection(), collapseTarget = splitter.collapseTarget, adjusters = me.splitAdjusters[splitter.vertical ? 'horz' : 'vert'], delta = offset[adjusters.index], dragInfo = me.dragInfo, owner; if (collapseDirection == 'right' || collapseDirection == 'bottom') { delta = -delta; } delta = Math.min(Math.max(dragInfo.minRange, delta), dragInfo.maxRange); if (delta) { (owner = splitter.ownerCt).suspendLayouts(); adjusters.adjustTarget(collapseTarget, dragInfo.targetSize, delta); owner.resumeLayouts(true); } }, splitAdjusters: { horz: { index: 0, adjustTarget: function (target, size, delta) { target.flex = null; target.setSize(size + delta); } }, vert: { index: 1, adjustTarget: function (target, targetSize, delta) { target.flex = null; target.setSize(undefined, targetSize + delta); } } }, getCollapseDirection: function() { return this.splitter.getCollapseDirection(); } }); Ext.define('Ext.resizer.Handle', { extend: Ext.Component , handleCls: '', baseHandleCls: Ext.baseCSSPrefix + 'resizable-handle', region: '', ariaRole: 'presentation', beforeRender: function() { var me = this; me.callParent(); me.protoEl.unselectable(); me.addCls( me.baseHandleCls, me.baseHandleCls + '-' + me.region, me.handleCls ); } }); Ext.define('Ext.resizer.ResizeTracker', { extend: Ext.dd.DragTracker , dynamic: true, preserveRatio: false, constrainTo: null, proxyCls: Ext.baseCSSPrefix + 'resizable-proxy', constructor: function(config) { var me = this, widthRatio, heightRatio, throttledResizeFn; if (!config.el) { if (config.target.isComponent) { me.el = config.target.getEl(); } else { me.el = config.target; } } this.callParent(arguments); if (me.preserveRatio && me.minWidth && me.minHeight) { widthRatio = me.minWidth / me.el.getWidth(); heightRatio = me.minHeight / me.el.getHeight(); if (heightRatio > widthRatio) { me.minWidth = me.el.getWidth() * heightRatio; } else { me.minHeight = me.el.getHeight() * widthRatio; } } if (me.throttle) { throttledResizeFn = Ext.Function.createThrottled(function() { Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments); }, me.throttle); me.resize = function(box, direction, atEnd) { if (atEnd) { Ext.resizer.ResizeTracker.prototype.resize.apply(me, arguments); } else { throttledResizeFn.apply(null, arguments); } }; } }, onBeforeStart: function(e) { this.startBox = this.target.getBox(); }, getDynamicTarget: function() { var me = this, target = me.target; if (me.dynamic) { return target; } else if (!me.proxy) { me.proxy = me.createProxy(target); } me.proxy.show(); return me.proxy; }, createProxy: function(target){ var proxy, cls = this.proxyCls; if (target.isComponent) { proxy = target.getProxy().addCls(cls); } else { proxy = target.createProxy({ tag: 'div', role: 'presentation', cls: cls, id: target.id + '-rzproxy' }, Ext.getBody()); } proxy.removeCls(Ext.baseCSSPrefix + 'proxy-el'); return proxy; }, onStart: function(e) { this.activeResizeHandle = Ext.get(this.getDragTarget().id); if (!this.dynamic) { this.resize(this.startBox, { horizontal: 'none', vertical: 'none' }); } }, onDrag: function(e) { if (this.dynamic || this.proxy) { this.updateDimensions(e); } }, updateDimensions: function(e, atEnd) { var me = this, region = me.activeResizeHandle.region, offset = me.getOffset(me.constrainTo ? 'dragTarget' : null), box = me.startBox, ratio, widthAdjust = 0, heightAdjust = 0, snappedWidth, snappedHeight, adjustX = 0, adjustY = 0, dragRatio, horizDir = offset[0] < 0 ? 'right' : 'left', vertDir = offset[1] < 0 ? 'down' : 'up', oppositeCorner, axis, newBox, newHeight, newWidth; region = me.convertRegionName(region); switch (region) { case 'south': heightAdjust = offset[1]; axis = 2; break; case 'north': heightAdjust = -offset[1]; adjustY = -heightAdjust; axis = 2; break; case 'east': widthAdjust = offset[0]; axis = 1; break; case 'west': widthAdjust = -offset[0]; adjustX = -widthAdjust; axis = 1; break; case 'northeast': heightAdjust = -offset[1]; adjustY = -heightAdjust; widthAdjust = offset[0]; oppositeCorner = [box.x, box.y + box.height]; axis = 3; break; case 'southeast': heightAdjust = offset[1]; widthAdjust = offset[0]; oppositeCorner = [box.x, box.y]; axis = 3; break; case 'southwest': widthAdjust = -offset[0]; adjustX = -widthAdjust; heightAdjust = offset[1]; oppositeCorner = [box.x + box.width, box.y]; axis = 3; break; case 'northwest': heightAdjust = -offset[1]; adjustY = -heightAdjust; widthAdjust = -offset[0]; adjustX = -widthAdjust; oppositeCorner = [box.x + box.width, box.y + box.height]; axis = 3; break; } newBox = { width: box.width + widthAdjust, height: box.height + heightAdjust, x: box.x + adjustX, y: box.y + adjustY }; snappedWidth = Ext.Number.snap(newBox.width, me.widthIncrement); snappedHeight = Ext.Number.snap(newBox.height, me.heightIncrement); if (snappedWidth != newBox.width || snappedHeight != newBox.height){ switch (region) { case 'northeast': newBox.y -= snappedHeight - newBox.height; break; case 'north': newBox.y -= snappedHeight - newBox.height; break; case 'southwest': newBox.x -= snappedWidth - newBox.width; break; case 'west': newBox.x -= snappedWidth - newBox.width; break; case 'northwest': newBox.x -= snappedWidth - newBox.width; newBox.y -= snappedHeight - newBox.height; } newBox.width = snappedWidth; newBox.height = snappedHeight; } if (newBox.width < me.minWidth || newBox.width > me.maxWidth) { newBox.width = Ext.Number.constrain(newBox.width, me.minWidth, me.maxWidth); if (adjustX) { newBox.x = box.x + (box.width - newBox.width); } } else { me.lastX = newBox.x; } if (newBox.height < me.minHeight || newBox.height > me.maxHeight) { newBox.height = Ext.Number.constrain(newBox.height, me.minHeight, me.maxHeight); if (adjustY) { newBox.y = box.y + (box.height - newBox.height); } } else { me.lastY = newBox.y; } if (me.preserveRatio || e.shiftKey) { ratio = me.startBox.width / me.startBox.height; newHeight = Math.min(Math.max(me.minHeight, newBox.width / ratio), me.maxHeight); newWidth = Math.min(Math.max(me.minWidth, newBox.height * ratio), me.maxWidth); if (axis == 1) { newBox.height = newHeight; } else if (axis == 2) { newBox.width = newWidth; } else { dragRatio = Math.abs(oppositeCorner[0] - this.lastXY[0]) / Math.abs(oppositeCorner[1] - this.lastXY[1]); if (dragRatio > ratio) { newBox.height = newHeight; } else { newBox.width = newWidth; } if (region == 'northeast') { newBox.y = box.y - (newBox.height - box.height); } else if (region == 'northwest') { newBox.y = box.y - (newBox.height - box.height); newBox.x = box.x - (newBox.width - box.width); } else if (region == 'southwest') { newBox.x = box.x - (newBox.width - box.width); } } } if (heightAdjust === 0) { vertDir = 'none'; } if (widthAdjust === 0) { horizDir = 'none'; } me.resize(newBox, { horizontal: horizDir, vertical: vertDir }, atEnd); }, getResizeTarget: function(atEnd) { return atEnd ? this.target : this.getDynamicTarget(); }, resize: function(box, direction, atEnd) { var me = this, target = me.getResizeTarget(atEnd); target.setBox(box); if (me.originalTarget && (me.dynamic || atEnd)) { me.originalTarget.setBox(box); } }, onEnd: function(e) { this.updateDimensions(e, true); if (this.proxy) { this.proxy.hide(); } }, convertRegionName: function(name) { return name; } }); Ext.define('Ext.resizer.Resizer', { mixins: { observable: Ext.util.Observable }, alternateClassName: 'Ext.Resizable', handleCls: Ext.baseCSSPrefix + 'resizable-handle', pinnedCls: Ext.baseCSSPrefix + 'resizable-pinned', overCls: Ext.baseCSSPrefix + 'resizable-over', wrapCls: Ext.baseCSSPrefix + 'resizable-wrap', delimiterRe: /(?:\s*[,;]\s*)|\s+/, dynamic: true, handles: 's e se', height : null, width : null, heightIncrement : 0, widthIncrement : 0, minHeight : 20, minWidth : 20, maxHeight : 10000, maxWidth : 10000, pinned: false, preserveRatio: false, transparent: false, possiblePositions: { n: 'north', s: 'south', e: 'east', w: 'west', se: 'southeast', sw: 'southwest', nw: 'northwest', ne: 'northeast' }, ariaRole: 'presentation', constructor: function(config) { var me = this, target, targetEl, tag, handles = me.handles, handleCls, possibles, len, i = 0, pos, handleEls = [], eastWestStyle, style, box, targetBaseCls, unselectableCls = Ext.dom.Element.unselectableCls; me.addEvents( 'beforeresize', 'resizedrag', 'resize' ); if (Ext.isString(config) || Ext.isElement(config) || config.dom) { target = config; config = arguments[1] || {}; config.target = target; } me.mixins.observable.constructor.call(me, config); target = me.target; if (target) { if (target.isComponent) { target.addClsWithUI('resizable'); me.el = target.getEl(); if (target.minWidth) { me.minWidth = target.minWidth; } if (target.minHeight) { me.minHeight = target.minHeight; } if (target.maxWidth) { me.maxWidth = target.maxWidth; } if (target.maxHeight) { me.maxHeight = target.maxHeight; } if (target.floating) { if (!me.hasOwnProperty('handles')) { me.handles = 'n ne e se s sw w nw'; } } } else { me.el = me.target = Ext.get(target); } } else { me.target = me.el = Ext.get(me.el); } tag = me.el.dom.tagName.toUpperCase(); if (tag == 'TEXTAREA' || tag == 'IMG' || tag == 'TABLE') { me.originalTarget = me.target; targetEl = me.el; box = targetEl.getBox(); me.target = me.el = me.el.wrap({ role: 'presentation', cls: me.wrapCls, id: me.el.id + '-rzwrap', style: targetEl.getStyles('margin-top', 'margin-bottom') }); me.el.setPositioning(targetEl.getPositioning()); targetEl.clearPositioning(); me.el.setBox(box); targetEl.setStyle('position', 'absolute'); } me.el.position(); if (me.pinned) { me.el.addCls(me.pinnedCls); } me.resizeTracker = new Ext.resizer.ResizeTracker({ disabled: me.disabled, target: me.target, constrainTo: me.constrainTo, overCls: me.overCls, throttle: me.throttle, originalTarget: me.originalTarget, delegate: '.' + me.handleCls, dynamic: me.dynamic, preserveRatio: me.preserveRatio, heightIncrement: me.heightIncrement, widthIncrement: me.widthIncrement, minHeight: me.minHeight, maxHeight: me.maxHeight, minWidth: me.minWidth, maxWidth: me.maxWidth }); me.resizeTracker.on({ mousedown: me.onBeforeResize, drag: me.onResize, dragend: me.onResizeEnd, scope: me }); if (me.handles == 'all') { me.handles = 'n s e w ne nw se sw'; } handles = me.handles = me.handles.split(me.delimiterRe); possibles = me.possiblePositions; len = handles.length; handleCls = me.handleCls + ' ' + me.handleCls + '-{0}'; if (me.target.isComponent) { targetBaseCls = me.target.baseCls handleCls += ' ' + targetBaseCls + '-handle ' + targetBaseCls + '-handle-{0}'; if (Ext.supports.CSS3BorderRadius) { handleCls += ' ' + targetBaseCls + '-handle-{0}-br'; } } eastWestStyle = Ext.isIE6 ? ' style="height:' + me.el.getHeight() + 'px"' : ''; for (; i < len; i++){ if (handles[i] && possibles[handles[i]]) { pos = possibles[handles[i]]; if (pos === 'east' || pos === 'west') { style = eastWestStyle; } else { style = ''; } handleEls.push( '' ); } } Ext.DomHelper.append(me.el, handleEls.join('')); for (i = 0; i < len; i++){ if (handles[i] && possibles[handles[i]]) { pos = possibles[handles[i]]; me[pos] = me.el.getById(me.el.id + '-' + pos + '-handle'); me[pos].region = pos; if (me.transparent) { me[pos].setOpacity(0); } } } if (Ext.isNumber(me.width)) { me.width = Ext.Number.constrain(me.width, me.minWidth, me.maxWidth); } if (Ext.isNumber(me.height)) { me.height = Ext.Number.constrain(me.height, me.minHeight, me.maxHeight); } if (me.width !== null || me.height !== null) { if (me.originalTarget) { me.originalTarget.setWidth(me.width); me.originalTarget.setHeight(me.height); } me.resizeTo(me.width, me.height); } me.forceHandlesHeight(); }, disable: function() { this.resizeTracker.disable(); }, enable: function() { this.resizeTracker.enable(); }, onBeforeResize: function(tracker, e) { var box = this.el.getBox(); return this.fireEvent('beforeresize', this, box.width, box.height, e); }, onResize: function(tracker, e) { var me = this, box = me.el.getBox(); me.forceHandlesHeight(); return me.fireEvent('resizedrag', me, box.width, box.height, e); }, onResizeEnd: function(tracker, e) { var me = this, box = me.el.getBox(); me.forceHandlesHeight(); return me.fireEvent('resize', me, box.width, box.height, e); }, resizeTo : function(width, height) { var me = this; me.target.setSize(width, height); me.fireEvent('resize', me, width, height, null); }, getEl : function() { return this.el; }, getTarget: function() { return this.target; }, destroy: function() { var me = this, i, handles = me.handles, len = handles.length, positions = me.possiblePositions, handle; me.resizeTracker.destroy(); for (i = 0; i < len; i++) { if (handle = me[positions[handles[i]]]) { handle.remove(); } } }, forceHandlesHeight : function() { var me = this, handle; if (Ext.isIE6) { handle = me.east; if (handle) { handle.setHeight(me.el.getHeight()); } handle = me.west; if (handle) { handle.setHeight(me.el.getHeight()); } me.el.repaint(); } } }); Ext.define('Ext.selection.CellModel', { extend: Ext.selection.Model , alias: 'selection.cellmodel', isCellModel: true, enableKeyNav: true, preventWrap: false, noSelection: { row: -1, column: -1 }, constructor: function() { this.addEvents( 'deselect', 'select' ); this.callParent(arguments); }, bindComponent: function(view) { var me = this, grid = view.ownerCt; me.primaryView = view; me.views = me.views || []; me.views.push(view); me.bindStore(view.getStore(), true); view.on({ cellclick: me.onCellClick, refresh: me.onViewRefresh, scope: me }); if (grid.optimizedColumnMove !== false) { grid.on('columnmove', me.onColumnMove, me); } if (me.enableKeyNav) { me.initKeyNav(view); } }, initKeyNav: function(view) { var me = this; if (!view.rendered) { view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true}); return; } view.el.set({ tabIndex: -1 }); me.keyNav = new Ext.util.KeyNav({ target: view.el, ignoreInputFields: true, up: me.onKeyUp, down: me.onKeyDown, right: me.onKeyRight, left: me.onKeyLeft, tab: me.onKeyTab, scope: me }); }, getHeaderCt: function() { var selection = this.getCurrentPosition(), view = selection ? selection.view : this.primaryView; return view.headerCt; }, onKeyUp: function(e) { this.doMove('up', e); }, onKeyDown: function(e) { this.doMove('down', e); }, onKeyLeft: function(e) { this.doMove('left', e); }, onKeyRight: function(e) { this.doMove('right', e); }, doMove: function(direction, e){ this.keyNavigation = true; this.move(direction, e); this.keyNavigation = false; }, select: function(pos, keepExisting, suppressEvent) { var me = this, row, oldPos = me.getCurrentPosition(), store = me.view.store; if (pos || pos === 0) { if (pos.isModel) { row = store.indexOf(pos); if (row !== -1) { pos = { row: row, column: oldPos ? oldPos.column : 0 }; } else { pos = null; } } else if (typeof pos === 'number') { pos = { row: pos, column: 0 } } } if (pos) { me.selectByPosition(pos, suppressEvent); } else { me.deselect(); } }, deselect: function(record, suppressEvent){ this.selectByPosition(null, suppressEvent); }, move: function(dir, e) { var me = this, pos = me.getCurrentPosition(), newPos; if (pos) { newPos = pos.view.walkCells(pos, dir, e, me.preventWrap); if (newPos) { return me.setCurrentPosition(newPos); } } }, getCurrentPosition: function() { return this.selecting ? this.nextSelection : this.selection; }, setCurrentPosition: function(pos, suppressEvent, preventCheck) { var me = this, last = me.selection; me.lastSelection = last; if (pos) { pos = pos.isCellContext ? pos : new Ext.grid.CellContext(me.primaryView).setPosition(pos); } if (!preventCheck && last) { if (pos && (pos.record === last.record && pos.columnHeader === last.columnHeader && pos.view === last.view)) { pos = null; } else { me.onCellDeselect(me.selection, suppressEvent); } } if (pos) { me.nextSelection = pos; me.selecting = true; me.onCellSelect(me.nextSelection, suppressEvent); me.selecting = false; return (me.selection = pos); } }, isCellSelected: function(view, row, column) { var me = this, testPos, pos = me.getCurrentPosition(); if (pos && pos.view === view) { testPos = new Ext.grid.CellContext(view).setPosition({ row: row, column: column }); return (testPos.record === pos.record) && (testPos.columnHeader === pos.columnHeader); } }, onStoreRemove: function(store, records, indexes) { var me = this, pos = me.getCurrentPosition(); me.callParent(arguments); if (pos && store.getCount() && store.indexOf(pos.record) !== -1) { me.setCurrentPosition({ row: pos.record, column: pos.columnHeader }, true, true); } else { me.selection = null; } }, onStoreAdd: function() { var me = this, pos = me.getCurrentPosition(); me.callParent(arguments); if (pos) { me.setCurrentPosition({ row: pos.record, column: pos.columnHeader }, true, true); } else { me.selection = null; } }, onCellClick: function(view, cell, cellIndex, record, row, recordIndex, e) { var newPos; if (recordIndex !== -1) { newPos = new Ext.grid.CellContext(view).setPosition({ view: view, row: row, column: view.ownerCt.getColumnManager().getHeaderAtIndex(cellIndex) }); this.setCurrentPosition(newPos); } }, onCellSelect: function(position, supressEvent) { if (position && position.row !== undefined && position.row > -1) { this.doSelect(position.record, false, supressEvent); } }, onCellDeselect: function(position, supressEvent) { if (position && position.row !== undefined) { this.doDeselect(position.record, supressEvent); } }, onSelectChange: function(record, isSelected, suppressEvent, commitFn) { var me = this, pos, eventName, view; if (isSelected) { pos = me.nextSelection; eventName = 'select'; } else { pos = me.lastSelection || me.noSelection; eventName = 'deselect'; } view = pos.view || me.primaryView; if ((suppressEvent || me.fireEvent('before' + eventName, me, record, pos.row, pos.column)) !== false && commitFn() !== false) { if (isSelected) { if (!me.preventFocus) { view.focusCell(pos, true); } view.onCellSelect(pos); } else { view.onCellDeselect(pos); delete me.selection; } if (!suppressEvent) { me.fireEvent(eventName, me, record, pos.row, pos.column); } } }, onKeyTab: function(e, t) { var me = this, pos = me.getCurrentPosition(), editingPlugin; if (pos) { editingPlugin = pos.view.editingPlugin; if (editingPlugin && me.wasEditing) { me.onEditorTab(editingPlugin, e) } else { me.move(e.shiftKey ? 'left' : 'right', e); } } }, onEditorTab: function(editingPlugin, e) { var me = this, direction = e.shiftKey ? 'left' : 'right', position = me.move(direction, e); if (position) { if (editingPlugin.startEdit(position.record, position.columnHeader)) { me.wasEditing = false; } else { position.view.scrollCellIntoView(position); me.wasEditing = true; } } }, refresh: function() { var pos = this.getCurrentPosition(), selRowIdx; if (pos && (selRowIdx = this.store.indexOf(this.selected.last())) !== -1) { pos.row = selRowIdx; } }, onColumnMove: function(headerCt, header, fromIdx, toIdx) { var grid = headerCt.up('tablepanel'); if (grid) { this.onViewRefresh(grid.view); } }, onUpdate: function(record) { var me = this, pos; if (me.isSelected(record)) { pos = me.selecting ? me.nextSelection : me.selection; me.view.onCellSelect(pos); } }, onViewRefresh: function(view) { var me = this, pos = me.getCurrentPosition(), newPos, headerCt = view.headerCt, record, columnHeader; if (pos && pos.view === view) { record = pos.record; columnHeader = pos.columnHeader; if (!columnHeader.isDescendantOf(headerCt)) { columnHeader = headerCt.queryById(columnHeader.id) || headerCt.down('[text="' + columnHeader.text + '"]') || headerCt.down('[dataIndex="' + columnHeader.dataIndex + '"]'); } if (pos.record) { if (columnHeader && (view.store.indexOfId(record.getId()) !== -1)) { newPos = new Ext.grid.CellContext(view).setPosition({ row: record, column: columnHeader }); me.setCurrentPosition(newPos); } } else { me.selection = null; } } }, selectByPosition: function(position, suppressEvent) { this.setCurrentPosition(position, suppressEvent); } }); Ext.define('Ext.selection.RowModel', { extend: Ext.selection.Model , alias: 'selection.rowmodel', deltaScroll: 5, enableKeyNav: true, ignoreRightMouseSelection: false, isRowModel: true, constructor: function() { this.addEvents( 'beforedeselect', 'beforeselect', 'deselect', 'select' ); this.views = []; this.callParent(arguments); }, bindComponent: function(view) { var me = this; view.on({ itemcontextmenu: me.onRowClick, itemclick: me.onRowClick, scope: me }); if (me.enableKeyNav) { me.initKeyNav(view); } }, initKeyNav: function(view) { var me = this; if (!view.rendered) { view.on('render', Ext.Function.bind(me.initKeyNav, me, [view], 0), me, {single: true}); return; } view.el.set({ tabIndex: -1 }); me.keyNav = new Ext.util.KeyNav({ target: view, ignoreInputFields: true, eventName: 'itemkeydown', processEvent: function(view, record, node, index, event) { event.record = record; event.recordIndex = index; return event; }, up: me.onKeyUp, down: me.onKeyDown, right: me.onKeyRight, left: me.onKeyLeft, pageDown: me.onKeyPageDown, pageUp: me.onKeyPageUp, home: me.onKeyHome, end: me.onKeyEnd, space: me.onKeySpace, enter: me.onKeyEnter, scope: me }); }, onUpdate: function(record) { var me = this, view = me.view, index; if (view && me.isSelected(record)) { index = view.indexOf(record); view.onRowSelect(index); if (record === me.lastFocused) { view.onRowFocus(index, true); } } }, getRowsVisible: function() { var rowsVisible = false, view = this.views[0], firstRow = view.all.first(), rowHeight, gridViewHeight; if (firstRow) { rowHeight = firstRow.getHeight(); gridViewHeight = view.el.getHeight(); rowsVisible = Math.floor(gridViewHeight / rowHeight); } return rowsVisible; }, onKeyEnd: function(e) { var me = this, view = me.views[0]; if (view.bufferedRenderer) { view.bufferedRenderer.scrollTo(me.store.getCount() - 1, false, function(newIdx, newRecord) { me.afterKeyNavigate(e, newRecord) }); } else { me.afterKeyNavigate(e, view.getRecord(view.all.getCount() - 1)) } }, onKeyHome: function(e) { var me = this, view = me.views[0]; if (view.bufferedRenderer) { view.bufferedRenderer.scrollTo(0, false, function(newIdx, newRecord) { me.afterKeyNavigate(e, newRecord) }); } else { me.afterKeyNavigate(e, view.getRecord(0)); } }, onKeyPageUp: function(e) { var me = this, view = me.views[0], rowsVisible = me.getRowsVisible(), newIdx, newRecord; if (rowsVisible) { if (view.bufferedRenderer) { newIdx = Math.max(e.recordIndex - rowsVisible, 0); (me.lastKeyEvent || (me.lastKeyEvent = new Ext.EventObjectImpl())).setEvent(e.browserEvent); view.bufferedRenderer.scrollTo(newIdx, false, me.afterBufferedScrollTo, me); } else { newRecord = view.walkRecs(e.record, -rowsVisible); me.afterKeyNavigate(e, newRecord); } } }, onKeyPageDown: function(e) { var me = this, view = me.views[0], rowsVisible = me.getRowsVisible(), newIdx, newRecord; if (rowsVisible) { if (view.bufferedRenderer) { newIdx = Math.min(e.recordIndex + rowsVisible, me.store.getCount() - 1); (me.lastKeyEvent || (me.lastKeyEvent = new Ext.EventObjectImpl())).setEvent(e.browserEvent); view.bufferedRenderer.scrollTo(newIdx, false, me.afterBufferedScrollTo, me); } else { newRecord = view.walkRecs(e.record, rowsVisible); me.afterKeyNavigate(e, newRecord); } } }, onKeySpace: function(e) { var record = this.lastFocused; if (record) { this.afterKeyNavigate(e, record); } }, onKeyEnter: Ext.emptyFn, onKeyUp: function(e) { var newRecord = this.views[0].walkRecs(e.record, -1); if (newRecord) { this.afterKeyNavigate(e, newRecord); } }, onKeyDown: function(e) { var newRecord = e.record.isExpandingOrCollapsing ? null : this.views[0].walkRecs(e.record, 1); if (newRecord) { this.afterKeyNavigate(e, newRecord); } }, afterBufferedScrollTo: function(newIdx, newRecord) { this.afterKeyNavigate(this.lastKeyEvent, newRecord) }, scrollByDeltaX: function(delta) { var view = this.views[0], section = view.up(), hScroll = section.horizontalScroller; if (hScroll) { hScroll.scrollByDeltaX(delta); } }, onKeyLeft: function(e) { this.scrollByDeltaX(-this.deltaScroll); }, onKeyRight: function(e) { this.scrollByDeltaX(this.deltaScroll); }, onRowClick: function(view, record, item, index, e) { var me = this; if (index !== -1) { if (!me.allowRightMouseSelection(e)) { return; } me.processSelection(view, record, item, index, e); } }, processSelection: function(view, record, item, index, e) { this.selectWithEvent(record, e); }, allowRightMouseSelection: function(e) { var disallow = this.ignoreRightMouseSelection && e.button !== 0; if (disallow) { disallow = this.hasSelection(); } return !disallow; }, onSelectChange: function(record, isSelected, suppressEvent, commitFn) { var me = this, views = me.views, viewsLn = views.length, rowIdx = views[0].indexOf(record), eventName = isSelected ? 'select' : 'deselect', i = 0; if ((suppressEvent || me.fireEvent('before' + eventName, me, record, rowIdx)) !== false && commitFn() !== false) { for (; i < viewsLn; i++) { if (isSelected) { views[i].onRowSelect(rowIdx, suppressEvent); } else { views[i].onRowDeselect(rowIdx, suppressEvent); } } if (!suppressEvent) { me.fireEvent(eventName, me, record, rowIdx); } } }, onLastFocusChanged: function(oldFocused, newFocused, supressFocus) { var views = this.views, viewsLn = views.length, rowIdx, i = 0; if (oldFocused) { rowIdx = views[0].indexOf(oldFocused); if (rowIdx != -1) { for (; i < viewsLn; i++) { views[i].onRowFocus(rowIdx, false, true); } } } if (newFocused) { rowIdx = views[0].indexOf(newFocused); if (rowIdx != -1) { for (i = 0; i < viewsLn; i++) { views[i].onRowFocus(rowIdx, true, supressFocus); } } } this.callParent(arguments); }, onEditorTab: function(editingPlugin, e) { var me = this, view = editingPlugin.context.view, record = editingPlugin.getActiveRecord(), header = editingPlugin.getActiveColumn(), position = view.getPosition(record, header), direction = e.shiftKey ? 'left' : 'right', lastPos; do { lastPos = position; position = view.walkCells(position, direction, e, me.preventWrap); if (lastPos && lastPos.isEqual(position)) { return; } } while (position && (!position.columnHeader.getEditor(record) || !editingPlugin.startEditByPosition(position))); }, getCurrentPosition: function() { var firstSelection = this.selected.getAt(0); if (firstSelection) { return new Ext.grid.CellContext(this.view).setPosition(this.store.indexOf(firstSelection), 0); } }, selectByPosition: function(position) { var context = new Ext.grid.CellContext(this.view); context.setPosition(position.row, position.column); this.select(context.record); }, selectNext: function(keepExisting, suppressEvent) { var me = this, store = me.store, selection = me.getSelection(), record = selection[selection.length - 1], index = me.views[0].indexOf(record) + 1, success; if (index === store.getCount() || index === 0) { success = false; } else { me.doSelect(index, keepExisting, suppressEvent); success = true; } return success; }, selectPrevious: function(keepExisting, suppressEvent) { var me = this, selection = me.getSelection(), record = selection[0], index = me.views[0].indexOf(record) - 1, success; if (index < 0) { success = false; } else { me.doSelect(index, keepExisting, suppressEvent); success = true; } return success; }, isRowSelected: function(record) { return this.isSelected(record); }, isCellSelected: function(view, record, columnHeader) { return this.isSelected(record); } }); Ext.define('Ext.selection.TreeModel', { extend: Ext.selection.RowModel , alias: 'selection.treemodel', constructor: function(config) { this.callParent(arguments); if (this.pruneRemoved) { this.pruneRemoved = false; this.pruneRemovedNodes = true; } }, bindStore: function(store, initial) { var me = this; me.callParent(arguments); if (me.pruneRemovedNodes) { me.view.mon(me.treeStore, { remove: me.onNodeRemove, scope: me }); } }, onNodeRemove: function(parent, node, isMove) { if (!isMove) { this.deselectDeletedRecords([node]); } }, onKeyRight: function(e, t) { this.navExpand(e, t); }, navExpand: function(e, t) { var focused = this.getLastFocused(), view = this.view; if (focused) { if (focused.isExpanded()) { this.onKeyDown(e, t); } else if (focused.isExpandable()) { if (!view.isTreeView) { view = view.lockingPartner; } view.expand(focused); } } }, onKeyLeft: function(e, t) { this.navCollapse(e, t); }, navCollapse: function(e, t) { var me = this, focused = this.getLastFocused(), view = this.view, parentNode; if (focused) { parentNode = focused.parentNode; if (focused.isExpanded()) { if (!view.isTreeView) { view = view.lockingPartner; } view.collapse(focused); } else if (parentNode && !parentNode.isRoot()) { if (e.shiftKey) { me.selectRange(parentNode, focused, e.ctrlKey, 'up'); me.setLastFocused(parentNode); } else if (e.ctrlKey) { me.setLastFocused(parentNode); } else { me.select(parentNode); } } } }, onKeySpace: function(e, t) { if (e.record.data.checked != null) { this.toggleCheck(e); } else { this.callParent(arguments); } }, onKeyEnter: function(e, t) { if (e.record.data.checked != null) { this.toggleCheck(e); } else { this.callParent(arguments); } }, toggleCheck: function(e) { var view = this.view, selected = this.getLastSelected(); e.stopEvent(); if (selected) { if (!view.isTreeView) { view = view.lockingPartner; } view.onCheckChange(selected); } } }); Ext.define('Ext.slider.Thumb', { topZIndex: 10000, constructor: function(config) { var me = this; Ext.apply(me, config || {}, { cls: Ext.baseCSSPrefix + 'slider-thumb', constrain: false }); me.callParent([config]); }, render: function() { var me = this; me.el = me.slider.innerEl.insertFirst(me.getElConfig()); me.onRender(); }, onRender: function() { if (this.disabled) { this.disable(); } this.initEvents(); }, getElConfig: function() { var me = this, slider = me.slider, style = {}; style[slider.vertical ? 'bottom' : slider.horizontalProp] = slider.calculateThumbPosition(slider.normalizeValue(me.value)) + '%'; return { style: style, id : this.id, cls : this.cls, role: 'presentation' }; }, move: function(v, animate) { var me = this, el = me.el, slider = me.slider, styleProp = slider.vertical ? 'bottom' : slider.horizontalProp, to, from; v += '%'; if (!animate) { el.dom.style[styleProp] = v; } else { to = {}; to[styleProp] = v; if (!Ext.supports.GetPositionPercentage) { from = {}; from[styleProp] = el.dom.style[styleProp]; } new Ext.fx.Anim({ target: el, duration: 350, from: from, to: to }); } }, bringToFront: function() { this.el.setStyle('zIndex', this.topZIndex); }, sendToBack: function() { this.el.setStyle('zIndex', ''); }, enable: function() { var me = this; me.disabled = false; if (me.el) { me.el.removeCls(me.slider.disabledCls); } }, disable: function() { var me = this; me.disabled = true; if (me.el) { me.el.addCls(me.slider.disabledCls); } }, initEvents: function() { var me = this, el = me.el; me.tracker = new Ext.dd.DragTracker({ onBeforeStart: Ext.Function.bind(me.onBeforeDragStart, me), onStart : Ext.Function.bind(me.onDragStart, me), onDrag : Ext.Function.bind(me.onDrag, me), onEnd : Ext.Function.bind(me.onDragEnd, me), tolerance : 3, autoStart : 300, overCls : Ext.baseCSSPrefix + 'slider-thumb-over' }); me.tracker.initEl(el); }, onBeforeDragStart : function(e) { if (this.disabled) { return false; } else { this.slider.promoteThumb(this); return true; } }, onDragStart: function(e){ var me = this, slider = me.slider; slider.onDragStart(me, e); me.el.addCls(Ext.baseCSSPrefix + 'slider-thumb-drag'); me.dragging = me.slider.dragging = true; me.dragStartValue = me.value; slider.fireEvent('dragstart', slider, e, me); }, onDrag: function(e) { var me = this, slider = me.slider, index = me.index, newValue = me.getValueFromTracker(), above, below; if (newValue !== undefined) { if (me.constrain) { above = slider.thumbs[index + 1]; below = slider.thumbs[index - 1]; if (below !== undefined && newValue <= below.value) { newValue = below.value; } if (above !== undefined && newValue >= above.value) { newValue = above.value; } } slider.setValue(index, newValue, false); slider.fireEvent('drag', slider, e, me); } }, getValueFromTracker: function() { var slider = this.slider, trackPoint = slider.getTrackpoint(this.tracker.getXY()); if (trackPoint !== undefined) { return slider.reversePixelValue(trackPoint); } }, onDragEnd: function(e) { var me = this, slider = me.slider, value = me.value; slider.onDragEnd(me, e); me.el.removeCls(Ext.baseCSSPrefix + 'slider-thumb-drag'); me.dragging = slider.dragging = false; slider.fireEvent('dragend', slider, e); if (me.dragStartValue != value) { slider.fireEvent('changecomplete', slider, value, me); } }, destroy: function() { Ext.destroy(this.tracker); } }); Ext.define('Ext.slider.Tip', { extend: Ext.tip.Tip , minWidth: 10, alias: 'widget.slidertip', offsets : null, align: null, position: '', defaultVerticalPosition: 'left', defaultHorizontalPosition: 'top', isSliderTip: true, init: function(slider) { var me = this, align, offsets; if (!me.position) { me.position = slider.vertical ? me.defaultVerticalPosition : me.defaultHorizontalPosition; } switch (me.position) { case 'top': offsets = [0, -10]; align = 'b-t?'; break; case 'bottom': offsets = [0, 10]; align = 't-b?'; break; case 'left': offsets = [-10, 0]; align = 'r-l?'; break; case 'right': offsets = [10, 0]; align = 'l-r?'; } if (!me.align) { me.align = align; } if (!me.offsets) { me.offsets = offsets; } slider.on({ scope : me, dragstart: me.onSlide, drag : me.onSlide, dragend : me.hide, destroy : me.destroy }); }, onSlide : function(slider, e, thumb) { var me = this; me.show(); me.update(me.getText(thumb)); me.el.alignTo(thumb.el, me.align, me.offsets); }, getText : function(thumb) { return String(thumb.value); } }); Ext.define('Ext.slider.Multi', { extend: Ext.form.field.Base , alias: 'widget.multislider', alternateClassName: 'Ext.slider.MultiSlider', childEls: [ 'endEl', 'innerEl' ], fieldSubTpl: [ '
    tabIndex="{tabIdx}"', ' aria-orientation="vertical" aria-orientation="horizontal"', '>', '', '
    ', { renderThumbs: function(out, values) { var me = values.$comp, i = 0, thumbs = me.thumbs, len = thumbs.length, thumb, thumbConfig; for (; i < len; i++) { thumb = thumbs[i]; thumbConfig = thumb.getElConfig(); thumbConfig.id = me.id + '-thumb-' + i; Ext.DomHelper.generateMarkup(thumbConfig, out); } }, disableFormats: true } ], horizontalProp: 'left', vertical: false, minValue: 0, maxValue: 100, decimalPrecision: 0, keyIncrement: 1, increment: 0, clickRange: [5,15], clickToChange : true, animate: true, dragging: false, constrainThumbs: true, componentLayout: 'sliderfield', useTips : true, tipText : null, ariaRole: 'slider', initValue: function() { var me = this, extValue = Ext.value, values = extValue(me.values, [extValue(me.value, extValue(me.minValue, 0))]), i = 0, len = values.length; me.originalValue = values; for (; i < len; i++) { me.addThumb(values[i]); } }, initComponent : function() { var me = this, tipPlug, hasTip, p, pLen, plugins; me.thumbs = []; me.keyIncrement = Math.max(me.increment, me.keyIncrement); me.addEvents( 'beforechange', 'change', 'changecomplete', 'dragstart', 'drag', 'dragend' ); me.callParent(); if (me.useTips) { if (Ext.isObject(me.useTips)) { tipPlug = Ext.apply({}, me.useTips); } else { tipPlug = me.tipText ? {getText: me.tipText} : {}; } plugins = me.plugins = me.plugins || []; pLen = plugins.length; for (p = 0; p < pLen; p++) { if (plugins[p].isSliderTip) { hasTip = true; break; } } if (!hasTip) { me.plugins.push(new Ext.slider.Tip(tipPlug)); } } }, addThumb: function(value) { var me = this, thumb = new Ext.slider.Thumb({ ownerCt : me, ownerLayout : me.getComponentLayout(), value : value, slider : me, index : me.thumbs.length, constrain : me.constrainThumbs, disabled : !!me.readOnly }); me.thumbs.push(thumb); if (me.rendered) { thumb.render(); } return thumb; }, promoteThumb: function(topThumb) { var thumbs = this.thumbs, ln = thumbs.length, zIndex, thumb, i; for (i = 0; i < ln; i++) { thumb = thumbs[i]; if (thumb == topThumb) { thumb.bringToFront(); } else { thumb.sendToBack(); } } }, getSubTplData : function() { var me = this; return Ext.apply(me.callParent(), { $comp: me, isVertical: me.vertical, vertical: me.vertical ? Ext.baseCSSPrefix + 'slider-vert' : Ext.baseCSSPrefix + 'slider-horz', minValue: me.minValue, maxValue: me.maxValue, value: me.value, tabIdx: me.tabIndex, childElCls: '' }); }, onRender : function() { var me = this, thumbs = me.thumbs, len = thumbs.length, i = 0, thumb; me.callParent(arguments); for (i = 0; i < len; i++) { thumb = thumbs[i]; thumb.el = me.el.getById(me.id + '-thumb-' + i); thumb.onRender(); } }, initEvents : function() { var me = this; me.mon(me.el, { scope : me, mousedown: me.onMouseDown, keydown : me.onKeyDown }); }, onDragStart: Ext.emptyFn, onDragEnd: Ext.emptyFn, getTrackpoint : function(xy) { var me = this, vertical = me.vertical, sliderTrack = me.innerEl, trackLength, result, positionProperty; if (vertical) { positionProperty = 'top'; trackLength = sliderTrack.getHeight(); } else { positionProperty = me.horizontalProp; trackLength = sliderTrack.getWidth(); } xy = me.transformTrackPoints(sliderTrack.translatePoints(xy)); result = Ext.Number.constrain(xy[positionProperty], 0, trackLength); return vertical ? trackLength - result : result; }, transformTrackPoints: Ext.identityFn, onMouseDown : function(e) { var me = this, thumbClicked = false, i = 0, thumbs = me.thumbs, len = thumbs.length, trackPoint; if (me.disabled) { return; } for (; i < len; i++) { thumbClicked = thumbClicked || e.target == thumbs[i].el.dom; } if (me.clickToChange && !thumbClicked) { trackPoint = me.getTrackpoint(e.getXY()); if (trackPoint !== undefined) { me.onClickChange(trackPoint); } } me.focus(); }, onClickChange : function(trackPoint) { var me = this, thumb, index; thumb = me.getNearest(trackPoint); if (!thumb.disabled) { index = thumb.index; me.setValue(index, Ext.util.Format.round(me.reversePixelValue(trackPoint), me.decimalPrecision), undefined, true); } }, getNearest: function(trackPoint) { var me = this, clickValue = me.reversePixelValue(trackPoint), nearestDistance = me.getRange() + 5, nearest = null, thumbs = me.thumbs, i = 0, len = thumbs.length, thumb, value, dist; for (; i < len; i++) { thumb = me.thumbs[i]; value = thumb.value; dist = Math.abs(value - clickValue); if (Math.abs(dist <= nearestDistance)) { nearest = thumb; nearestDistance = dist; } } return nearest; }, onKeyDown : function(e) { var me = this, k, val; if(me.disabled || me.thumbs.length !== 1) { e.preventDefault(); return; } k = e.getKey(); switch(k) { case e.UP: case e.RIGHT: e.stopEvent(); val = e.ctrlKey ? me.maxValue : me.getValue(0) + me.keyIncrement; me.setValue(0, val, undefined, true); break; case e.DOWN: case e.LEFT: e.stopEvent(); val = e.ctrlKey ? me.minValue : me.getValue(0) - me.keyIncrement; me.setValue(0, val, undefined, true); break; default: e.preventDefault(); } }, normalizeValue : function(v) { var me = this, snapFn = me.zeroBasedSnapping ? 'snap' : 'snapInRange'; v = Ext.Number[snapFn](v, me.increment, me.minValue, me.maxValue); v = Ext.util.Format.round(v, me.decimalPrecision); v = Ext.Number.constrain(v, me.minValue, me.maxValue); return v; }, setMinValue : function(val) { var me = this, thumbs = me.thumbs, len = thumbs.length, thumb, i; me.minValue = val; for (i = 0; i < len; ++i) { thumb = thumbs[i]; if (thumb.value < val) { me.setValue(i, val, false); } } me.syncThumbs(); }, setMaxValue : function(val) { var me = this, thumbs = me.thumbs, len = thumbs.length, thumb, i; me.maxValue = val; for (i = 0; i < len; ++i) { thumb = thumbs[i]; if (thumb.value > val) { me.setValue(i, val, false); } } me.syncThumbs(); }, setValue : function(index, value, animate, changeComplete) { var me = this, thumbs = me.thumbs, thumb, len, i, values; if (Ext.isArray(index)) { values = index; animate = value; for (i = 0, len = values.length; i < len; ++i) { thumb = thumbs[i]; if (thumb) { me.setValue(i, values[i], animate); } } return me; } thumb = me.thumbs[index]; value = me.normalizeValue(value); if (value !== thumb.value && me.fireEvent('beforechange', me, value, thumb.value, thumb) !== false) { thumb.value = value; if (me.rendered) { thumb.move(me.calculateThumbPosition(value), Ext.isDefined(animate) ? animate !== false : me.animate); me.fireEvent('change', me, value, thumb); me.checkDirty(); if (changeComplete) { me.fireEvent('changecomplete', me, value, thumb); } } } return me; }, calculateThumbPosition : function(v) { var me = this, minValue = me.minValue, pos = (v - minValue) / me.getRange() * 100; if (isNaN(pos)) { pos = minValue; } return pos; }, getRatio : function() { var me = this, innerEl = me.innerEl, trackLength = me.vertical ? innerEl.getHeight() : innerEl.getWidth(), valueRange = me.getRange(); return valueRange === 0 ? trackLength : (trackLength / valueRange); }, getRange: function(){ return this.maxValue - this.minValue; }, reversePixelValue : function(pos) { return this.minValue + (pos / this.getRatio()); }, reversePercentageValue : function(pos) { return this.minValue + this.getRange() * (pos / 100); }, onDisable: function() { var me = this, i = 0, thumbs = me.thumbs, len = thumbs.length, thumb, el, xy; me.callParent(); for (; i < len; i++) { thumb = thumbs[i]; el = thumb.el; thumb.disable(); if(Ext.isIE) { xy = el.getXY(); el.hide(); me.innerEl.addCls(me.disabledCls).dom.disabled = true; if (!me.thumbHolder) { me.thumbHolder = me.endEl.createChild({ role: 'presentation', cls: Ext.baseCSSPrefix + 'slider-thumb ' + me.disabledCls }); } me.thumbHolder.show().setXY(xy); } } }, onEnable: function() { var me = this, i = 0, thumbs = me.thumbs, len = thumbs.length, thumb, el; this.callParent(); for (; i < len; i++) { thumb = thumbs[i]; el = thumb.el; thumb.enable(); if (Ext.isIE) { me.innerEl.removeCls(me.disabledCls).dom.disabled = false; if (me.thumbHolder) { me.thumbHolder.hide(); } el.show(); me.syncThumbs(); } } }, syncThumbs : function() { if (this.rendered) { var thumbs = this.thumbs, length = thumbs.length, i = 0; for (; i < length; i++) { thumbs[i].move(this.calculateThumbPosition(thumbs[i].value)); } } }, getValue : function(index) { return Ext.isNumber(index) ? this.thumbs[index].value : this.getValues(); }, getValues: function() { var values = [], i = 0, thumbs = this.thumbs, len = thumbs.length; for (; i < len; i++) { values.push(thumbs[i].value); } return values; }, getSubmitValue: function() { var me = this; return (me.disabled || !me.submitValue) ? null : me.getValue(); }, reset: function() { var me = this, arr = [].concat(me.originalValue), a = 0, aLen = arr.length, val; for (; a < aLen; a++) { val = arr[a]; me.setValue(a, val); } me.clearInvalid(); delete me.wasValid; }, setReadOnly: function(readOnly){ var me = this, thumbs = me.thumbs, len = thumbs.length, i = 0; me.callParent(arguments); readOnly = me.readOnly; for (; i < len; ++i) { if (readOnly) { thumbs[i].disable(); } else { thumbs[i].enable(); } } }, beforeDestroy : function() { var me = this, thumbs = me.thumbs, t = 0, tLen = thumbs.length, thumb; Ext.destroy(me.innerEl, me.endEl, me.focusEl); for (; t < tLen; t++) { thumb = thumbs[t]; Ext.destroy(thumb); } me.callParent(); } }); Ext.define('Ext.tab.Tab', { extend: Ext.button.Button , alias: 'widget.tab', isTab: true, baseCls: Ext.baseCSSPrefix + 'tab', closeElOverCls: Ext.baseCSSPrefix + 'tab-close-btn-over', activeCls: 'active', closableCls: 'closable', closable: true, closeText: 'Close Tab', active: false, childEls: [ 'closeEl' ], scale: false, position: 'top', ariaRole: 'tab', initComponent: function() { var me = this; me.addEvents( 'activate', 'deactivate', 'beforeclose', 'close' ); me.callParent(arguments); if (me.card) { me.setCard(me.card); } me.overCls = ['over', me.position + '-over']; }, getTemplateArgs: function() { var me = this, result = me.callParent(); result.closable = me.closable; result.closeText = me.closeText; return result; }, getFramingInfoCls: function(){ return this.baseCls + '-' + this.ui + '-' + this.position; }, beforeRender: function() { var me = this, tabBar = me.up('tabbar'), tabPanel = me.up('tabpanel'); me.callParent(); me.addClsWithUI(me.position); if (me.active) { me.addClsWithUI([me.activeCls, me.position + '-' + me.activeCls]); } me.syncClosableUI(); if (!me.minWidth) { me.minWidth = (tabBar) ? tabBar.minTabWidth : me.minWidth; if (!me.minWidth && tabPanel) { me.minWidth = tabPanel.minTabWidth; } if (me.minWidth && me.iconCls) { me.minWidth += 25; } } if (!me.maxWidth) { me.maxWidth = (tabBar) ? tabBar.maxTabWidth : me.maxWidth; if (!me.maxWidth && tabPanel) { me.maxWidth = tabPanel.maxTabWidth; } } }, onRender: function() { var me = this; me.setElOrientation(); me.callParent(arguments); if (me.closable) { me.closeEl.addClsOnOver(me.closeElOverCls); } me.initKeyNav(); }, initKeyNav: function() { var me = this; me.keyNav = new Ext.util.KeyNav(me.el, { enter: me.onEnterKey, del: me.onDeleteKey, scope: me }); }, setElOrientation: function() { var position = this.position; if (position === 'left' || position === 'right') { this.el.setVertical(position === 'right' ? 90 : 270); } }, enable : function(silent) { var me = this; me.callParent(arguments); me.removeClsWithUI(me.position + '-disabled'); return me; }, disable : function(silent) { var me = this; me.callParent(arguments); me.addClsWithUI(me.position + '-disabled'); return me; }, onDestroy: function() { var me = this; Ext.destroy(me.keyNav); delete me.keyNav; me.callParent(arguments); }, setClosable: function(closable) { var me = this; closable = (!arguments.length || !!closable); if (me.closable != closable) { me.closable = closable; if (me.card) { me.card.closable = closable; } me.syncClosableUI(); if (me.rendered) { me.syncClosableElements(); me.updateLayout(); } } }, syncClosableElements: function () { var me = this, closeEl = me.closeEl; if (me.closable) { if (!closeEl) { closeEl = me.closeEl = me.btnWrap.insertSibling({ tag: 'a', role: 'presentation', cls: me.baseCls + '-close-btn', href: '#', title: me.closeText }, 'after'); } closeEl.addClsOnOver(me.closeElOverCls); } else if (closeEl) { closeEl.remove(); delete me.closeEl; } }, syncClosableUI: function () { var me = this, classes = [me.closableCls, me.closableCls + '-' + me.position]; if (me.closable) { me.addClsWithUI(classes); } else { me.removeClsWithUI(classes); } }, setCard: function(card) { var me = this; me.card = card; me.setText(me.title || card.title); me.setIconCls(me.iconCls || card.iconCls); me.setIcon(me.icon || card.icon); me.setGlyph(me.glyph || card.glyph); }, onCloseClick: function() { var me = this; if (me.fireEvent('beforeclose', me) !== false) { if (me.tabBar) { if (me.tabBar.closeTab(me) === false) { return; } } else { me.fireClose(); } } }, fireClose: function(){ this.fireEvent('close', this); }, onEnterKey: function(e) { var me = this; if (me.tabBar) { me.tabBar.onClick(e, me.el); } }, onDeleteKey: function(e) { if (this.closable) { this.onCloseClick(); } }, activate : function(supressEvent) { var me = this; me.active = true; me.addClsWithUI([me.activeCls, me.position + '-' + me.activeCls]); if (supressEvent !== true) { me.fireEvent('activate', me); } }, deactivate : function(supressEvent) { var me = this; me.active = false; me.removeClsWithUI([me.activeCls, me.position + '-' + me.activeCls]); if (supressEvent !== true) { me.fireEvent('deactivate', me); } } }); Ext.define('Ext.util.Point', { extend: Ext.util.Region , statics: { fromEvent: function(e) { e = e.browserEvent || e; e = (e.changedTouches && e.changedTouches.length > 0) ? e.changedTouches[0] : e; return new this(e.pageX, e.pageY); } }, constructor: function(x, y) { this.callParent([y, x, y, x]); }, toString: function() { return "Point[" + this.x + "," + this.y + "]"; }, equals: function(p) { return (this.x == p.x && this.y == p.y); }, isWithin: function(p, threshold) { if (!Ext.isObject(threshold)) { threshold = { x: threshold, y: threshold }; } return (this.x <= p.x + threshold.x && this.x >= p.x - threshold.x && this.y <= p.y + threshold.y && this.y >= p.y - threshold.y); }, isContainedBy: function(region) { if (!(region instanceof Ext.util.Region)) { region = Ext.get(region.el || region).getRegion(); } return region.contains(this); }, roundedEquals: function(p) { return (Math.round(this.x) == Math.round(p.x) && Math.round(this.y) == Math.round(p.y)); } }, function() { this.prototype.translate = Ext.util.Region.prototype.translateBy; }); Ext.define('Ext.tab.Bar', { extend: Ext.panel.Header , alias: 'widget.tabbar', baseCls: Ext.baseCSSPrefix + 'tab-bar', isTabBar: true, defaultType: 'tab', plain: false, ariaRole: 'tablist', childEls: [ 'body', 'strip' ], renderTpl: [ '', '' ], _reverseDockNames: { left: 'right', right: 'left' }, initComponent: function() { var me = this; if (me.plain) { me.addCls(me.baseCls + '-plain'); } me.addClsWithUI(me.orientation); me.addEvents( 'change' ); me.callParent(arguments); Ext.merge(me.layout, me.initialConfig.layout); me.layout.align = (me.orientation == 'vertical') ? 'left' : 'top'; me.layout.overflowHandler = new Ext.layout.container.boxOverflow.Scroller(me.layout); me.remove(me.titleCmp); delete me.titleCmp; Ext.apply(me.renderData, { bodyCls: me.bodyCls, dock: me.dock }); }, onRender: function() { var me = this; me.callParent(); if (me.orientation === 'vertical' && (Ext.isIE8 || Ext.isIE9) && Ext.isStrict) { me.el.on({ mousemove: me.onMouseMove, scope: me }); } }, afterRender: function() { var layout = this.layout; this.callParent(); if (Ext.isIE9 && Ext.isStrict && this.orientation === 'vertical') { layout.innerCt.on('scroll', function() { layout.innerCt.dom.scrollLeft = 0; }); } }, afterLayout: function() { this.adjustTabPositions(); this.callParent(arguments); }, adjustTabPositions: function() { var items = this.items.items, i = items.length, tab; if (!Ext.isIE9m) { if (this.dock === 'right') { while (i--) { tab = items[i]; if (tab.isVisible()) { tab.el.setStyle('left', tab.lastBox.width + 'px'); } } } else if (this.dock === 'left') { while (i--) { tab = items[i]; if (tab.isVisible()) { tab.el.setStyle('left', -tab.lastBox.height + 'px'); } } } } }, getLayout: function() { var me = this; me.layout.type = (me.orientation === 'horizontal') ? 'hbox' : 'vbox'; return me.callParent(arguments); }, onAdd: function(tab) { tab.position = this.dock; this.callParent(arguments); }, onRemove: function(tab) { var me = this; if (tab === me.previousTab) { me.previousTab = null; } me.callParent(arguments); }, afterComponentLayout : function(width) { var me = this, needsScroll = me.needsScroll; me.callParent(arguments); if (needsScroll) { me.layout.overflowHandler.scrollToItem(me.activeTab); } delete me.needsScroll; }, onClick: function(e, target) { var me = this, tabPanel = me.tabPanel, tabEl, tab, isCloseClick, tabInfo; if (e.getTarget('.' + Ext.baseCSSPrefix + 'box-scroller')) { return; } if (me.orientation === 'vertical' && (Ext.isIE8 || Ext.isIE9) && Ext.isStrict) { tabInfo = me.getTabInfoFromPoint(e.getXY()); tab = tabInfo.tab; isCloseClick = tabInfo.close; } else { tabEl = e.getTarget('.' + Ext.tab.Tab.prototype.baseCls); tab = tabEl && Ext.getCmp(tabEl.id); isCloseClick = tab && tab.closeEl && (target === tab.closeEl.dom); } if (isCloseClick) { e.preventDefault(); } if (tab && tab.isDisabled && !tab.isDisabled()) { if (tab.closable && isCloseClick) { tab.onCloseClick(); } else { if (tabPanel) { tabPanel.setActiveTab(tab.card); } else { me.setActiveTab(tab); } tab.focus(); } } }, onMouseMove: function(e) { var me = this, overTab = me._overTab, tabInfo, tab; if (e.getTarget('.' + Ext.baseCSSPrefix + 'box-scroller')) { return; } tabInfo = me.getTabInfoFromPoint(e.getXY()); tab = tabInfo.tab; if (tab !== overTab) { if (overTab && overTab.rendered) { overTab.onMouseLeave(e); me._overTab = null; } if (tab) { tab.onMouseEnter(e); me._overTab = tab; if (!tab.disabled) { me.el.setStyle('cursor', 'pointer'); } } else { me.el.setStyle('cursor', 'default'); } } }, onMouseLeave: function(e) { var overTab = this._overTab; if (overTab && overTab.rendered) { overTab.onMouseLeave(e); } }, getTabInfoFromPoint: function(xy) { var me = this, tabs = me.items.items, length = tabs.length, innerCt = me.layout.innerCt, innerCtXY = innerCt.getXY(), point = new Ext.util.Point(xy[0], xy[1]), i = 0, lastBox, tabRegion, closeEl, close, closeXY, closeX, closeY, closeWidth, closeHeight, tabX, tabY, tabWidth, tabHeight, closeRegion, isTabReversed, direction, tab; for (; i < length; i++) { lastBox = tabs[i].lastBox; tabX = innerCtXY[0] + lastBox.x; tabY = innerCtXY[1] - innerCt.dom.scrollTop + lastBox.y; tabWidth = lastBox.width; tabHeight = lastBox.height; tabRegion = new Ext.util.Region( tabY, tabX + tabWidth, tabY + tabHeight, tabX ); if (tabRegion.contains(point)) { tab = tabs[i]; closeEl = tab.closeEl; if (closeEl) { if (me._isTabReversed === undefined) { me._isTabReversed = isTabReversed = (tab.btnWrap.dom.currentStyle.filter.indexOf('rotation=2') !== -1); } direction = isTabReversed ? this._reverseDockNames[me.dock] : me.dock; closeWidth = closeEl.getWidth(); closeHeight = closeEl.getHeight(); closeXY = me.getCloseXY(closeEl, tabX, tabY, tabWidth, tabHeight, closeWidth, closeHeight, direction); closeX = closeXY[0]; closeY = closeXY[1]; closeRegion = new Ext.util.Region( closeY, closeX + closeWidth, closeY + closeHeight, closeX ); close = closeRegion.contains(point); } break; } } return { tab: tab, close: close }; }, getCloseXY: function(closeEl, tabX, tabY, tabWidth, tabHeight, closeWidth, closeHeight, direction) { var closeXY = closeEl.getXY(), closeX, closeY; if (direction === 'right') { closeX = tabX + tabWidth - ((closeXY[1] - tabY) + closeHeight); closeY = tabY + (closeXY[0] - tabX); } else { closeX = tabX + (closeXY[1] - tabY); closeY = tabY + tabX + tabHeight - closeXY[0] - closeWidth; } return [closeX, closeY]; }, closeTab: function(toClose) { var me = this, card = toClose.card, tabPanel = me.tabPanel, toActivate; if (card && card.fireEvent('beforeclose', card) === false) { return false; } toActivate = me.findNextActivatable(toClose); Ext.suspendLayouts(); if (tabPanel && card) { delete toClose.ownerCt; card.fireEvent('close', card); tabPanel.remove(card); if (!tabPanel.getComponent(card)) { toClose.fireClose(); me.remove(toClose); } else { toClose.ownerCt = me; Ext.resumeLayouts(true); return false; } } if (toActivate) { if (tabPanel) { tabPanel.setActiveTab(toActivate.card); } else { me.setActiveTab(toActivate); } toActivate.focus(); } Ext.resumeLayouts(true); }, findNextActivatable: function(toClose) { var me = this; if (toClose.active && me.items.getCount() > 1) { return (me.previousTab && me.previousTab !== toClose && !me.previousTab.disabled) ? me.previousTab : (toClose.next('tab[disabled=false]') || toClose.prev('tab[disabled=false]')); } }, setActiveTab: function(tab, initial) { var me = this; if (!tab.disabled && tab !== me.activeTab) { if (me.activeTab) { if (me.activeTab.isDestroyed) { me.previousTab = null; } else { me.previousTab = me.activeTab; me.activeTab.deactivate(); } } tab.activate(); me.activeTab = tab; me.needsScroll = true; if (!initial) { me.fireEvent('change', me, tab, tab.card); me.updateLayout(); } } } }); Ext.define('Ext.tree.Column', { extend: Ext.grid.column.Column , alias: 'widget.treecolumn', tdCls: Ext.baseCSSPrefix + 'grid-cell-treecolumn', autoLock: true, lockable: false, draggable: false, hideable: false, iconCls: Ext.baseCSSPrefix + 'tree-icon', checkboxCls: Ext.baseCSSPrefix + 'tree-checkbox', elbowCls: Ext.baseCSSPrefix + 'tree-elbow', expanderCls: Ext.baseCSSPrefix + 'tree-expander', textCls: Ext.baseCSSPrefix + 'tree-node-text', innerCls: Ext.baseCSSPrefix + 'grid-cell-inner-treecolumn', isTreeColumn: true, cellTpl: [ '', 'lineempty" role="presentation"/>', '', '-end-plus {expanderCls}" role="presentation"/>', '', ' {checkboxCls}-checked"/>', '', 'leafparent {iconCls}"', 'style="background-image:url({icon})"/>', '', '{value}', '', '{value}', '' ], initComponent: function() { var me = this, renderer = me.renderer; if (typeof renderer == 'string') { renderer = Ext.util.Format[renderer]; } me.origRenderer = renderer; me.origScope = me.scope || window; me.renderer = me.treeRenderer; me.scope = me; me.callParent(); }, treeRenderer: function(value, metaData, record, rowIdx, colIdx, store, view){ var me = this, cls = record.get('cls'), rendererData; if (cls) { metaData.tdCls += ' ' + cls; } rendererData = me.initTemplateRendererData(value, metaData, record, rowIdx, colIdx, store, view); return me.getTpl('cellTpl').apply(rendererData); }, initTemplateRendererData: function(value, metaData, record, rowIdx, colIdx, store, view) { var me = this, renderer = me.origRenderer, data = record.data, parent = record.parentNode, rootVisible = view.rootVisible, lines = [], parentData; while (parent && (rootVisible || parent.data.depth > 0)) { parentData = parent.data; lines[rootVisible ? parentData.depth : parentData.depth - 1] = parentData.isLast ? 0 : 1; parent = parent.parentNode; } return { record: record, baseIconCls: me.iconCls, iconCls: data.iconCls, icon: data.icon, checkboxCls: me.checkboxCls, checked: data.checked, elbowCls: me.elbowCls, expanderCls: me.expanderCls, textCls: me.textCls, leaf: data.leaf, expandable: record.isExpandable(), isLast: data.isLast, blankUrl: Ext.BLANK_IMAGE_URL, href: data.href, hrefTarget: data.hrefTarget, lines: lines, metaData: metaData, childCls: me.getChildCls ? me.getChildCls() + ' ' : '', value: renderer ? renderer.apply(me.origScope, arguments) : value }; } }); Ext.define('Ext.selection.CheckboxModel', { alias: 'selection.checkboxmodel', extend: Ext.selection.RowModel , mode: 'MULTI', injectCheckbox: 0, checkOnly: false, showHeaderCheckbox: undefined, checkSelector: '.' + Ext.baseCSSPrefix + 'grid-row-checker', headerWidth: 24, checkerOnCls: Ext.baseCSSPrefix + 'grid-hd-checker-on', constructor: function(){ var me = this; me.callParent(arguments); if (me.mode === 'SINGLE' && me.showHeaderCheckbox !== true) { me.showHeaderCheckbox = false; } }, beforeViewRender: function(view) { var me = this, owner; me.callParent(arguments); if (!me.hasLockedHeader() || view.headerCt.lockedCt) { if (me.showHeaderCheckbox !== false) { view.headerCt.on('headerclick', me.onHeaderClick, me); } me.addCheckbox(view, true); owner = view.ownerCt; if (view.headerCt.lockedCt) { owner = owner.ownerCt; } me.mon(owner, 'reconfigure', me.onReconfigure, me); } }, bindComponent: function(view) { var me = this; me.sortable = false; me.callParent(arguments); }, hasLockedHeader: function(){ var views = this.views, vLen = views.length, v; for (v = 0; v < vLen; v++) { if (views[v].headerCt.lockedCt) { return true; } } return false; }, addCheckbox: function(view, initial){ var me = this, checkbox = me.injectCheckbox, headerCt = view.headerCt; if (checkbox !== false) { if (checkbox == 'first') { checkbox = 0; } else if (checkbox == 'last') { checkbox = headerCt.getColumnCount(); } Ext.suspendLayouts(); if (view.getStore().buffered) { me.showHeaderCheckbox = false; } headerCt.add(checkbox, me.getHeaderConfig()); Ext.resumeLayouts(); } if (initial !== true) { view.refresh(); } }, onReconfigure: function(grid, store, columns) { if(columns) { this.addCheckbox(this.views[0]); } }, toggleUiHeader: function(isChecked) { var view = this.views[0], headerCt = view.headerCt, checkHd = headerCt.child('gridcolumn[isCheckerHd]'), cls = this.checkerOnCls; if (checkHd) { if (isChecked) { checkHd.addCls(cls); } else { checkHd.removeCls(cls); } } }, onHeaderClick: function(headerCt, header, e) { if (header.isCheckerHd) { e.stopEvent(); var me = this, isChecked = header.el.hasCls(Ext.baseCSSPrefix + 'grid-hd-checker-on'); me.preventFocus = true; if (isChecked) { me.deselectAll(); } else { me.selectAll(); } delete me.preventFocus; } }, getHeaderConfig: function() { var me = this, showCheck = me.showHeaderCheckbox !== false; return { isCheckerHd: showCheck, text : ' ', clickTargetName: 'el', width: me.headerWidth, sortable: false, draggable: false, resizable: false, hideable: false, menuDisabled: true, dataIndex: '', cls: showCheck ? Ext.baseCSSPrefix + 'column-header-checkbox ' : '', renderer: Ext.Function.bind(me.renderer, me), editRenderer: me.editRenderer || me.renderEmpty, locked: me.hasLockedHeader() }; }, renderEmpty: function() { return ' '; }, refresh: function() { this.callParent(arguments); this.updateHeaderState(); }, renderer: function(value, metaData, record, rowIndex, colIndex, store, view) { var baseCSSPrefix = Ext.baseCSSPrefix; metaData.tdCls = baseCSSPrefix + 'grid-cell-special ' + baseCSSPrefix + 'grid-cell-row-checker'; return ''; }, processSelection: function(view, record, item, index, e){ var me = this, checker = e.getTarget(me.checkSelector), mode; if (me.checkOnly && !checker) { return; } if (checker) { mode = me.getSelectionMode(); if (mode !== 'SINGLE') { me.setSelectionMode('SIMPLE'); } me.selectWithEvent(record, e); me.setSelectionMode(mode); } else { me.selectWithEvent(record, e); } }, onSelectChange: function() { this.callParent(arguments); if (!this.suspendChange) { this.updateHeaderState(); } }, onStoreLoad: function() { this.callParent(arguments); this.updateHeaderState(); }, onStoreAdd: function() { this.callParent(arguments); this.updateHeaderState(); }, onStoreRemove: function() { this.callParent(arguments); this.updateHeaderState(); }, onStoreRefresh: function(){ this.callParent(arguments); this.updateHeaderState(); }, maybeFireSelectionChange: function(fireEvent) { if (fireEvent && !this.suspendChange) { this.updateHeaderState(); } this.callParent(arguments); }, resumeChanges: function(){ this.callParent(); if (!this.suspendChange) { this.updateHeaderState(); } }, updateHeaderState: function() { var me = this, store = me.store, storeCount = store.getCount(), views = me.views, hdSelectStatus = false, selectedCount = 0, selected, len, i; if (!store.buffered && storeCount > 0) { selected = me.selected; hdSelectStatus = true; for (i = 0, len = selected.getCount(); i < len; ++i) { if (!me.storeHasSelected(selected.getAt(i))) { break; } ++selectedCount; } hdSelectStatus = storeCount === selectedCount; } if (views && views.length) { me.toggleUiHeader(hdSelectStatus); } } }); Ext.define('Ext.slider.Single', { extend: Ext.slider.Multi , alias: ['widget.slider', 'widget.sliderfield'], alternateClassName: ['Ext.Slider', 'Ext.form.SliderField', 'Ext.slider.SingleSlider', 'Ext.slider.Slider'], getValue: function() { return this.callParent([0]); }, setValue: function(value, animate) { var args = arguments, len = args.length; if (len == 1 || (len <= 3 && typeof args[1] != 'number')) { args = Ext.toArray(args); args.unshift(0); } return this.callParent(args); }, getNearest : function(){ return this.thumbs[0]; } }); Ext.define('Ext.state.CookieProvider', { extend: Ext.state.Provider , constructor : function(config){ var me = this; me.path = "/"; me.expires = new Date(Ext.Date.now() + (1000*60*60*24*7)); me.domain = null; me.secure = false; me.callParent(arguments); me.state = me.readCookies(); }, set : function(name, value){ var me = this; if(typeof value == "undefined" || value === null){ me.clear(name); return; } me.setCookie(name, value); me.callParent(arguments); }, clear : function(name){ this.clearCookie(name); this.callParent(arguments); }, readCookies : function(){ var cookies = {}, c = document.cookie + ";", re = /\s?(.*?)=(.*?);/g, prefix = this.prefix, len = prefix.length, matches, name, value; while((matches = re.exec(c)) != null){ name = matches[1]; value = matches[2]; if (name && name.substring(0, len) == prefix){ cookies[name.substr(len)] = this.decodeValue(value); } } return cookies; }, setCookie : function(name, value){ var me = this; document.cookie = me.prefix + name + "=" + me.encodeValue(value) + ((me.expires == null) ? "" : ("; expires=" + me.expires.toGMTString())) + ((me.path == null) ? "" : ("; path=" + me.path)) + ((me.domain == null) ? "" : ("; domain=" + me.domain)) + ((me.secure == true) ? "; secure" : ""); }, clearCookie : function(name){ var me = this; document.cookie = me.prefix + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" + ((me.path == null) ? "" : ("; path=" + me.path)) + ((me.domain == null) ? "" : ("; domain=" + me.domain)) + ((me.secure == true) ? "; secure" : ""); } }); Ext.define('Ext.util.LocalStorage', { id: null, destroyed: false, lazyKeys: true, prefix: '', session: false, _keys: null, _store: null, _users: 0, statics: { cache: {}, get: function (id) { var me = this, cache = me.cache, config = { _users: 1 }, instance; if (Ext.isString(id)) { config.id = id; } else { Ext.apply(config, id); } if (!(instance = cache[config.id])) { instance = new me(config); } else { ++instance._users; } return instance; }, supported: true }, constructor: function (config) { var me = this; Ext.apply(me, config); if (me._users) { Ext.util.LocalStorage.cache[me.id] = me; } me.init(); }, init: function () { var me = this, id = me.id; if (!me.prefix && id) { me.prefix = id + '-'; } me._store = (me.session ? window.sessionStorage : window.localStorage); }, destroy: function () { var me = this; delete Ext.util.LocalStorage.cache[me.id]; me._store = me._keys = null; me.destroyed = true; me.destroy = Ext.emptyFn; }, getKeys: function () { var me = this, store = me._store, prefix = me.prefix, keys = me._keys, n = prefix.length, i, key; if (!keys) { me._keys = keys = []; for (i = store.length; i--; ) { key = store.key(i); if (key.length > n) { if (prefix === key.substring(0, n)) { keys.push(key.substring(n)); } } } } return keys; }, release: function () { if (! --this._users) { this.destroy(); } }, save: Ext.emptyFn, clear: function () { var me = this, store = me._store, prefix = me.prefix, keys = me._keys || me.getKeys(), i; for (i = keys.length; i--; ) { store.removeItem(prefix + keys[i]); } keys.length = 0; }, key: function (index) { var keys = this._keys || this.getKeys(); return (0 <= index && index < keys.length) ? keys[index] : null; }, getItem: function (key) { var k = this.prefix + key; return this._store.getItem(k); }, removeItem: function (key) { var me = this, k = me.prefix + key, store = me._store, keys = me._keys, length = store.length; store.removeItem(k); if (keys && length !== store.length) { if (me.lazyKeys) { me._keys = null; } else { Ext.Array.remove(keys, key); } } }, setItem: function (key, value) { var me = this, k = me.prefix + key, store = me._store, length = store.length, keys = me._keys; store.setItem(k, value); if (keys && length !== store.length) { keys.push(key); } } }, function () { var LocalStorage = this; if ('localStorage' in window) { return; } if (!Ext.isIE) { LocalStorage.supported = false; return; } LocalStorage.override({ data: null, flushDelay: 1, init: function () { var me = this, data = me.data, el; me.el = el = document.createElement('div'); el.id = (me.id || (me.id = 'extjs-localstore')); el.addBehavior('#default#userdata'); Ext.getHead().dom.appendChild(el); el.load(me.id); data = el.getAttribute('xdata'); me.data = data = (data ? Ext.decode(data) : {}); me._flushFn = function () { me._timer = null; me.save(0); }; }, destroy: function () { var me = this, el = me.el; if (el) { if (me._timer) { me.save(); } el.parentNode.removeChild(el); me.data = me.el = null; me.callParent(); } }, getKeys: function () { var me = this, keys = me._keys; if (!keys) { me._keys = keys = Ext.Object.getKeys(me.data); } return keys; }, save: function (delay) { var me = this; if (!delay) { if (me._timer) { clearTimeout(me._timer); me._timer = null; } me.el.setAttribute('xdata', Ext.encode(me.data)); me.el.save(me.id); } else if (!me._timer) { me._timer = setTimeout(me._flushFn, delay); } }, clear: function () { var me = this; me.data = {}; me._keys = null; me.save(me.flushDelay); }, getItem: function (key) { var data = this.data; return (key in data) ? data[key] : null; }, removeItem: function (key) { var me = this, keys = me._keys, data = me.data; if (key in data) { delete data[key]; if (keys) { if (me.lazyKeys) { me._keys = null; } else { Ext.Array.remove(keys, key); } } me.save(me.flushDelay); } }, setItem: function (key, value) { var me = this, data = me.data, keys = me._keys; if (keys && !(key in data)) { keys.push(key); } data[key] = value; me.save(me.flushDelay); } }); }); Ext.define('Ext.state.LocalStorageProvider', { extend: Ext.state.Provider , alias: 'state.localstorage', constructor: function () { var me = this; me.callParent(arguments); me.store = me.getStorageObject(); if (me.store) { me.state = me.readLocalStorage(); } else { me.state = {}; } }, readLocalStorage: function () { var store = this.store, data = {}, keys = store.getKeys(), i = keys.length, key; while (i--) { key = keys[i]; data[key] = this.decodeValue(store.getItem(key)); } return data; }, set: function (name, value) { var me = this; me.clear(name); if (value != null) { me.store.setItem(name, me.encodeValue(value)); me.callParent(arguments); } }, clear: function (name) { this.store.removeItem(name); this.callParent(arguments); }, getStorageObject: function () { var prefix = this.prefix, id = prefix, n = id.length - 1; if (id.charAt(n) === '-') { id = id.substring(0, n); } return new Ext.util.LocalStorage({ id: id, prefix: prefix }); } }); Ext.define('Ext.tab.Panel', { extend: Ext.panel.Panel , alias: 'widget.tabpanel', alternateClassName: ['Ext.TabPanel'], tabPosition : 'top', removePanelHeader: true, plain: false, itemCls: Ext.baseCSSPrefix + 'tabpanel-child', minTabWidth: undefined, maxTabWidth: undefined, deferredRender : true, initComponent: function() { var me = this, dockedItems = [].concat(me.dockedItems || []), activeTab = me.activeTab || (me.activeTab = 0), tabPosition = me.tabPosition; me.layout = new Ext.layout.container.Card(Ext.apply({ owner: me, deferredRender: me.deferredRender, itemCls: me.itemCls, activeItem: activeTab }, me.layout)); me.tabBar = new Ext.tab.Bar(Ext.apply({ ui: me.ui, dock: me.tabPosition, orientation: (tabPosition == 'top' || tabPosition == 'bottom') ? 'horizontal' : 'vertical', plain: me.plain, cardLayout: me.layout, tabPanel: me }, me.tabBar)); dockedItems.push(me.tabBar); me.dockedItems = dockedItems; me.addEvents( 'beforetabchange', 'tabchange' ); me.callParent(arguments); activeTab = me.activeTab = me.getComponent(activeTab); if (activeTab) { me.tabBar.setActiveTab(activeTab.tab, true); } }, setActiveTab: function(card) { var me = this, previous; card = me.getComponent(card); if (card) { previous = me.getActiveTab(); if (previous === card || me.fireEvent('beforetabchange', me, card, previous) === false) { return false; } if (!card.isComponent) { Ext.suspendLayouts(); card = me.add(card); Ext.resumeLayouts(); } me.activeTab = card; Ext.suspendLayouts(); me.layout.setActiveItem(card); card = me.activeTab = me.layout.getActiveItem(); if (card && card !== previous) { me.tabBar.setActiveTab(card.tab); Ext.resumeLayouts(true); if (previous !== card) { me.fireEvent('tabchange', me, card, previous); } } else { Ext.resumeLayouts(true); } return card; } }, getActiveTab: function() { var me = this, result = me.getComponent(me.activeTab); if (result && me.items.indexOf(result) != -1) { me.activeTab = result; } else { me.activeTab = null; } return me.activeTab; }, getTabBar: function() { return this.tabBar; }, onAdd: function(item, index) { var me = this, cfg = item.tabConfig || {}, defaultConfig = { xtype: 'tab', ui: me.tabBar.ui, card: item, disabled: item.disabled, closable: item.closable, hidden: item.hidden && !item.hiddenByLayout, tooltip: item.tooltip, tabBar: me.tabBar, position: me.tabPosition }; if (item.closeText !== undefined) { defaultConfig.closeText = item.closeText; } cfg = Ext.applyIf(cfg, defaultConfig); item.tab = me.tabBar.insert(index, cfg); item.on({ scope : me, enable: me.onItemEnable, disable: me.onItemDisable, beforeshow: me.onItemBeforeShow, iconchange: me.onItemIconChange, iconclschange: me.onItemIconClsChange, titlechange: me.onItemTitleChange }); if (item.isPanel) { if (me.removePanelHeader) { if (item.rendered) { if (item.header) { item.header.hide(); } } else { item.header = false; } } if (item.isPanel && me.border) { item.setBorder(false); } } }, onItemEnable: function(item){ item.tab.enable(); }, onItemDisable: function(item){ item.tab.disable(); }, onItemBeforeShow: function(item) { if (item !== this.activeTab) { this.setActiveTab(item); return false; } }, onItemIconChange: function(item, newIcon) { item.tab.setIcon(newIcon); }, onItemIconClsChange: function(item, newIconCls) { item.tab.setIconCls(newIconCls); }, onItemTitleChange: function(item, newTitle) { item.tab.setText(newTitle); }, doRemove: function(item, autoDestroy) { var me = this, toActivate; if (me.destroying || me.items.getCount() == 1) { me.activeTab = null; } else if ((toActivate = me.tabBar.items.indexOf(me.tabBar.findNextActivatable(item.tab))) !== -1) { me.setActiveTab(toActivate); } this.callParent(arguments); delete item.tab.card; delete item.tab; }, onRemove: function(item, destroying) { var me = this; item.un({ scope : me, enable: me.onItemEnable, disable: me.onItemDisable, beforeshow: me.onItemBeforeShow }); if (!me.destroying && item.tab.ownerCt === me.tabBar) { me.tabBar.remove(item.tab); } } }); Ext.define('Ext.toolbar.Spacer', { extend: Ext.Component , alias: 'widget.tbspacer', alternateClassName: 'Ext.Toolbar.Spacer', baseCls: Ext.baseCSSPrefix + 'toolbar-spacer', focusable: false, ariaRole: 'presentation' }); Ext.define('Ext.tree.Panel', { extend: Ext.panel.Table , alias: 'widget.treepanel', alternateClassName: ['Ext.tree.TreePanel', 'Ext.TreePanel'], viewType: 'treeview', selType: 'treemodel', treeCls: Ext.baseCSSPrefix + 'tree-panel', deferRowRender: false, rowLines: false, lines: true, useArrows: false, singleExpand: false, ddConfig: { enableDrag: true, enableDrop: true }, rootVisible: true, displayField: 'text', root: null, normalCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible', 'scroll'], lockedCfgCopy: ['displayField', 'root', 'singleExpand', 'useArrows', 'lines', 'rootVisible'], isTree: true, arrowCls: Ext.baseCSSPrefix + 'tree-arrows', linesCls: Ext.baseCSSPrefix + 'tree-lines', noLinesCls: Ext.baseCSSPrefix + 'tree-no-lines', autoWidthCls: Ext.baseCSSPrefix + 'autowidth-table', constructor: function(config) { config = config || {}; if (config.animate === undefined) { config.animate = Ext.isBoolean(this.animate) ? this.animate : Ext.enableFx; } this.enableAnimations = config.animate; delete config.animate; this.callParent([config]); }, initComponent: function() { var me = this, cls = [me.treeCls], store = me.store, view; if (me.useArrows) { cls.push(me.arrowCls); me.lines = false; } if (me.lines) { cls.push(me.linesCls); } else if (!me.useArrows) { cls.push(me.noLinesCls); } if (Ext.isString(store)) { store = me.store = Ext.StoreMgr.lookup(store); } else if (!store || !store.isStore) { store = Ext.apply({ type: 'tree', root: me.root, fields: me.fields, model: me.model, folderSort: me.folderSort }, store); store = me.store = Ext.StoreMgr.lookup(store); } else if (me.root) { store = me.store = Ext.data.StoreManager.lookup(store); store.setRootNode(me.root); if (me.folderSort !== undefined) { store.folderSort = me.folderSort; store.sort(); } } me.viewConfig = Ext.apply({ rootVisible: me.rootVisible, animate: me.enableAnimations, singleExpand: me.singleExpand, node: store.getRootNode(), hideHeaders: me.hideHeaders }, me.viewConfig); if (!me.columns) { if (me.initialConfig.hideHeaders === undefined) { me.hideHeaders = true; } me.addCls(me.autoWidthCls); me.columns = [{ xtype : 'treecolumn', text : 'Name', width : Ext.isIE6 ? '100%' : 10000, dataIndex: me.displayField }]; } if (me.cls) { cls.push(me.cls); } me.cls = cls.join(' '); me.callParent(); me.selModel.treeStore = me.store; view = me.getView(); me.relayEvents(view, [ 'checkchange', 'afteritemexpand', 'afteritemcollapse' ]); if (!view.isLockingView) { if (!view.rootVisible && !me.getRootNode()) { me.setRootNode({ expanded: true }); } } }, bindStore: function(store, initial) { var me = this; me.store = store; me.storeListeners = me.mon(store, { destroyable: true, load: me.onStoreLoad, rootchange: me.onRootChange, clear: me.onClear, scope: me }); me.storeRelayers = me.relayEvents(store, [ 'beforeload', 'load' ]); me.storeRelayers1 = me.mon(store, { destroyable: true, append: me.createRelayer('itemappend'), remove: me.createRelayer('itemremove'), move: me.createRelayer('itemmove', [0, 4]), insert: me.createRelayer('iteminsert'), beforeappend: me.createRelayer('beforeitemappend'), beforeremove: me.createRelayer('beforeitemremove'), beforemove: me.createRelayer('beforeitemmove'), beforeinsert: me.createRelayer('beforeiteminsert'), expand: me.createRelayer('itemexpand', [0, 1]), collapse: me.createRelayer('itemcollapse', [0, 1]), beforeexpand: me.createRelayer('beforeitemexpand', [0, 1]), beforecollapse: me.createRelayer('beforeitemcollapse', [0, 1]) }); store.ownerTree = me; if (!initial) { me.view.setRootNode(me.getRootNode()); } }, unbindStore: function() { var me = this, store = me.store; if (store) { Ext.destroy(me.storeListeners, me.storeRelayers, me.storeRelayers1); delete store.ownerTree; } }, onClear: function(){ this.view.onClear(); }, setRootNode: function() { return this.store.setRootNode.apply(this.store, arguments); }, getRootNode: function() { return this.store.getRootNode(); }, onRootChange: function(root) { this.view.setRootNode(root); }, getChecked: function() { return this.getView().getChecked(); }, isItemChecked: function(rec) { return rec.get('checked'); }, expandNode: function(record, deep, callback, scope) { return this.getView().expand(record, deep, callback, scope || this); }, collapseNode: function(record, deep, callback, scope) { return this.getView().collapse(record, deep, callback, scope || this); }, expandAll : function(callback, scope) { var me = this, root = me.getRootNode(), animate = me.enableAnimations; if (root) { if (!animate) { Ext.suspendLayouts(); } root.expand(true, callback, scope || me); if (!animate) { Ext.resumeLayouts(true); } } }, collapseAll : function(callback, scope) { var me = this, root = me.getRootNode(), animate = me.enableAnimations, view = me.getView(); if (root) { if (!animate) { Ext.suspendLayouts(); } scope = scope || me; if (view.rootVisible) { root.collapse(true, callback, scope); } else { root.collapseChildren(true, callback, scope); } if (!animate) { Ext.resumeLayouts(true); } } }, expandPath: function(path, field, separator, callback, scope) { var me = this, current = me.getRootNode(), index = 1, view = me.getView(), keys, expander; field = field || me.getRootNode().idProperty; separator = separator || '/'; if (Ext.isEmpty(path)) { Ext.callback(callback, scope || me, [false, null]); return; } keys = path.split(separator); if (current.get(field) != keys[1]) { Ext.callback(callback, scope || me, [false, current]); return; } expander = function(){ if (++index === keys.length) { Ext.callback(callback, scope || me, [true, current]); return; } var node = current.findChild(field, keys[index]); if (!node) { Ext.callback(callback, scope || me, [false, current]); return; } current = node; current.expand(false, expander); }; current.expand(false, expander); }, selectPath: function(path, field, separator, callback, scope) { var me = this, root, keys, last; field = field || me.getRootNode().idProperty; separator = separator || '/'; keys = path.split(separator); last = keys.pop(); if (keys.length > 1) { me.expandPath(keys.join(separator), field, separator, function(success, node){ var lastNode = node; if (success && node) { node = node.findChild(field, last); if (node) { me.getSelectionModel().select(node); Ext.callback(callback, scope || me, [true, node]); return; } } Ext.callback(callback, scope || me, [false, lastNode]); }, me); } else { root = me.getRootNode(); if (root.getId() === last) { me.getSelectionModel().select(root); Ext.callback(callback, scope || me, [true, root]); } else { Ext.callback(callback, scope || me, [false, null]); } } } }); Ext.define('Ext.view.DragZone', { extend: Ext.dd.DragZone , containerScroll: false, constructor: function(config) { var me = this, view, ownerCt, el; Ext.apply(me, config); if (!me.ddGroup) { me.ddGroup = 'view-dd-zone-' + me.view.id; } view = me.view; ownerCt = view.ownerCt; if (ownerCt) { el = ownerCt.getTargetEl().dom; } else { el = view.el.dom.parentNode; } me.callParent([el]); me.ddel = Ext.get(document.createElement('div')); me.ddel.addCls(Ext.baseCSSPrefix + 'grid-dd-wrap'); }, init: function(id, sGroup, config) { var me = this; me.initTarget(id, sGroup, config); me.view.on('itemmousedown', me.onItemMouseDown, me); }, onValidDrop: function(target, e, id) { this.callParent(); target.el.focus(); }, onItemMouseDown: function(view, record, item, index, e) { if (!this.isPreventDrag(e, record, item, index)) { if (view.focusRow) { view.focusRow(record); } this.handleMouseDown(e); } }, isPreventDrag: function(e) { return false; }, getDragData: function(e) { var view = this.view, item = e.getTarget(view.getItemSelector()); if (item) { return { copy: view.copy || (view.allowCopy && e.ctrlKey), event: new Ext.EventObjectImpl(e), view: view, ddel: this.ddel, item: item, records: view.getSelectionModel().getSelection(), fromPosition: Ext.fly(item).getXY() }; } }, onInitDrag: function(x, y) { var me = this, data = me.dragData, view = data.view, selectionModel = view.getSelectionModel(), record = view.getRecord(data.item); if (!selectionModel.isSelected(record)) { selectionModel.selectWithEvent(record, me.DDMInstance.mousedownEvent); } data.records = selectionModel.getSelection(); me.ddel.update(me.getDragText()); me.proxy.update(me.ddel.dom); me.onStartDrag(x, y); return true; }, getDragText: function() { var count = this.dragData.records.length; return Ext.String.format(this.dragText, count, count == 1 ? '' : 's'); }, getRepairXY : function(e, data){ return data ? data.fromPosition : false; } }); Ext.define('Ext.tree.ViewDragZone', { extend: Ext.view.DragZone , isPreventDrag: function(e, record) { return (record.get('allowDrag') === false) || !!e.getTarget(this.view.expanderSelector); }, getDragText: function() { var records = this.dragData.records, count = records.length, text = records[0].get(this.displayField), suffix = 's'; if (count === 1 && text) { return text; } else if (!text) { suffix = ''; } return Ext.String.format(this.dragText, count, suffix); }, afterRepair: function() { var me = this, view = me.view, selectedRowCls = view.selectedItemCls, records = me.dragData.records, r, rLen = records.length, fly = Ext.fly, item; if (Ext.enableFx && me.repairHighlight) { for (r = 0; r < rLen; r++) { item = view.getNode(records[r]); fly(item.firstChild).highlight(me.repairHighlightColor, { listeners: { beforeanimate: function() { if (view.isSelected(item)) { fly(item).removeCls(selectedRowCls); } }, afteranimate: function() { if (view.isSelected(item)) { fly(item).addCls(selectedRowCls); } } } }); } } me.dragging = false; } }); Ext.define('Ext.tree.ViewDropZone', { extend: Ext.view.DropZone , allowParentInserts: false, allowContainerDrops: false, appendOnly: false, expandDelay : 500, indicatorCls: Ext.baseCSSPrefix + 'tree-ddindicator', expandNode : function(node) { var view = this.view; this.expandProcId = false; if (!node.isLeaf() && !node.isExpanded()) { view.expand(node); this.expandProcId = false; } }, queueExpand : function(node) { this.expandProcId = Ext.Function.defer(this.expandNode, this.expandDelay, this, [node]); }, cancelExpand : function() { if (this.expandProcId) { clearTimeout(this.expandProcId); this.expandProcId = false; } }, getPosition: function(e, node) { var view = this.view, record = view.getRecord(node), y = e.getPageY(), noAppend = record.isLeaf(), noBelow = false, region = Ext.fly(node).getRegion(), fragment; if (record.isRoot()) { return 'append'; } if (this.appendOnly) { return noAppend ? false : 'append'; } if (!this.allowParentInserts) { noBelow = record.hasChildNodes() && record.isExpanded(); } fragment = (region.bottom - region.top) / (noAppend ? 2 : 3); if (y >= region.top && y < (region.top + fragment)) { return 'before'; } else if (!noBelow && (noAppend || (y >= (region.bottom - fragment) && y <= region.bottom))) { return 'after'; } else { return 'append'; } }, isValidDropPoint : function(node, position, dragZone, e, data) { if (!node || !data.item) { return false; } var view = this.view, targetNode = view.getRecord(node), draggedRecords = data.records, dataLength = draggedRecords.length, ln = draggedRecords.length, i, record; if (!(targetNode && position && dataLength)) { return false; } for (i = 0; i < ln; i++) { record = draggedRecords[i]; if (record.isNode && record.contains(targetNode)) { return false; } } if (position === 'append' && targetNode.get('allowDrop') === false) { return false; } else if (position != 'append' && targetNode.parentNode.get('allowDrop') === false) { return false; } if (Ext.Array.contains(draggedRecords, targetNode)) { return false; } return view.fireEvent('nodedragover', targetNode, position, data, e) !== false; }, onNodeOver : function(node, dragZone, e, data) { var position = this.getPosition(e, node), returnCls = this.dropNotAllowed, view = this.view, targetNode = view.getRecord(node), indicator = this.getIndicator(), indicatorY = 0; this.cancelExpand(); if (position == 'append' && !this.expandProcId && !Ext.Array.contains(data.records, targetNode) && !targetNode.isLeaf() && !targetNode.isExpanded()) { this.queueExpand(targetNode); } if (this.isValidDropPoint(node, position, dragZone, e, data)) { this.valid = true; this.currentPosition = position; this.overRecord = targetNode; indicator.setWidth(Ext.fly(node).getWidth()); indicatorY = Ext.fly(node).getY() - Ext.fly(view.el).getY() - 1; if (position == 'before') { returnCls = targetNode.isFirst() ? Ext.baseCSSPrefix + 'tree-drop-ok-above' : Ext.baseCSSPrefix + 'tree-drop-ok-between'; indicator.showAt(0, indicatorY); dragZone.proxy.show(); } else if (position == 'after') { returnCls = targetNode.isLast() ? Ext.baseCSSPrefix + 'tree-drop-ok-below' : Ext.baseCSSPrefix + 'tree-drop-ok-between'; indicatorY += Ext.fly(node).getHeight(); indicator.showAt(0, indicatorY); dragZone.proxy.show(); } else { returnCls = Ext.baseCSSPrefix + 'tree-drop-ok-append'; indicator.hide(); } } else { this.valid = false; } this.currentCls = returnCls; return returnCls; }, onNodeOut : function(n, dd, e, data){ this.valid = false; this.getIndicator().hide(); }, onContainerOver : function(dd, e, data) { return e.getTarget('.' + this.indicatorCls) ? this.currentCls : this.dropNotAllowed; }, notifyOut: function() { this.callParent(arguments); this.cancelExpand(); }, handleNodeDrop : function(data, targetNode, position) { var me = this, targetView = me.view, parentNode = targetNode ? targetNode.parentNode : targetView.panel.getRootNode(), Model = targetView.getStore().treeStore.model, records, i, len, record, insertionMethod, argList, needTargetExpand, transferData; if (data.copy) { records = data.records; data.records = []; for (i = 0, len = records.length; i < len; i++) { record = records[i]; if (record.isNode) { data.records.push(record.copy(undefined, true)); } else { data.records.push(new Model(record.data, record.getId())); } } } me.cancelExpand(); if (position == 'before') { insertionMethod = parentNode.insertBefore; argList = [null, targetNode]; targetNode = parentNode; } else if (position == 'after') { if (targetNode.nextSibling) { insertionMethod = parentNode.insertBefore; argList = [null, targetNode.nextSibling]; } else { insertionMethod = parentNode.appendChild; argList = [null]; } targetNode = parentNode; } else { if (!(targetNode.isExpanded() || targetNode.isLoading())) { needTargetExpand = true; } insertionMethod = targetNode.appendChild; argList = [null]; } transferData = function() { var color, n; Ext.suspendLayouts(); for (i = 0, len = data.records.length; i < len; i++) { record = data.records[i]; if (!record.isNode) { if (record.isModel) { record = new Model(record.data, record.getId()); } else { record = new Model(record); } data.records[i] = record; } argList[0] = record; insertionMethod.apply(targetNode, argList); } if (me.sortOnDrop) { targetNode.sort(targetNode.getOwnerTree().store.generateComparator()); } Ext.resumeLayouts(true); if (Ext.enableFx && me.dropHighlight) { color = me.dropHighlightColor; for (i = 0; i < len; i++) { n = targetView.getNode(data.records[i]); if (n) { Ext.fly(n).highlight(color); } } } }; if (needTargetExpand) { targetNode.expand(false, transferData); } else if (targetNode.isLoading()) { targetNode.on({ expand: transferData, delay: 1, single: true }); } else { transferData(); } } }); Ext.define('Ext.tree.plugin.TreeViewDragDrop', { extend: Ext.AbstractPlugin , alias: 'plugin.treeviewdragdrop', dragText : '{0} selected node{1}', allowParentInserts: false, allowContainerDrops: false, appendOnly: false, ddGroup : "TreeDD", containerScroll: false, expandDelay : 1000, enableDrop: true, enableDrag: true, nodeHighlightColor: 'c3daf9', nodeHighlightOnDrop: Ext.enableFx, nodeHighlightOnRepair: Ext.enableFx, displayField: 'text', init : function(view) { view.on('render', this.onViewRender, this, {single: true}); }, destroy: function() { Ext.destroy(this.dragZone, this.dropZone); }, onViewRender : function(view) { var me = this, scrollEl; if (me.enableDrag) { if (me.containerScroll) { scrollEl = view.getEl(); } me.dragZone = new Ext.tree.ViewDragZone({ view: view, ddGroup: me.dragGroup || me.ddGroup, dragText: me.dragText, displayField: me.displayField, repairHighlightColor: me.nodeHighlightColor, repairHighlight: me.nodeHighlightOnRepair, scrollEl: scrollEl }); } if (me.enableDrop) { me.dropZone = new Ext.tree.ViewDropZone({ view: view, ddGroup: me.dropGroup || me.ddGroup, allowContainerDrops: me.allowContainerDrops, appendOnly: me.appendOnly, allowParentInserts: me.allowParentInserts, expandDelay: me.expandDelay, dropHighlightColor: me.nodeHighlightColor, dropHighlight: me.nodeHighlightOnDrop, sortOnDrop: me.sortOnDrop, containerScroll: me.containerScroll }); } } }, function(){ var proto = this.prototype; proto.nodeHighlightOnDrop = proto.nodeHighlightOnRepair = Ext.enableFx; }); Ext.define('Ext.util.Cookies', { singleton: true, set : function(name, value){ var argv = arguments, argc = arguments.length, expires = (argc > 2) ? argv[2] : null, path = (argc > 3) ? argv[3] : '/', domain = (argc > 4) ? argv[4] : null, secure = (argc > 5) ? argv[5] : false; document.cookie = name + "=" + escape(value) + ((expires === null) ? "" : ("; expires=" + expires.toGMTString())) + ((path === null) ? "" : ("; path=" + path)) + ((domain === null) ? "" : ("; domain=" + domain)) + ((secure === true) ? "; secure" : ""); }, get : function(name){ var arg = name + "=", alen = arg.length, clen = document.cookie.length, i = 0, j = 0; while(i < clen){ j = i + alen; if(document.cookie.substring(i, j) == arg){ return this.getCookieVal(j); } i = document.cookie.indexOf(" ", i) + 1; if(i === 0){ break; } } return null; }, clear : function(name, path){ if(this.get(name)){ path = path || '/'; document.cookie = name + '=' + '; expires=Thu, 01-Jan-70 00:00:01 GMT; path=' + path; } }, getCookieVal : function(offset){ var endstr = document.cookie.indexOf(";", offset); if(endstr == -1){ endstr = document.cookie.length; } return unescape(document.cookie.substring(offset, endstr)); } }); Ext.define('Ext.util.Grouper', { extend: Ext.util.Sorter , isGrouper: true, getGroupString: function(instance) { return instance.get(this.property); } }); Ext.define('Ext.util.History', { singleton: true, alternateClassName: 'Ext.History', mixins: { observable: Ext.util.Observable }, useTopWindow: true, fieldId: Ext.baseCSSPrefix + 'history-field', iframeId: Ext.baseCSSPrefix + 'history-frame', constructor: function() { var me = this; me.oldIEMode = Ext.isIE7m || !Ext.isStrict && Ext.isIE8; me.iframe = null; me.hiddenField = null; me.ready = false; me.currentToken = null; me.mixins.observable.constructor.call(me); }, getHash: function() { var href = window.location.href, i = href.indexOf("#"); return i >= 0 ? href.substr(i + 1) : null; }, setHash: function (hash) { var me = this, win = me.useTopWindow ? window.top : window; try { win.location.hash = hash; } catch (e) { } }, doSave: function() { this.hiddenField.value = this.currentToken; }, handleStateChange: function(token) { this.currentToken = token; this.fireEvent('change', token); }, updateIFrame: function(token) { var html = '', doc; try { doc = this.iframe.contentWindow.document; doc.open(); doc.write(html); doc.close(); return true; } catch (e) { return false; } }, checkIFrame: function () { var me = this, contentWindow = me.iframe.contentWindow, doc, elem, oldToken, oldHash; if (!contentWindow || !contentWindow.document) { Ext.Function.defer(this.checkIFrame, 10, this); return; } doc = contentWindow.document; elem = doc.getElementById("state"); oldToken = elem ? elem.innerText : null; oldHash = me.getHash(); Ext.TaskManager.start({ run: function () { var doc = contentWindow.document, elem = doc.getElementById("state"), newToken = elem ? elem.innerText : null, newHash = me.getHash(); if (newToken !== oldToken) { oldToken = newToken; me.handleStateChange(newToken); me.setHash(newToken); oldHash = newToken; me.doSave(); } else if (newHash !== oldHash) { oldHash = newHash; me.updateIFrame(newHash); } }, interval: 50, scope: me }); me.ready = true; me.fireEvent('ready', me); }, startUp: function () { var me = this, hash; me.currentToken = me.hiddenField.value || this.getHash(); if (me.oldIEMode) { me.checkIFrame(); } else { hash = me.getHash(); Ext.TaskManager.start({ run: function () { var newHash = me.getHash(); if (newHash !== hash) { hash = newHash; me.handleStateChange(hash); me.doSave(); } }, interval: 50, scope: me }); me.ready = true; me.fireEvent('ready', me); } }, init: function (onReady, scope) { var me = this, DomHelper = Ext.DomHelper; if (me.ready) { Ext.callback(onReady, scope, [me]); return; } if (!Ext.isReady) { Ext.onReady(function() { me.init(onReady, scope); }); return; } me.hiddenField = Ext.getDom(me.fieldId); if (!me.hiddenField) { me.hiddenField = Ext.getBody().createChild({ id: Ext.id(), tag: 'form', role: 'presentation', cls: Ext.baseCSSPrefix + 'hide-display', children: [{ tag: 'input', type: 'hidden', id: me.fieldId }] }, false, true).firstChild; } if (me.oldIEMode) { me.iframe = Ext.getDom(me.iframeId); if (!me.iframe) { me.iframe = DomHelper.append(me.hiddenField.parentNode, { tag: 'iframe', role: 'presentation', id: me.iframeId, src: Ext.SSL_SECURE_URL }); } } me.addEvents( 'ready', 'change' ); if (onReady) { me.on('ready', onReady, scope, {single: true}); } me.startUp(); }, add: function (token, preventDup) { var me = this; if (preventDup !== false) { if (me.getToken() === token) { return true; } } if (me.oldIEMode) { return me.updateIFrame(token); } else { me.setHash(token); return true; } }, back: function() { window.history.go(-1); }, forward: function(){ window.history.go(1); }, getToken: function() { return this.ready ? this.currentToken : this.getHash(); } });




    © 2015 - 2024 Weber Informatics LLC | Privacy Policy