93094 lines
2.3 MiB
93094 lines
2.3 MiB
/*
|
|
|
|
This file is part of Ext JS 4
|
|
|
|
Copyright (c) 2011 Sencha Inc
|
|
|
|
Contact: http://www.sencha.com/contact
|
|
|
|
GNU General Public License Usage
|
|
This file may be used under the terms of the GNU General Public License version 3.0 as published by the Free Software Foundation and appearing in the file LICENSE included in the packaging of this file. Please review the following information to ensure the GNU General Public License version 3.0 requirements will be met: http://www.gnu.org/copyleft/gpl.html.
|
|
|
|
If you are unsure which license is appropriate for your use, please contact the sales department at http://www.sencha.com/contact.
|
|
|
|
*/
|
|
|
|
|
|
(function() {
|
|
var global = this,
|
|
objectPrototype = Object.prototype,
|
|
toString = objectPrototype.toString,
|
|
enumerables = true,
|
|
enumerablesTest = { toString: 1 },
|
|
i;
|
|
|
|
if (typeof Ext === 'undefined') {
|
|
global.Ext = {};
|
|
}
|
|
|
|
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-',
|
|
scopeResetCSS: false
|
|
}, Ext.buildSettings || {});
|
|
|
|
Ext.apply(Ext, {
|
|
|
|
emptyFn: function() {},
|
|
|
|
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(cls, overrides) {
|
|
if (cls.prototype.$className) {
|
|
return cls.override(overrides);
|
|
}
|
|
else {
|
|
Ext.apply(cls.prototype, overrides);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.apply(Ext, {
|
|
|
|
|
|
valueFrom: function(value, defaultValue, allowBlank){
|
|
return Ext.isEmpty(value, allowBlank) ? defaultValue : value;
|
|
},
|
|
|
|
|
|
typeOf: function(value) {
|
|
if (value === null) {
|
|
return 'null';
|
|
}
|
|
|
|
var type = typeof value;
|
|
|
|
if (type === 'undefined' || type === 'string' || type === 'number' || type === 'boolean') {
|
|
return type;
|
|
}
|
|
|
|
var 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 (/\S/).test(value.nodeValue) ? 'textnode' : 'whitespace';
|
|
}
|
|
else {
|
|
return 'element';
|
|
}
|
|
}
|
|
|
|
return 'object';
|
|
}
|
|
|
|
},
|
|
|
|
|
|
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]';
|
|
},
|
|
|
|
|
|
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 toString.call(value) === '[object Function]';
|
|
} : function(value) {
|
|
return 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) {
|
|
return (value && typeof value !== 'string') ? value.length !== undefined : false;
|
|
}
|
|
});
|
|
|
|
Ext.apply(Ext, {
|
|
|
|
|
|
clone: function(item) {
|
|
if (item === null || item === undefined) {
|
|
return item;
|
|
}
|
|
|
|
|
|
|
|
|
|
if (item.nodeType && item.cloneNode) {
|
|
return item.cloneNode(true);
|
|
}
|
|
|
|
var type = toString.call(item);
|
|
|
|
|
|
if (type === '[object Date]') {
|
|
return new Date(item.getTime());
|
|
}
|
|
|
|
var i, j, k, clone, key;
|
|
|
|
|
|
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];
|
|
clone[k] = item[k];
|
|
}
|
|
}
|
|
}
|
|
|
|
return clone || item;
|
|
},
|
|
|
|
|
|
getUniqueGlobalNamespace: function() {
|
|
var uniqueGlobalNamespace = this.uniqueGlobalNamespace;
|
|
|
|
if (uniqueGlobalNamespace === undefined) {
|
|
var i = 0;
|
|
|
|
do {
|
|
uniqueGlobalNamespace = 'ExtBox' + (++i);
|
|
} while (Ext.global[uniqueGlobalNamespace] !== undefined);
|
|
|
|
Ext.global[uniqueGlobalNamespace] = Ext;
|
|
this.uniqueGlobalNamespace = uniqueGlobalNamespace;
|
|
}
|
|
|
|
return uniqueGlobalNamespace;
|
|
},
|
|
|
|
|
|
functionFactory: function() {
|
|
var args = Array.prototype.slice.call(arguments);
|
|
|
|
if (args.length > 0) {
|
|
args[args.length - 1] = 'var Ext=window.' + this.getUniqueGlobalNamespace() + ';' +
|
|
args[args.length - 1];
|
|
}
|
|
|
|
return Function.prototype.constructor.apply(Function.prototype, args);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.type = Ext.typeOf;
|
|
|
|
})();
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
var version = '4.0.7', Version;
|
|
Ext.Version = Version = Ext.extend(Object, {
|
|
|
|
|
|
constructor: function(version) {
|
|
var parts, releaseStartIndex;
|
|
|
|
if (version instanceof Version) {
|
|
return version;
|
|
}
|
|
|
|
this.version = this.shortVersion = String(version).toLowerCase().replace(/_/g, '.').replace(/[\-+]/g, '');
|
|
|
|
releaseStartIndex = this.version.search(/([^\d\.])/);
|
|
|
|
if (releaseStartIndex !== -1) {
|
|
this.release = this.version.substr(releaseStartIndex, version.length);
|
|
this.shortVersion = this.version.substr(0, releaseStartIndex);
|
|
}
|
|
|
|
this.shortVersion = this.shortVersion.replace(/[^\d]/g, '');
|
|
|
|
parts = this.version.split('.');
|
|
|
|
this.major = parseInt(parts.shift() || 0, 10);
|
|
this.minor = parseInt(parts.shift() || 0, 10);
|
|
this.patch = parseInt(parts.shift() || 0, 10);
|
|
this.build = parseInt(parts.shift() || 0, 10);
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
toString: function() {
|
|
return this.version;
|
|
},
|
|
|
|
|
|
valueOf: function() {
|
|
return this.version;
|
|
},
|
|
|
|
|
|
getMajor: function() {
|
|
return this.major || 0;
|
|
},
|
|
|
|
|
|
getMinor: function() {
|
|
return this.minor || 0;
|
|
},
|
|
|
|
|
|
getPatch: function() {
|
|
return this.patch || 0;
|
|
},
|
|
|
|
|
|
getBuild: function() {
|
|
return this.build || 0;
|
|
},
|
|
|
|
|
|
getRelease: function() {
|
|
return this.release || '';
|
|
},
|
|
|
|
|
|
isGreaterThan: function(target) {
|
|
return Version.compare(this.version, target) === 1;
|
|
},
|
|
|
|
|
|
isLessThan: function(target) {
|
|
return Version.compare(this.version, target) === -1;
|
|
},
|
|
|
|
|
|
equals: function(target) {
|
|
return Version.compare(this.version, target) === 0;
|
|
},
|
|
|
|
|
|
match: function(target) {
|
|
target = String(target);
|
|
return this.version.substr(0, target.length) === target;
|
|
},
|
|
|
|
|
|
toArray: function() {
|
|
return [this.getMajor(), this.getMinor(), this.getPatch(), this.getBuild(), this.getRelease()];
|
|
},
|
|
|
|
|
|
getShortVersion: function() {
|
|
return this.shortVersion;
|
|
}
|
|
});
|
|
|
|
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 currentValue, targetValue, i;
|
|
|
|
current = new Version(current).toArray();
|
|
target = new Version(target).toArray();
|
|
|
|
for (i = 0; i < Math.max(current.length, target.length); i++) {
|
|
currentValue = this.getComponentValue(current[i]);
|
|
targetValue = this.getComponentValue(target[i]);
|
|
|
|
if (currentValue < targetValue) {
|
|
return -1;
|
|
} else if (currentValue > targetValue) {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
});
|
|
|
|
Ext.apply(Ext, {
|
|
|
|
versions: {},
|
|
|
|
|
|
lastRegisteredVersion: null,
|
|
|
|
|
|
setVersion: function(packageName, version) {
|
|
Ext.versions[packageName] = new Version(version);
|
|
Ext.lastRegisteredVersion = Ext.versions[packageName];
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
getVersion: function(packageName) {
|
|
if (packageName === undefined) {
|
|
return Ext.lastRegisteredVersion;
|
|
}
|
|
|
|
return Ext.versions[packageName];
|
|
},
|
|
|
|
|
|
deprecate: function(packageName, since, closure, scope) {
|
|
if (Version.compare(Ext.getVersion(packageName), since) < 1) {
|
|
closure.call(scope);
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.setVersion('core', version);
|
|
|
|
})();
|
|
|
|
|
|
|
|
Ext.String = {
|
|
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,
|
|
|
|
/**
|
|
* Convert certain characters (&, <, >, and ") to their HTML character equivalents for literal display in web pages.
|
|
* @param {String} value The string to encode
|
|
* @return {String} The encoded text
|
|
* @method
|
|
*/
|
|
htmlEncode: (function() {
|
|
var entities = {
|
|
'&': '&',
|
|
'>': '>',
|
|
'<': '<',
|
|
'"': '"'
|
|
}, keys = [], p, regex;
|
|
|
|
for (p in entities) {
|
|
keys.push(p);
|
|
}
|
|
|
|
regex = new RegExp('(' + keys.join('|') + ')', 'g');
|
|
|
|
return function(value) {
|
|
return (!value) ? value : String(value).replace(regex, function(match, capture) {
|
|
return entities[capture];
|
|
});
|
|
};
|
|
})(),
|
|
|
|
/**
|
|
* Convert certain characters (&, <, >, and ") from their HTML character equivalents.
|
|
* @param {String} value The string to decode
|
|
* @return {String} The decoded text
|
|
* @method
|
|
*/
|
|
htmlDecode: (function() {
|
|
var entities = {
|
|
'&': '&',
|
|
'>': '>',
|
|
'<': '<',
|
|
'"': '"'
|
|
}, keys = [], p, regex;
|
|
|
|
for (p in entities) {
|
|
keys.push(p);
|
|
}
|
|
|
|
regex = new RegExp('(' + keys.join('|') + '|&#[0-9]{1,5};' + ')', 'g');
|
|
|
|
return function(value) {
|
|
return (!value) ? value : String(value).replace(regex, function(match, capture) {
|
|
if (capture in entities) {
|
|
return entities[capture];
|
|
} else {
|
|
return String.fromCharCode(parseInt(capture.substr(2), 10));
|
|
}
|
|
});
|
|
};
|
|
})(),
|
|
|
|
|
|
urlAppend : function(url, string) {
|
|
if (!Ext.isEmpty(string)) {
|
|
return url + (url.indexOf('?') === -1 ? '?' : '&') + string;
|
|
}
|
|
|
|
return url;
|
|
},
|
|
|
|
|
|
trim: function(string) {
|
|
return string.replace(Ext.String.trimRegex, "");
|
|
},
|
|
|
|
|
|
capitalize: function(string) {
|
|
return string.charAt(0).toUpperCase() + 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(Ext.String.escapeRegexRe, "\\$1");
|
|
},
|
|
|
|
|
|
escape: function(string) {
|
|
return string.replace(Ext.String.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(Ext.String.formatRe, function(m, i) {
|
|
return args[i];
|
|
});
|
|
},
|
|
|
|
|
|
repeat: function(pattern, count, sep) {
|
|
for (var buf = [], i = count; i--; ) {
|
|
buf.push(pattern);
|
|
}
|
|
return buf.join(sep || '');
|
|
}
|
|
};
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
var isToFixedBroken = (0.9).toFixed() !== '1';
|
|
|
|
Ext.Number = {
|
|
|
|
constrain: function(number, min, max) {
|
|
number = parseFloat(number);
|
|
|
|
if (!isNaN(min)) {
|
|
number = Math.max(number, min);
|
|
}
|
|
if (!isNaN(max)) {
|
|
number = Math.min(number, max);
|
|
}
|
|
return number;
|
|
},
|
|
|
|
|
|
snap : function(value, increment, minValue, maxValue) {
|
|
var newValue = value,
|
|
m;
|
|
|
|
if (!(increment && value)) {
|
|
return value;
|
|
}
|
|
m = value % increment;
|
|
if (m !== 0) {
|
|
newValue -= m;
|
|
if (m * 2 >= increment) {
|
|
newValue += increment;
|
|
} else if (m * 2 < -increment) {
|
|
newValue -= increment;
|
|
}
|
|
}
|
|
return Ext.Number.constrain(newValue, minValue, maxValue);
|
|
},
|
|
|
|
|
|
toFixed: function(value, precision) {
|
|
if (isToFixedBroken) {
|
|
precision = precision || 0;
|
|
var pow = Math.pow(10, precision);
|
|
return (Math.round(value * pow) / pow).toFixed(precision);
|
|
}
|
|
|
|
return value.toFixed(precision);
|
|
},
|
|
|
|
|
|
from: function(value, defaultValue) {
|
|
if (isFinite(value)) {
|
|
value = parseFloat(value);
|
|
}
|
|
|
|
return !isNaN(value) ? value : defaultValue;
|
|
}
|
|
};
|
|
|
|
})();
|
|
|
|
|
|
Ext.num = function() {
|
|
return Ext.Number.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;
|
|
|
|
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);
|
|
|
|
|
|
if (pos === length) {
|
|
if (add) {
|
|
array.push.apply(array, insert);
|
|
}
|
|
} else {
|
|
var remove = Math.min(removeCount, length - pos),
|
|
tailOldPos = pos + remove,
|
|
tailNewPos = tailOldPos + add - remove,
|
|
tailCount = length - tailOldPos,
|
|
lengthAfterRemove = length - remove,
|
|
i;
|
|
|
|
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 < 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));
|
|
}
|
|
|
|
var 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: function(array, fn, scope) {
|
|
if (supportsForEach) {
|
|
return array.forEach(fn, scope);
|
|
}
|
|
|
|
var i = 0,
|
|
ln = array.length;
|
|
|
|
for (; i < ln; i++) {
|
|
fn.call(scope, array[i], i, array);
|
|
}
|
|
},
|
|
|
|
|
|
indexOf: function(array, item, from) {
|
|
if (supportsIndexOf) {
|
|
return array.indexOf(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: function(array, item) {
|
|
if (supportsIndexOf) {
|
|
return array.indexOf(item) !== -1;
|
|
}
|
|
|
|
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: function(array, fn, scope) {
|
|
if (supportsMap) {
|
|
return array.map(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: function(array, fn, scope) {
|
|
if (supportsEvery) {
|
|
return array.every(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: function(array, fn, scope) {
|
|
if (supportsSome) {
|
|
return array.some(fn, scope);
|
|
}
|
|
|
|
var i = 0,
|
|
ln = array.length;
|
|
|
|
for (; i < ln; ++i) {
|
|
if (fn.call(scope, array[i], i, array)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
|
|
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: function(array, fn, scope) {
|
|
if (supportsFilter) {
|
|
return array.filter(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;
|
|
},
|
|
|
|
|
|
from: function(value, newReference) {
|
|
if (value === undefined || value === null) {
|
|
return [];
|
|
}
|
|
|
|
if (Ext.isArray(value)) {
|
|
return (newReference) ? slice.call(value) : value;
|
|
}
|
|
|
|
if (value && value.length !== undefined && typeof value !== 'string') {
|
|
return Ext.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 intersect = [],
|
|
arrays = slice.call(arguments),
|
|
i, j, k, minArray, array, x, y, ln, arraysLn, arrayLn;
|
|
|
|
if (!arrays.length) {
|
|
return intersect;
|
|
}
|
|
|
|
|
|
for (i = x = 0,ln = arrays.length; i < ln,array = arrays[i]; i++) {
|
|
if (!minArray || array.length < minArray.length) {
|
|
minArray = array;
|
|
x = i;
|
|
}
|
|
}
|
|
|
|
minArray = ExtArray.unique(minArray);
|
|
erase(arrays, x, 1);
|
|
|
|
|
|
|
|
|
|
for (i = 0,ln = minArray.length; i < ln,x = minArray[i]; i++) {
|
|
var count = 0;
|
|
|
|
for (j = 0,arraysLn = arrays.length; j < arraysLn,array = arrays[j]; j++) {
|
|
for (k = 0,arrayLn = array.length; k < arrayLn,y = array[k]; k++) {
|
|
if (x === y) {
|
|
count++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (count === arraysLn) {
|
|
intersect.push(x);
|
|
}
|
|
}
|
|
|
|
return intersect;
|
|
},
|
|
|
|
|
|
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: function(array, sortFn) {
|
|
if (supportsSort) {
|
|
if (sortFn) {
|
|
return array.sort(sortFn);
|
|
} else {
|
|
return array.sort();
|
|
}
|
|
}
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
|
|
erase: erase,
|
|
|
|
|
|
insert: function (array, index, items) {
|
|
return replace(array, index, 0, items);
|
|
},
|
|
|
|
|
|
replace: replace,
|
|
|
|
|
|
splice: splice
|
|
};
|
|
|
|
|
|
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 || window, callArgs);
|
|
};
|
|
},
|
|
|
|
|
|
pass: function(fn, args, scope) {
|
|
if (args) {
|
|
args = Ext.Array.from(args);
|
|
}
|
|
|
|
return function() {
|
|
return fn.apply(scope, args.concat(Ext.Array.toArray(arguments)));
|
|
};
|
|
},
|
|
|
|
|
|
alias: function(object, methodName) {
|
|
return function() {
|
|
return object[methodName].apply(object, arguments);
|
|
};
|
|
},
|
|
|
|
|
|
createInterceptor: function(origFn, newFn, scope, returnValue) {
|
|
var method = origFn;
|
|
if (!Ext.isFunction(newFn)) {
|
|
return origFn;
|
|
}
|
|
else {
|
|
return function() {
|
|
var me = this,
|
|
args = arguments;
|
|
newFn.target = me;
|
|
newFn.method = origFn;
|
|
return (newFn.apply(scope || me || window, args) !== false) ? origFn.apply(me || window, args) : returnValue || null;
|
|
};
|
|
}
|
|
},
|
|
|
|
|
|
createDelayed: function(fn, delay, scope, args, appendArgs) {
|
|
if (scope || args) {
|
|
fn = Ext.Function.bind(fn, scope, args, appendArgs);
|
|
}
|
|
return function() {
|
|
var me = this;
|
|
setTimeout(function() {
|
|
fn.apply(me, arguments);
|
|
}, delay);
|
|
};
|
|
},
|
|
|
|
|
|
defer: function(fn, millis, obj, args, appendArgs) {
|
|
fn = Ext.Function.bind(fn, obj, args, appendArgs);
|
|
if (millis > 0) {
|
|
return setTimeout(fn, millis);
|
|
}
|
|
fn();
|
|
return 0;
|
|
},
|
|
|
|
|
|
createSequence: function(origFn, newFn, scope) {
|
|
if (!Ext.isFunction(newFn)) {
|
|
return origFn;
|
|
}
|
|
else {
|
|
return function() {
|
|
var retval = origFn.apply(this || window, arguments);
|
|
newFn.apply(scope || this || window, arguments);
|
|
return retval;
|
|
};
|
|
}
|
|
},
|
|
|
|
|
|
createBuffered: function(fn, buffer, scope, args) {
|
|
return function(){
|
|
var timerId;
|
|
return function() {
|
|
var me = this;
|
|
if (timerId) {
|
|
clearTimeout(timerId);
|
|
timerId = null;
|
|
}
|
|
timerId = setTimeout(function(){
|
|
fn.apply(scope || me, args || arguments);
|
|
}, buffer);
|
|
};
|
|
}();
|
|
},
|
|
|
|
|
|
createThrottled: function(fn, interval, scope) {
|
|
var lastCallTime, elapsed, lastArgs, timer, execute = function() {
|
|
fn.apply(scope || this, lastArgs);
|
|
lastCallTime = new Date().getTime();
|
|
};
|
|
|
|
return function() {
|
|
elapsed = new Date().getTime() - lastCallTime;
|
|
lastArgs = arguments;
|
|
|
|
clearTimeout(timer);
|
|
if (!lastCallTime || (elapsed >= interval)) {
|
|
execute();
|
|
} else {
|
|
timer = setTimeout(execute, interval - elapsed);
|
|
}
|
|
};
|
|
},
|
|
|
|
|
|
interceptBefore: function(object, methodName, fn) {
|
|
var method = object[methodName] || Ext.emptyFn;
|
|
|
|
return object[methodName] = function() {
|
|
var ret = fn.apply(this, arguments);
|
|
method.apply(this, arguments);
|
|
|
|
return ret;
|
|
};
|
|
},
|
|
|
|
|
|
interceptAfter: function(object, methodName, fn) {
|
|
var method = object[methodName] || Ext.emptyFn;
|
|
|
|
return object[methodName] = function() {
|
|
method.apply(this, arguments);
|
|
return fn.apply(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 ExtObject = Ext.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(source, key, value) {
|
|
if (typeof key === 'string') {
|
|
if (value && value.constructor === Object) {
|
|
if (source[key] && source[key].constructor === Object) {
|
|
ExtObject.merge(source[key], value);
|
|
}
|
|
else {
|
|
source[key] = Ext.clone(value);
|
|
}
|
|
}
|
|
else {
|
|
source[key] = value;
|
|
}
|
|
|
|
return source;
|
|
}
|
|
|
|
var i = 1,
|
|
ln = arguments.length,
|
|
object, property;
|
|
|
|
for (; i < ln; i++) {
|
|
object = arguments[i];
|
|
|
|
for (property in object) {
|
|
if (object.hasOwnProperty(property)) {
|
|
ExtObject.merge(source, property, object[property]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return source;
|
|
},
|
|
|
|
|
|
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: ('keys' in Object.prototype) ? Object.keys : 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;
|
|
}
|
|
};
|
|
|
|
|
|
|
|
Ext.merge = Ext.Object.merge;
|
|
|
|
|
|
Ext.urlEncode = function() {
|
|
var args = Ext.Array.from(arguments),
|
|
prefix = '';
|
|
|
|
|
|
if ((typeof args[1] === 'string')) {
|
|
prefix = args[1] + '&';
|
|
args[1] = false;
|
|
}
|
|
|
|
return prefix + Ext.Object.toQueryString.apply(Ext.Object, args);
|
|
};
|
|
|
|
|
|
Ext.urlDecode = function() {
|
|
return Ext.Object.fromQueryString.apply(Ext.Object, arguments);
|
|
};
|
|
|
|
})();
|
|
|
|
|
|
|
|
|
|
|
|
(function() {
|
|
|
|
|
|
|
|
|
|
function xf(format) {
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
return format.replace(/\{(\d+)\}/g, function(m, i) {
|
|
return args[i];
|
|
});
|
|
}
|
|
|
|
Ext.Date = {
|
|
|
|
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 || new Date()));
|
|
},
|
|
|
|
|
|
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 re = new RegExp('\\/Date\\(([-+])?(\\d+)(?:[+-]\\d{4})?\\)\\/');
|
|
var r = (input || '').match(re);
|
|
return r? new Date(((r[1] || '') + r[2]) * 1) : null;
|
|
}
|
|
},
|
|
parseRegexes: [],
|
|
|
|
|
|
formatFunctions: {
|
|
"MS": function() {
|
|
|
|
return '\\/Date(' + this.getTime() + ')\\/';
|
|
}
|
|
},
|
|
|
|
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 : {
|
|
Jan:0,
|
|
Feb:1,
|
|
Mar:2,
|
|
Apr:3,
|
|
May:4,
|
|
Jun:5,
|
|
Jul:6,
|
|
Aug:7,
|
|
Sep:8,
|
|
Oct:9,
|
|
Nov:10,
|
|
Dec:11
|
|
},
|
|
|
|
defaultFormat : "m/d/Y",
|
|
|
|
getShortMonthName : function(month) {
|
|
return utilDate.monthNames[month].substring(0, 3);
|
|
},
|
|
|
|
|
|
getShortDayName : function(day) {
|
|
return utilDate.dayNames[day].substring(0, 3);
|
|
},
|
|
|
|
|
|
getMonthNumber : function(name) {
|
|
|
|
return utilDate.monthNumbers[name.substring(0, 1).toUpperCase() + name.substring(1, 3).toLowerCase()];
|
|
},
|
|
|
|
|
|
formatContainsHourInfo : (function(){
|
|
var stripEscapeRe = /(\\.)/g,
|
|
hourInfoRe = /([gGhHisucUOPZ]|MS)/;
|
|
return function(format){
|
|
return hourInfoRe.test(format.replace(stripEscapeRe, ''));
|
|
};
|
|
})(),
|
|
|
|
|
|
formatContainsDateInfo : (function(){
|
|
var stripEscapeRe = /(\\.)/g,
|
|
dateInfoRe = /([djzmnYycU]|MS)/;
|
|
|
|
return function(format){
|
|
return dateInfoRe.test(format.replace(stripEscapeRe, ''));
|
|
};
|
|
})(),
|
|
|
|
|
|
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() {
|
|
for (var c = "Y-m-dTH:i:sP", code = [], i = 0, l = c.length; i < l; ++i) {
|
|
var 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](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 = '';
|
|
|
|
for (var 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() {
|
|
var code = [
|
|
"var dt, y, m, d, h, i, s, ms, o, z, zz, u, v,",
|
|
"def = Ext.Date.defaults,",
|
|
"results = String(input).match(Ext.Date.parseRegexes[{0}]);",
|
|
|
|
"if(results){",
|
|
"{1}",
|
|
|
|
"if(u != null){",
|
|
"v = new Date(u * 1000);",
|
|
"}else{",
|
|
|
|
|
|
|
|
"dt = Ext.Date.clearTime(new Date);",
|
|
|
|
|
|
"y = Ext.Number.from(y, Ext.Number.from(def.y, dt.getFullYear()));",
|
|
"m = Ext.Number.from(m, Ext.Number.from(def.m - 1, dt.getMonth()));",
|
|
"d = Ext.Number.from(d, Ext.Number.from(def.d, dt.getDate()));",
|
|
|
|
|
|
"h = Ext.Number.from(h, Ext.Number.from(def.h, dt.getHours()));",
|
|
"i = Ext.Number.from(i, Ext.Number.from(def.i, dt.getMinutes()));",
|
|
"s = Ext.Number.from(s, Ext.Number.from(def.s, dt.getSeconds()));",
|
|
"ms = Ext.Number.from(ms, Ext.Number.from(def.ms, dt.getMilliseconds()));",
|
|
|
|
"if(z >= 0 && y >= 0){",
|
|
|
|
|
|
|
|
|
|
|
|
"v = Ext.Date.add(new Date(y < 100 ? 100 : y, 0, 1, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);",
|
|
|
|
|
|
"v = !strict? v : (strict === true && (z <= 364 || (Ext.Date.isLeapYear(v) && z <= 365))? Ext.Date.add(v, Ext.Date.DAY, z) : null);",
|
|
"}else if(strict === true && !Ext.Date.isValid(y, m + 1, d, h, i, s, ms)){",
|
|
"v = null;",
|
|
"}else{",
|
|
|
|
|
|
"v = Ext.Date.add(new Date(y < 100 ? 100 : y, m, d, h, i, s, ms), Ext.Date.YEAR, y < 100 ? y - 100 : 0);",
|
|
"}",
|
|
"}",
|
|
"}",
|
|
|
|
"if(v){",
|
|
|
|
"if(zz != null){",
|
|
|
|
"v = Ext.Date.add(v, Ext.Date.SECOND, -v.getTimezoneOffset() * 60 - zz);",
|
|
"}else if(o){",
|
|
|
|
"v = Ext.Date.add(v, Ext.Date.MINUTE, -v.getTimezoneOffset() + (sn == '+'? -1 : 1) * (hr * 60 + mn));",
|
|
"}",
|
|
"}",
|
|
|
|
"return v;"
|
|
].join('\n');
|
|
|
|
return function(format) {
|
|
var regexNum = utilDate.parseRegexes.length,
|
|
currentGroup = 1,
|
|
calc = [],
|
|
regex = [],
|
|
special = false,
|
|
ch = "";
|
|
|
|
for (var i = 0; i < format.length; ++i) {
|
|
ch = format.charAt(i);
|
|
if (!special && ch == "\\") {
|
|
special = true;
|
|
} else if (special) {
|
|
special = false;
|
|
regex.push(Ext.String.escape(ch));
|
|
} else {
|
|
var obj = utilDate.formatCodeToRegex(ch, currentGroup);
|
|
currentGroup += obj.g;
|
|
regex.push(obj.s);
|
|
if (obj.g && obj.c) {
|
|
calc.push(obj.c);
|
|
}
|
|
}
|
|
}
|
|
|
|
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:"(\\d{2})"
|
|
},
|
|
j: {
|
|
g:1,
|
|
c:"d = parseInt(results[{0}], 10);\n",
|
|
s:"(\\d{1,2})"
|
|
},
|
|
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:0,
|
|
c:null,
|
|
s:"(?:\\d{2})"
|
|
},
|
|
F: function() {
|
|
return {
|
|
g:1,
|
|
c:"m = parseInt(Ext.Date.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:"(\\d{2})"
|
|
},
|
|
n: {
|
|
g:1,
|
|
c:"m = parseInt(results[{0}], 10) - 1;\n",
|
|
s:"(\\d{1,2})"
|
|
},
|
|
t: {
|
|
g:0,
|
|
c:null,
|
|
s:"(?:\\d{2})"
|
|
},
|
|
L: {
|
|
g:0,
|
|
c:null,
|
|
s:"(?:1|0)"
|
|
},
|
|
o: function() {
|
|
return utilDate.formatCodeToRegex("Y");
|
|
},
|
|
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 > Ext.Date.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)"
|
|
},
|
|
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)"
|
|
},
|
|
g: function() {
|
|
return utilDate.formatCodeToRegex("G");
|
|
},
|
|
G: {
|
|
g:1,
|
|
c:"h = parseInt(results[{0}], 10);\n",
|
|
s:"(\\d{1,2})"
|
|
},
|
|
h: function() {
|
|
return utilDate.formatCodeToRegex("H");
|
|
},
|
|
H: {
|
|
g:1,
|
|
c:"h = parseInt(results[{0}], 10);\n",
|
|
s:"(\\d{2})"
|
|
},
|
|
i: {
|
|
g:1,
|
|
c:"i = parseInt(results[{0}], 10);\n",
|
|
s:"(\\d{2})"
|
|
},
|
|
s: {
|
|
g:1,
|
|
c:"s = parseInt(results[{0}], 10);\n",
|
|
s:"(\\d{2})"
|
|
},
|
|
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,4}"
|
|
},
|
|
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')}
|
|
];
|
|
|
|
for (var 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);
|
|
},
|
|
|
|
|
|
format: function(date, format) {
|
|
if (utilDate.formatFunctions[format] == null) {
|
|
utilDate.createFormat(format);
|
|
}
|
|
var result = utilDate.formatFunctions[format].call(date);
|
|
return result + '';
|
|
},
|
|
|
|
|
|
getTimezone : function(date) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return date.toString().replace(/^.* (?:\((.*)\)|([A-Z]{1,4})(?:[\-+][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();
|
|
|
|
|
|
date.setHours(0);
|
|
date.setMinutes(0);
|
|
date.setSeconds(0);
|
|
date.setMilliseconds(0);
|
|
|
|
if (date.getDate() != d) {
|
|
|
|
|
|
|
|
|
|
for (var 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;
|
|
if (!interval || value === 0) return d;
|
|
|
|
switch(interval.toLowerCase()) {
|
|
case Ext.Date.MILLI:
|
|
d.setMilliseconds(d.getMilliseconds() + value);
|
|
break;
|
|
case Ext.Date.SECOND:
|
|
d.setSeconds(d.getSeconds() + value);
|
|
break;
|
|
case Ext.Date.MINUTE:
|
|
d.setMinutes(d.getMinutes() + value);
|
|
break;
|
|
case Ext.Date.HOUR:
|
|
d.setHours(d.getHours() + value);
|
|
break;
|
|
case Ext.Date.DAY:
|
|
d.setDate(d.getDate() + value);
|
|
break;
|
|
case Ext.Date.MONTH:
|
|
var day = date.getDate();
|
|
if (day > 28) {
|
|
day = Math.min(day, Ext.Date.getLastDateOfMonth(Ext.Date.add(Ext.Date.getFirstDateOfMonth(date), 'mo', value)).getDate());
|
|
}
|
|
d.setDate(day);
|
|
d.setMonth(date.getMonth() + value);
|
|
break;
|
|
case Ext.Date.YEAR:
|
|
d.setFullYear(date.getFullYear() + value);
|
|
break;
|
|
}
|
|
return d;
|
|
},
|
|
|
|
|
|
between : function(date, start, end) {
|
|
var t = date.getTime();
|
|
return start.getTime() <= t && t <= end.getTime();
|
|
},
|
|
|
|
|
|
compat: function() {
|
|
var nativeDate = window.Date,
|
|
p, u,
|
|
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'];
|
|
|
|
|
|
Ext.Array.forEach(statics, function(s) {
|
|
nativeDate[s] = utilDate[s];
|
|
});
|
|
|
|
|
|
Ext.Array.forEach(proto, function(s) {
|
|
nativeDate.prototype[s] = function() {
|
|
var args = Array.prototype.slice.call(arguments);
|
|
args.unshift(this);
|
|
return utilDate[s].apply(utilDate, args);
|
|
};
|
|
});
|
|
}
|
|
};
|
|
|
|
var utilDate = Ext.Date;
|
|
|
|
})();
|
|
|
|
|
|
(function(flexSetter) {
|
|
|
|
var Base = Ext.Base = function() {};
|
|
Base.prototype = {
|
|
$className: 'Ext.Base',
|
|
|
|
$class: Base,
|
|
|
|
|
|
self: Base,
|
|
|
|
|
|
constructor: function() {
|
|
return this;
|
|
},
|
|
|
|
|
|
|
|
initConfig: function(config) {
|
|
if (!this.$configInited) {
|
|
this.config = Ext.Object.merge({}, this.config || {}, config || {});
|
|
|
|
this.applyConfig(this.config);
|
|
|
|
this.$configInited = true;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
setConfig: function(config) {
|
|
this.applyConfig(config || {});
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
applyConfig: flexSetter(function(name, value) {
|
|
var setter = 'set' + Ext.String.capitalize(name);
|
|
|
|
if (typeof this[setter] === 'function') {
|
|
this[setter].call(this, value);
|
|
}
|
|
|
|
return this;
|
|
}),
|
|
|
|
|
|
|
|
callParent: function(args) {
|
|
var method = this.callParent.caller,
|
|
parentClass, methodName;
|
|
|
|
if (!method.$owner) {
|
|
|
|
method = method.caller;
|
|
}
|
|
|
|
parentClass = method.$owner.superclass;
|
|
methodName = method.$name;
|
|
|
|
|
|
return parentClass[methodName].apply(this, args || []);
|
|
},
|
|
|
|
|
|
|
|
statics: function() {
|
|
var method = this.statics.caller,
|
|
self = this.self;
|
|
|
|
if (!method) {
|
|
return self;
|
|
}
|
|
|
|
return method.$owner;
|
|
},
|
|
|
|
|
|
callOverridden: function(args) {
|
|
var method = this.callOverridden.caller;
|
|
|
|
|
|
return method.$previous.apply(this, args || []);
|
|
},
|
|
|
|
destroy: function() {}
|
|
};
|
|
|
|
|
|
Ext.apply(Ext.Base, {
|
|
|
|
create: function() {
|
|
return Ext.create.apply(Ext, [this].concat(Array.prototype.slice.call(arguments, 0)));
|
|
},
|
|
|
|
|
|
own: function(name, value) {
|
|
if (typeof value == 'function') {
|
|
this.ownMethod(name, value);
|
|
}
|
|
else {
|
|
this.prototype[name] = value;
|
|
}
|
|
},
|
|
|
|
|
|
ownMethod: function(name, fn) {
|
|
var originalFn;
|
|
|
|
if (typeof fn.$owner !== 'undefined' && fn !== Ext.emptyFn) {
|
|
originalFn = fn;
|
|
|
|
fn = function() {
|
|
return originalFn.apply(this, arguments);
|
|
};
|
|
}
|
|
|
|
fn.$owner = this;
|
|
fn.$name = name;
|
|
|
|
this.prototype[name] = fn;
|
|
},
|
|
|
|
|
|
addStatics: function(members) {
|
|
for (var name in members) {
|
|
if (members.hasOwnProperty(name)) {
|
|
this[name] = members[name];
|
|
}
|
|
}
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
implement: function(members) {
|
|
var prototype = this.prototype,
|
|
enumerables = Ext.enumerables,
|
|
name, i, member;
|
|
for (name in members) {
|
|
if (members.hasOwnProperty(name)) {
|
|
member = members[name];
|
|
|
|
if (typeof member === 'function') {
|
|
member.$owner = this;
|
|
member.$name = name;
|
|
}
|
|
|
|
prototype[name] = member;
|
|
}
|
|
}
|
|
|
|
if (enumerables) {
|
|
for (i = enumerables.length; i--;) {
|
|
name = enumerables[i];
|
|
|
|
if (members.hasOwnProperty(name)) {
|
|
member = members[name];
|
|
member.$owner = this;
|
|
member.$name = name;
|
|
prototype[name] = member;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
borrow: function(fromClass, members) {
|
|
var fromPrototype = fromClass.prototype,
|
|
i, ln, member;
|
|
|
|
members = Ext.Array.from(members);
|
|
|
|
for (i = 0, ln = members.length; i < ln; i++) {
|
|
member = members[i];
|
|
|
|
this.own(member, fromPrototype[member]);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
override: function(members) {
|
|
var prototype = this.prototype,
|
|
enumerables = Ext.enumerables,
|
|
name, i, member, previous;
|
|
|
|
if (arguments.length === 2) {
|
|
name = members;
|
|
member = arguments[1];
|
|
|
|
if (typeof member == 'function') {
|
|
if (typeof prototype[name] == 'function') {
|
|
previous = prototype[name];
|
|
member.$previous = previous;
|
|
}
|
|
|
|
this.ownMethod(name, member);
|
|
}
|
|
else {
|
|
prototype[name] = member;
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
for (name in members) {
|
|
if (members.hasOwnProperty(name)) {
|
|
member = members[name];
|
|
|
|
if (typeof member === 'function') {
|
|
if (typeof prototype[name] === 'function') {
|
|
previous = prototype[name];
|
|
member.$previous = previous;
|
|
}
|
|
|
|
this.ownMethod(name, member);
|
|
}
|
|
else {
|
|
prototype[name] = member;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (enumerables) {
|
|
for (i = enumerables.length; i--;) {
|
|
name = enumerables[i];
|
|
|
|
if (members.hasOwnProperty(name)) {
|
|
if (typeof prototype[name] !== 'undefined') {
|
|
previous = prototype[name];
|
|
members[name].$previous = previous;
|
|
}
|
|
|
|
this.ownMethod(name, members[name]);
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
|
|
mixin: function(name, cls) {
|
|
var mixin = cls.prototype,
|
|
my = this.prototype,
|
|
key, fn;
|
|
|
|
for (key in mixin) {
|
|
if (mixin.hasOwnProperty(key)) {
|
|
if (typeof my[key] === 'undefined' && key !== 'mixins' && key !== 'mixinId') {
|
|
if (typeof mixin[key] === 'function') {
|
|
fn = mixin[key];
|
|
|
|
if (typeof fn.$owner === 'undefined') {
|
|
this.ownMethod(key, fn);
|
|
}
|
|
else {
|
|
my[key] = fn;
|
|
}
|
|
}
|
|
else {
|
|
my[key] = mixin[key];
|
|
}
|
|
}
|
|
|
|
else if (key === 'config' && my.config && mixin.config) {
|
|
Ext.Object.merge(my.config, mixin.config);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (typeof mixin.onClassMixedIn !== 'undefined') {
|
|
mixin.onClassMixedIn.call(cls, this);
|
|
}
|
|
|
|
if (!my.hasOwnProperty('mixins')) {
|
|
if ('mixins' in my) {
|
|
my.mixins = Ext.Object.merge({}, my.mixins);
|
|
}
|
|
else {
|
|
my.mixins = {};
|
|
}
|
|
}
|
|
|
|
my.mixins[name] = mixin;
|
|
},
|
|
|
|
|
|
|
|
getName: function() {
|
|
return Ext.getClassName(this);
|
|
},
|
|
|
|
|
|
createAlias: flexSetter(function(alias, origin) {
|
|
this.prototype[alias] = function() {
|
|
return this[origin].apply(this, arguments);
|
|
}
|
|
})
|
|
});
|
|
|
|
})(Ext.Function.flexSetter);
|
|
|
|
|
|
(function() {
|
|
|
|
var Class,
|
|
Base = Ext.Base,
|
|
baseStaticProperties = [],
|
|
baseStaticProperty;
|
|
|
|
for (baseStaticProperty in Base) {
|
|
if (Base.hasOwnProperty(baseStaticProperty)) {
|
|
baseStaticProperties.push(baseStaticProperty);
|
|
}
|
|
}
|
|
|
|
|
|
Ext.Class = Class = function(newClass, classData, onClassCreated) {
|
|
if (typeof newClass != 'function') {
|
|
onClassCreated = classData;
|
|
classData = newClass;
|
|
newClass = function() {
|
|
return this.constructor.apply(this, arguments);
|
|
};
|
|
}
|
|
|
|
if (!classData) {
|
|
classData = {};
|
|
}
|
|
|
|
var preprocessorStack = classData.preprocessors || Class.getDefaultPreprocessors(),
|
|
registeredPreprocessors = Class.getPreprocessors(),
|
|
index = 0,
|
|
preprocessors = [],
|
|
preprocessor, staticPropertyName, process, i, j, ln;
|
|
|
|
for (i = 0, ln = baseStaticProperties.length; i < ln; i++) {
|
|
staticPropertyName = baseStaticProperties[i];
|
|
newClass[staticPropertyName] = Base[staticPropertyName];
|
|
}
|
|
|
|
delete classData.preprocessors;
|
|
|
|
for (j = 0, ln = preprocessorStack.length; j < ln; j++) {
|
|
preprocessor = preprocessorStack[j];
|
|
|
|
if (typeof preprocessor == 'string') {
|
|
preprocessor = registeredPreprocessors[preprocessor];
|
|
|
|
if (!preprocessor.always) {
|
|
if (classData.hasOwnProperty(preprocessor.name)) {
|
|
preprocessors.push(preprocessor.fn);
|
|
}
|
|
}
|
|
else {
|
|
preprocessors.push(preprocessor.fn);
|
|
}
|
|
}
|
|
else {
|
|
preprocessors.push(preprocessor);
|
|
}
|
|
}
|
|
|
|
classData.onClassCreated = onClassCreated || Ext.emptyFn;
|
|
|
|
classData.onBeforeClassCreated = function(cls, data) {
|
|
onClassCreated = data.onClassCreated;
|
|
|
|
delete data.onBeforeClassCreated;
|
|
delete data.onClassCreated;
|
|
|
|
cls.implement(data);
|
|
|
|
onClassCreated.call(cls, cls);
|
|
};
|
|
|
|
process = function(cls, data) {
|
|
preprocessor = preprocessors[index++];
|
|
|
|
if (!preprocessor) {
|
|
data.onBeforeClassCreated.apply(this, arguments);
|
|
return;
|
|
}
|
|
|
|
if (preprocessor.call(this, cls, data, process) !== false) {
|
|
process.apply(this, arguments);
|
|
}
|
|
};
|
|
|
|
process.call(Class, newClass, classData);
|
|
|
|
return newClass;
|
|
};
|
|
|
|
Ext.apply(Class, {
|
|
|
|
|
|
preprocessors: {},
|
|
|
|
|
|
registerPreprocessor: function(name, fn, always) {
|
|
this.preprocessors[name] = {
|
|
name: name,
|
|
always: always || false,
|
|
fn: fn
|
|
};
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
getPreprocessor: function(name) {
|
|
return this.preprocessors[name];
|
|
},
|
|
|
|
getPreprocessors: function() {
|
|
return this.preprocessors;
|
|
},
|
|
|
|
|
|
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;
|
|
}
|
|
});
|
|
|
|
|
|
Class.registerPreprocessor('extend', function(cls, data) {
|
|
var extend = data.extend,
|
|
base = Ext.Base,
|
|
basePrototype = base.prototype,
|
|
prototype = function() {},
|
|
parent, i, k, ln, staticName, parentStatics,
|
|
parentPrototype, clsPrototype;
|
|
|
|
if (extend && extend !== Object) {
|
|
parent = extend;
|
|
}
|
|
else {
|
|
parent = base;
|
|
}
|
|
|
|
parentPrototype = parent.prototype;
|
|
|
|
prototype.prototype = parentPrototype;
|
|
clsPrototype = cls.prototype = new prototype();
|
|
|
|
if (!('$class' in parent)) {
|
|
for (i in basePrototype) {
|
|
if (!parentPrototype[i]) {
|
|
parentPrototype[i] = basePrototype[i];
|
|
}
|
|
}
|
|
}
|
|
|
|
clsPrototype.self = cls;
|
|
|
|
cls.superclass = clsPrototype.superclass = parentPrototype;
|
|
|
|
delete data.extend;
|
|
|
|
|
|
|
|
parentStatics = parentPrototype.$inheritableStatics;
|
|
|
|
if (parentStatics) {
|
|
for (k = 0, ln = parentStatics.length; k < ln; k++) {
|
|
staticName = parentStatics[k];
|
|
|
|
if (!cls.hasOwnProperty(staticName)) {
|
|
cls[staticName] = parent[staticName];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parentPrototype.config) {
|
|
clsPrototype.config = Ext.Object.merge({}, parentPrototype.config);
|
|
}
|
|
else {
|
|
clsPrototype.config = {};
|
|
}
|
|
|
|
|
|
|
|
if (clsPrototype.$onExtended) {
|
|
clsPrototype.$onExtended.call(cls, cls, data);
|
|
}
|
|
|
|
if (data.onClassExtended) {
|
|
clsPrototype.$onExtended = data.onClassExtended;
|
|
delete data.onClassExtended;
|
|
}
|
|
|
|
|
|
}, true);
|
|
|
|
|
|
|
|
Class.registerPreprocessor('statics', function(cls, data) {
|
|
cls.addStatics(data.statics);
|
|
|
|
delete data.statics;
|
|
});
|
|
|
|
|
|
|
|
|
|
Class.registerPreprocessor('inheritableStatics', function(cls, data) {
|
|
cls.addInheritableStatics(data.inheritableStatics);
|
|
|
|
delete data.inheritableStatics;
|
|
});
|
|
|
|
|
|
|
|
|
|
Class.registerPreprocessor('config', function(cls, data) {
|
|
var prototype = cls.prototype;
|
|
|
|
Ext.Object.each(data.config, function(name) {
|
|
var cName = name.charAt(0).toUpperCase() + name.substr(1),
|
|
pName = name,
|
|
apply = 'apply' + cName,
|
|
setter = 'set' + cName,
|
|
getter = 'get' + cName;
|
|
|
|
if (!(apply in prototype) && !data.hasOwnProperty(apply)) {
|
|
data[apply] = function(val) {
|
|
return val;
|
|
};
|
|
}
|
|
|
|
if (!(setter in prototype) && !data.hasOwnProperty(setter)) {
|
|
data[setter] = function(val) {
|
|
var ret = this[apply].call(this, val, this[pName]);
|
|
|
|
if (typeof ret != 'undefined') {
|
|
this[pName] = ret;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
}
|
|
|
|
if (!(getter in prototype) && !data.hasOwnProperty(getter)) {
|
|
data[getter] = function() {
|
|
return this[pName];
|
|
};
|
|
}
|
|
});
|
|
|
|
Ext.Object.merge(prototype.config, data.config);
|
|
delete data.config;
|
|
});
|
|
|
|
|
|
|
|
|
|
Class.registerPreprocessor('mixins', function(cls, data) {
|
|
var mixins = data.mixins,
|
|
name, mixin, i, ln;
|
|
|
|
delete data.mixins;
|
|
|
|
Ext.Function.interceptBefore(data, 'onClassCreated', function(cls) {
|
|
if (mixins instanceof Array) {
|
|
for (i = 0,ln = mixins.length; i < ln; i++) {
|
|
mixin = mixins[i];
|
|
name = mixin.prototype.mixinId || mixin.$className;
|
|
|
|
cls.mixin(name, mixin);
|
|
}
|
|
}
|
|
else {
|
|
for (name in mixins) {
|
|
if (mixins.hasOwnProperty(name)) {
|
|
cls.mixin(name, mixins[name]);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
|
|
Class.setDefaultPreprocessors([
|
|
'extend'
|
|
|
|
,'statics'
|
|
|
|
|
|
,'inheritableStatics'
|
|
|
|
|
|
,'config'
|
|
|
|
|
|
,'mixins'
|
|
|
|
]);
|
|
|
|
|
|
|
|
Ext.extend = function(subclass, superclass, members) {
|
|
if (arguments.length === 2 && Ext.isObject(superclass)) {
|
|
members = superclass;
|
|
superclass = subclass;
|
|
subclass = null;
|
|
}
|
|
|
|
var cls;
|
|
|
|
if (!superclass) {
|
|
Ext.Error.raise("Attempting to extend from a class which has not been loaded on the page.");
|
|
}
|
|
|
|
members.extend = superclass;
|
|
members.preprocessors = [
|
|
'extend'
|
|
|
|
,'statics'
|
|
|
|
|
|
,'inheritableStatics'
|
|
|
|
|
|
,'mixins'
|
|
|
|
|
|
,'config'
|
|
|
|
];
|
|
|
|
if (subclass) {
|
|
cls = new Class(subclass, members);
|
|
}
|
|
else {
|
|
cls = new Class(members);
|
|
}
|
|
|
|
cls.prototype.override = function(o) {
|
|
for (var m in o) {
|
|
if (o.hasOwnProperty(m)) {
|
|
this[m] = o[m];
|
|
}
|
|
}
|
|
};
|
|
|
|
return cls;
|
|
};
|
|
|
|
|
|
})();
|
|
|
|
|
|
(function(Class, alias) {
|
|
|
|
var slice = Array.prototype.slice;
|
|
|
|
var Manager = Ext.ClassManager = {
|
|
|
|
|
|
classes: {},
|
|
|
|
|
|
existCache: {},
|
|
|
|
|
|
namespaceRewrites: [{
|
|
from: 'Ext.',
|
|
to: Ext
|
|
}],
|
|
|
|
|
|
maps: {
|
|
alternateToName: {},
|
|
aliasToName: {},
|
|
nameToAliases: {}
|
|
},
|
|
|
|
|
|
enableNamespaceParseCache: true,
|
|
|
|
|
|
namespaceParseCache: {},
|
|
|
|
|
|
instantiators: [],
|
|
|
|
|
|
|
|
isCreated: function(className) {
|
|
var i, ln, part, root, parts;
|
|
|
|
|
|
if (this.classes.hasOwnProperty(className) || this.existCache.hasOwnProperty(className)) {
|
|
return true;
|
|
}
|
|
|
|
root = Ext.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];
|
|
}
|
|
}
|
|
|
|
Ext.Loader.historyPush(className);
|
|
|
|
this.existCache[className] = true;
|
|
|
|
return true;
|
|
},
|
|
|
|
|
|
parseNamespace: function(namespace) {
|
|
|
|
var cache = this.namespaceParseCache;
|
|
|
|
if (this.enableNamespaceParseCache) {
|
|
if (cache.hasOwnProperty(namespace)) {
|
|
return cache[namespace];
|
|
}
|
|
}
|
|
|
|
var parts = [],
|
|
rewrites = this.namespaceRewrites,
|
|
rewrite, from, to, i, ln, root = Ext.global;
|
|
|
|
for (i = 0, ln = rewrites.length; i < ln; i++) {
|
|
rewrite = rewrites[i];
|
|
from = rewrite.from;
|
|
to = rewrite.to;
|
|
|
|
if (namespace === from || namespace.substring(0, from.length) === from) {
|
|
namespace = namespace.substring(from.length);
|
|
|
|
if (typeof to !== 'string') {
|
|
root = to;
|
|
} else {
|
|
parts = parts.concat(to.split('.'));
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
parts.push(root);
|
|
|
|
parts = parts.concat(namespace.split('.'));
|
|
|
|
if (this.enableNamespaceParseCache) {
|
|
cache[namespace] = parts;
|
|
}
|
|
|
|
return parts;
|
|
},
|
|
|
|
|
|
setNamespace: function(name, value) {
|
|
var root = Ext.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 = Ext.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 targetName = this.getName(value);
|
|
|
|
this.classes[name] = this.setNamespace(name, value);
|
|
|
|
if (targetName && targetName !== name) {
|
|
this.maps.alternateToName[name] = targetName;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
get: function(name) {
|
|
if (this.classes.hasOwnProperty(name)) {
|
|
return this.classes[name];
|
|
}
|
|
|
|
var root = Ext.global,
|
|
parts = this.parseNamespace(name),
|
|
part, i, ln;
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
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 manager = this;
|
|
|
|
|
|
data.$className = className;
|
|
|
|
return new Class(data, function() {
|
|
var postprocessorStack = data.postprocessors || manager.defaultPostprocessors,
|
|
registeredPostprocessors = manager.postprocessors,
|
|
index = 0,
|
|
postprocessors = [],
|
|
postprocessor, process, i, ln;
|
|
|
|
delete data.postprocessors;
|
|
|
|
for (i = 0, ln = postprocessorStack.length; i < ln; i++) {
|
|
postprocessor = postprocessorStack[i];
|
|
|
|
if (typeof postprocessor === 'string') {
|
|
postprocessor = registeredPostprocessors[postprocessor];
|
|
|
|
if (!postprocessor.always) {
|
|
if (data[postprocessor.name] !== undefined) {
|
|
postprocessors.push(postprocessor.fn);
|
|
}
|
|
}
|
|
else {
|
|
postprocessors.push(postprocessor.fn);
|
|
}
|
|
}
|
|
else {
|
|
postprocessors.push(postprocessor);
|
|
}
|
|
}
|
|
|
|
process = function(clsName, cls, clsData) {
|
|
postprocessor = postprocessors[index++];
|
|
|
|
if (!postprocessor) {
|
|
manager.set(className, cls);
|
|
|
|
Ext.Loader.historyPush(className);
|
|
|
|
if (createdFn) {
|
|
createdFn.call(cls, cls);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (postprocessor.call(this, clsName, cls, clsData, process) !== false) {
|
|
process.apply(this, arguments);
|
|
}
|
|
};
|
|
|
|
process.call(manager, className, this, data);
|
|
});
|
|
},
|
|
|
|
|
|
instantiateByAlias: function() {
|
|
var alias = arguments[0],
|
|
args = slice.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],
|
|
args = slice.call(arguments, 1),
|
|
alias = name,
|
|
possibleName, cls;
|
|
|
|
if (typeof name !== 'function') {
|
|
|
|
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 = Ext.Array.from(args, true);
|
|
args.unshift(name);
|
|
|
|
return this.instantiate.apply(this, args);
|
|
},
|
|
|
|
|
|
getInstantiator: function(length) {
|
|
if (!this.instantiators[length]) {
|
|
var i = length,
|
|
args = [];
|
|
|
|
for (i = 0; i < length; i++) {
|
|
args.push('a['+i+']');
|
|
}
|
|
|
|
this.instantiators[length] = new Function('c', 'a', 'return new c('+args.join(',')+')');
|
|
}
|
|
|
|
return this.instantiators[length];
|
|
},
|
|
|
|
|
|
postprocessors: {},
|
|
|
|
|
|
defaultPostprocessors: [],
|
|
|
|
|
|
registerPostprocessor: function(name, fn, always) {
|
|
this.postprocessors[name] = {
|
|
name: name,
|
|
always: always || false,
|
|
fn: fn
|
|
};
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
setDefaultPostprocessors: function(postprocessors) {
|
|
this.defaultPostprocessors = Ext.Array.from(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;
|
|
}
|
|
};
|
|
|
|
var defaultPostprocessors = Manager.defaultPostprocessors;
|
|
|
|
|
|
|
|
Manager.registerPostprocessor('alias', function(name, cls, data) {
|
|
var aliases = data.alias,
|
|
i, ln;
|
|
|
|
delete data.alias;
|
|
|
|
for (i = 0, ln = aliases.length; i < ln; i++) {
|
|
alias = aliases[i];
|
|
|
|
this.setAlias(cls, alias);
|
|
}
|
|
});
|
|
|
|
|
|
Manager.registerPostprocessor('singleton', function(name, cls, data, fn) {
|
|
fn.call(this, name, new cls(), data);
|
|
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);
|
|
}
|
|
});
|
|
|
|
Manager.setDefaultPostprocessors(['alias', 'singleton', 'alternateClassName']);
|
|
|
|
Ext.apply(Ext, {
|
|
|
|
create: alias(Manager, 'instantiate'),
|
|
|
|
|
|
factory: function(item, namespace) {
|
|
if (item instanceof Array) {
|
|
var i, ln;
|
|
|
|
for (i = 0, ln = item.length; i < ln; i++) {
|
|
item[i] = Ext.factory(item[i], namespace);
|
|
}
|
|
|
|
return item;
|
|
}
|
|
|
|
var isString = (typeof item === 'string');
|
|
|
|
if (isString || (item instanceof Object && item.constructor === Object)) {
|
|
var name, config = {};
|
|
|
|
if (isString) {
|
|
name = item;
|
|
}
|
|
else {
|
|
name = item.className;
|
|
config = item;
|
|
delete config.className;
|
|
}
|
|
|
|
if (namespace !== undefined && name.indexOf(namespace) === -1) {
|
|
name = namespace + '.' + Ext.String.capitalize(name);
|
|
}
|
|
|
|
return Ext.create(name, config);
|
|
}
|
|
|
|
if (typeof item === 'function') {
|
|
return Ext.create(item);
|
|
}
|
|
|
|
return item;
|
|
},
|
|
|
|
|
|
widget: function(name) {
|
|
var args = slice.call(arguments);
|
|
args[0] = 'widget.' + name;
|
|
|
|
return Manager.instantiateByAlias.apply(Manager, args);
|
|
},
|
|
|
|
|
|
createByAlias: alias(Manager, 'instantiateByAlias'),
|
|
|
|
|
|
|
|
|
|
define: function (className, data, createdFn) {
|
|
if (!data.override) {
|
|
return Manager.create.apply(Manager, arguments);
|
|
}
|
|
|
|
var requires = data.requires,
|
|
uses = data.uses,
|
|
overrideName = className;
|
|
|
|
className = data.override;
|
|
|
|
|
|
data = Ext.apply({}, data);
|
|
delete data.requires;
|
|
delete data.uses;
|
|
delete data.override;
|
|
|
|
|
|
if (typeof requires == 'string') {
|
|
requires = [ className, requires ];
|
|
} else if (requires) {
|
|
requires = requires.slice(0);
|
|
requires.unshift(className);
|
|
} else {
|
|
requires = [ className ];
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Manager.create(overrideName, {
|
|
requires: requires,
|
|
uses: uses,
|
|
isPartial: true,
|
|
constructor: function () {
|
|
}
|
|
}, function () {
|
|
var cls = Manager.get(className);
|
|
if (cls.override) {
|
|
cls.override(data);
|
|
} else {
|
|
cls.self.override(data);
|
|
}
|
|
|
|
if (createdFn) {
|
|
|
|
|
|
|
|
createdFn.call(cls);
|
|
}
|
|
});
|
|
},
|
|
|
|
|
|
getClassName: alias(Manager, 'getName'),
|
|
|
|
|
|
getDisplayName: function(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);
|
|
|
|
Class.setDefaultPreprocessorPosition('className', 'first');
|
|
|
|
Class.registerPreprocessor('xtype', function(cls, data) {
|
|
var xtypes = Ext.Array.from(data.xtype),
|
|
widgetPrefix = 'widget.',
|
|
aliases = Ext.Array.from(data.alias),
|
|
i, ln, xtype;
|
|
|
|
data.xtype = xtypes[0];
|
|
data.xtypes = xtypes;
|
|
|
|
aliases = data.alias = Ext.Array.from(data.alias);
|
|
|
|
for (i = 0,ln = xtypes.length; i < ln; i++) {
|
|
xtype = xtypes[i];
|
|
|
|
|
|
aliases.push(widgetPrefix + xtype);
|
|
}
|
|
|
|
data.alias = aliases;
|
|
});
|
|
|
|
Class.setDefaultPreprocessorPosition('xtype', 'last');
|
|
|
|
Class.registerPreprocessor('alias', function(cls, data) {
|
|
var aliases = Ext.Array.from(data.alias),
|
|
xtypes = Ext.Array.from(data.xtypes),
|
|
widgetPrefix = 'widget.',
|
|
widgetPrefixLength = widgetPrefix.length,
|
|
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);
|
|
|
|
if (!cls.xtype) {
|
|
cls.xtype = data.xtype = xtype;
|
|
}
|
|
}
|
|
}
|
|
|
|
data.alias = aliases;
|
|
data.xtypes = xtypes;
|
|
});
|
|
|
|
Class.setDefaultPreprocessorPosition('alias', 'last');
|
|
|
|
})(Ext.Class, Ext.Function.alias);
|
|
|
|
|
|
(function(Manager, Class, flexSetter, alias) {
|
|
|
|
var
|
|
dependencyProperties = ['extend', 'mixins', 'requires'],
|
|
Loader;
|
|
|
|
Loader = Ext.Loader = {
|
|
|
|
documentHead: typeof document !== 'undefined' && (document.head || document.getElementsByTagName('head')[0]),
|
|
|
|
|
|
isLoading: false,
|
|
|
|
|
|
queue: [],
|
|
|
|
|
|
isFileLoaded: {},
|
|
|
|
|
|
readyListeners: [],
|
|
|
|
|
|
optionalRequires: [],
|
|
|
|
|
|
requiresMap: {},
|
|
|
|
|
|
numPendingFiles: 0,
|
|
|
|
|
|
numLoadedFiles: 0,
|
|
|
|
|
|
hasFileLoadError: false,
|
|
|
|
|
|
classNameToFilePathMap: {},
|
|
|
|
|
|
history: [],
|
|
|
|
|
|
config: {
|
|
|
|
enabled: false,
|
|
|
|
|
|
disableCaching: true,
|
|
|
|
|
|
disableCachingParam: '_dc',
|
|
|
|
|
|
paths: {
|
|
'Ext': '.'
|
|
}
|
|
},
|
|
|
|
|
|
setConfig: function(name, value) {
|
|
if (Ext.isObject(name) && arguments.length === 1) {
|
|
Ext.Object.merge(this.config, name);
|
|
}
|
|
else {
|
|
this.config[name] = (Ext.isObject(value)) ? Ext.Object.merge(this.config[name], value) : value;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
getConfig: function(name) {
|
|
if (name) {
|
|
return this.config[name];
|
|
}
|
|
|
|
return this.config;
|
|
},
|
|
|
|
|
|
setPath: flexSetter(function(name, path) {
|
|
this.config.paths[name] = path;
|
|
|
|
return this;
|
|
}),
|
|
|
|
|
|
getPath: function(className) {
|
|
var path = '',
|
|
paths = this.config.paths,
|
|
prefix = this.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(/\/\.\//g, '/') + className.replace(/\./g, "/") + '.js';
|
|
},
|
|
|
|
|
|
getPrefix: function(className) {
|
|
var paths = this.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;
|
|
},
|
|
|
|
|
|
refreshQueue: function() {
|
|
var ln = this.queue.length,
|
|
i, item, j, requires;
|
|
|
|
if (ln === 0) {
|
|
this.triggerReady();
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
item = this.queue[i];
|
|
|
|
if (item) {
|
|
requires = item.requires;
|
|
|
|
|
|
|
|
if (requires.length > this.numLoadedFiles) {
|
|
continue;
|
|
}
|
|
|
|
j = 0;
|
|
|
|
do {
|
|
if (Manager.isCreated(requires[j])) {
|
|
|
|
Ext.Array.erase(requires, j, 1);
|
|
}
|
|
else {
|
|
j++;
|
|
}
|
|
} while (j < requires.length);
|
|
|
|
if (item.requires.length === 0) {
|
|
Ext.Array.erase(this.queue, i, 1);
|
|
item.callback.call(item.scope);
|
|
this.refreshQueue();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
injectScriptElement: function(url, onLoad, onError, scope) {
|
|
var script = document.createElement('script'),
|
|
me = this,
|
|
onLoadFn = function() {
|
|
me.cleanupScriptElement(script);
|
|
onLoad.call(scope);
|
|
},
|
|
onErrorFn = function() {
|
|
me.cleanupScriptElement(script);
|
|
onError.call(scope);
|
|
};
|
|
|
|
script.type = 'text/javascript';
|
|
script.src = url;
|
|
script.onload = onLoadFn;
|
|
script.onerror = onErrorFn;
|
|
script.onreadystatechange = function() {
|
|
if (this.readyState === 'loaded' || this.readyState === 'complete') {
|
|
onLoadFn();
|
|
}
|
|
};
|
|
|
|
this.documentHead.appendChild(script);
|
|
|
|
return script;
|
|
},
|
|
|
|
|
|
cleanupScriptElement: function(script) {
|
|
script.onload = null;
|
|
script.onreadystatechange = null;
|
|
script.onerror = null;
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
loadScriptFile: function(url, onLoad, onError, scope, synchronous) {
|
|
var me = this,
|
|
noCacheUrl = url + (this.getConfig('disableCaching') ? ('?' + this.getConfig('disableCachingParam') + '=' + Ext.Date.now()) : ''),
|
|
fileName = url.split('/').pop(),
|
|
isCrossOriginRestricted = false,
|
|
xhr, status, onScriptError;
|
|
|
|
scope = scope || this;
|
|
|
|
this.isLoading = true;
|
|
|
|
if (!synchronous) {
|
|
onScriptError = function() {
|
|
onError.call(scope, "Failed loading '" + url + "', please verify that the file exists", synchronous);
|
|
};
|
|
|
|
if (!Ext.isReady && Ext.onDocumentReady) {
|
|
Ext.onDocumentReady(function() {
|
|
me.injectScriptElement(noCacheUrl, onLoad, onScriptError, scope);
|
|
});
|
|
}
|
|
else {
|
|
this.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;
|
|
|
|
if (!isCrossOriginRestricted) {
|
|
isCrossOriginRestricted = (status === 0);
|
|
}
|
|
|
|
if (isCrossOriginRestricted
|
|
) {
|
|
onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; It's likely that the file is either " +
|
|
"being loaded from a different domain or from the local file system whereby cross origin " +
|
|
"requests are not allowed due to security reasons. Use asynchronous loading with " +
|
|
"Ext.require instead.", synchronous);
|
|
}
|
|
else if (status >= 200 && status < 300
|
|
) {
|
|
|
|
new Function(xhr.responseText + "\n//@ sourceURL=" + fileName)();
|
|
|
|
onLoad.call(scope);
|
|
}
|
|
else {
|
|
onError.call(this, "Failed loading synchronously via XHR: '" + url + "'; please " +
|
|
"verify that the file exists. " +
|
|
"XHR status code: " + status, synchronous);
|
|
}
|
|
|
|
|
|
xhr = null;
|
|
}
|
|
},
|
|
|
|
|
|
exclude: function(excludes) {
|
|
var me = this;
|
|
|
|
return {
|
|
require: function(expressions, fn, scope) {
|
|
return me.require(expressions, fn, scope, excludes);
|
|
},
|
|
|
|
syncRequire: function(expressions, fn, scope) {
|
|
return me.syncRequire(expressions, fn, scope, excludes);
|
|
}
|
|
};
|
|
},
|
|
|
|
|
|
syncRequire: function() {
|
|
this.syncModeEnabled = true;
|
|
this.require.apply(this, arguments);
|
|
this.refreshQueue();
|
|
this.syncModeEnabled = false;
|
|
},
|
|
|
|
|
|
require: function(expressions, fn, scope, excludes) {
|
|
var filePath, expression, exclude, className, excluded = {},
|
|
excludedClassNames = [],
|
|
possibleClassNames = [],
|
|
possibleClassName, classNames = [],
|
|
i, j, ln, subLn;
|
|
|
|
expressions = Ext.Array.from(expressions);
|
|
excludes = Ext.Array.from(excludes);
|
|
|
|
fn = fn || Ext.emptyFn;
|
|
|
|
scope = scope || Ext.global;
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0, ln = expressions.length; i < ln; i++) {
|
|
expression = expressions[i];
|
|
|
|
if (typeof expression === 'string' && expression.length > 0) {
|
|
possibleClassNames = Manager.getNamesByExpression(expression);
|
|
|
|
for (j = 0, subLn = possibleClassNames.length; j < subLn; j++) {
|
|
possibleClassName = possibleClassNames[j];
|
|
|
|
if (!excluded.hasOwnProperty(possibleClassName) && !Manager.isCreated(possibleClassName)) {
|
|
Ext.Array.include(classNames, possibleClassName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!this.config.enabled) {
|
|
if (classNames.length > 0) {
|
|
Ext.Error.raise({
|
|
sourceClass: "Ext.Loader",
|
|
sourceMethod: "require",
|
|
msg: "Ext.Loader is not enabled, so dependencies cannot be resolved dynamically. " +
|
|
"Missing required class" + ((classNames.length > 1) ? "es" : "") + ": " + classNames.join(', ')
|
|
});
|
|
}
|
|
}
|
|
|
|
if (classNames.length === 0) {
|
|
fn.call(scope);
|
|
return this;
|
|
}
|
|
|
|
this.queue.push({
|
|
requires: classNames,
|
|
callback: fn,
|
|
scope: scope
|
|
});
|
|
|
|
classNames = classNames.slice();
|
|
|
|
for (i = 0, ln = classNames.length; i < ln; i++) {
|
|
className = classNames[i];
|
|
|
|
if (!this.isFileLoaded.hasOwnProperty(className)) {
|
|
this.isFileLoaded[className] = false;
|
|
|
|
filePath = this.getPath(className);
|
|
|
|
this.classNameToFilePathMap[className] = filePath;
|
|
|
|
this.numPendingFiles++;
|
|
|
|
this.loadScriptFile(
|
|
filePath,
|
|
Ext.Function.pass(this.onFileLoaded, [className, filePath], this),
|
|
Ext.Function.pass(this.onFileLoadError, [className, filePath]),
|
|
this,
|
|
this.syncModeEnabled
|
|
);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
onFileLoaded: function(className, filePath) {
|
|
this.numLoadedFiles++;
|
|
|
|
this.isFileLoaded[className] = true;
|
|
|
|
this.numPendingFiles--;
|
|
|
|
if (this.numPendingFiles === 0) {
|
|
this.refreshQueue();
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
onFileLoadError: function(className, filePath, errorMessage, isSynchronous) {
|
|
this.numPendingFiles--;
|
|
this.hasFileLoadError = true;
|
|
|
|
},
|
|
|
|
|
|
addOptionalRequires: function(requires) {
|
|
var optionalRequires = this.optionalRequires,
|
|
i, ln, require;
|
|
|
|
requires = Ext.Array.from(requires);
|
|
|
|
for (i = 0, ln = requires.length; i < ln; i++) {
|
|
require = requires[i];
|
|
|
|
Ext.Array.include(optionalRequires, require);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
triggerReady: function(force) {
|
|
var readyListeners = this.readyListeners,
|
|
optionalRequires, listener;
|
|
|
|
if (this.isLoading || force) {
|
|
this.isLoading = false;
|
|
|
|
if (this.optionalRequires.length) {
|
|
|
|
optionalRequires = Ext.Array.clone(this.optionalRequires);
|
|
|
|
|
|
this.optionalRequires.length = 0;
|
|
|
|
this.require(optionalRequires, Ext.Function.pass(this.triggerReady, [true], this), this);
|
|
return this;
|
|
}
|
|
|
|
while (readyListeners.length) {
|
|
listener = readyListeners.shift();
|
|
listener.fn.call(listener.scope);
|
|
|
|
if (this.isLoading) {
|
|
return this;
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
onReady: function(fn, scope, withDomReady, options) {
|
|
var oldFn;
|
|
|
|
if (withDomReady !== false && Ext.onDocumentReady) {
|
|
oldFn = fn;
|
|
|
|
fn = function() {
|
|
Ext.onDocumentReady(oldFn, scope, options);
|
|
};
|
|
}
|
|
|
|
if (!this.isLoading) {
|
|
fn.call(scope);
|
|
}
|
|
else {
|
|
this.readyListeners.push({
|
|
fn: fn,
|
|
scope: scope
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
historyPush: function(className) {
|
|
if (className && this.isFileLoaded.hasOwnProperty(className)) {
|
|
Ext.Array.include(this.history, className);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
};
|
|
|
|
|
|
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, continueFn) {
|
|
var me = this,
|
|
dependencies = [],
|
|
className = Manager.getName(cls),
|
|
i, j, ln, subLn, value, propertyName, propertyValue;
|
|
|
|
|
|
|
|
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);
|
|
});
|
|
|
|
return false;
|
|
}, true);
|
|
|
|
Class.setDefaultPreprocessorPosition('loader', 'after', 'className');
|
|
|
|
|
|
Manager.registerPostprocessor('uses', function(name, cls, data) {
|
|
var uses = Ext.Array.from(data.uses),
|
|
items = [],
|
|
i, ln, item;
|
|
|
|
for (i = 0, ln = uses.length; i < ln; i++) {
|
|
item = uses[i];
|
|
|
|
if (typeof item === 'string') {
|
|
items.push(item);
|
|
}
|
|
}
|
|
|
|
Loader.addOptionalRequires(items);
|
|
});
|
|
|
|
Manager.setDefaultPostprocessorPosition('uses', 'last');
|
|
|
|
})(Ext.ClassManager, Ext.Class, Ext.Function.flexSetter, Ext.Function.alias);
|
|
|
|
|
|
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;
|
|
|
|
if (method) {
|
|
if (method.$name) {
|
|
err.sourceMethod = method.$name;
|
|
}
|
|
if (method.$owner) {
|
|
err.sourceClass = method.$owner.$className;
|
|
}
|
|
}
|
|
|
|
if (Ext.Error.handle(err) !== true) {
|
|
var 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.className ? me.className : '',
|
|
methodName = me.methodName ? '.' + me.methodName + '(): ' : '',
|
|
msg = me.msg || '(No description provided)';
|
|
|
|
return className + methodName + msg;
|
|
}
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ext.JSON = new(function() {
|
|
var useHasOwn = !! {}.hasOwnProperty,
|
|
isNative = function() {
|
|
var useNative = null;
|
|
|
|
return 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) {
|
|
if (!Ext.isDefined(o) || o === null) {
|
|
return "null";
|
|
} else if (Ext.isArray(o)) {
|
|
return encodeArray(o);
|
|
} else if (Ext.isDate(o)) {
|
|
return Ext.JSON.encodeDate(o);
|
|
} else if (Ext.isString(o)) {
|
|
return encodeString(o);
|
|
} else if (typeof o == "number") {
|
|
|
|
return isFinite(o) ? String(o) : "null";
|
|
} else if (Ext.isBoolean(o)) {
|
|
return String(o);
|
|
} else if (Ext.isObject(o)) {
|
|
return encodeObject(o);
|
|
} 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) {
|
|
var a = ["[", ""],
|
|
|
|
len = o.length,
|
|
i;
|
|
for (i = 0; i < len; i += 1) {
|
|
a.push(doEncode(o[i]), ',');
|
|
}
|
|
|
|
a[a.length - 1] = ']';
|
|
return a.join("");
|
|
},
|
|
encodeObject = function(o) {
|
|
var a = ["{", ""],
|
|
|
|
i;
|
|
for (i in o) {
|
|
if (!useHasOwn || o.hasOwnProperty(i)) {
|
|
a.push(doEncode(i), ":", doEncode(o[i]), ',');
|
|
}
|
|
}
|
|
|
|
a[a.length - 1] = '}';
|
|
return a.join("");
|
|
};
|
|
|
|
|
|
this.encodeDate = function(o) {
|
|
return '"' + o.getFullYear() + "-"
|
|
+ pad(o.getMonth() + 1) + "-"
|
|
+ pad(o.getDate()) + "T"
|
|
+ pad(o.getHours()) + ":"
|
|
+ pad(o.getMinutes()) + ":"
|
|
+ pad(o.getSeconds()) + '"';
|
|
};
|
|
|
|
|
|
this.encode = function() {
|
|
var ec;
|
|
return function(o) {
|
|
if (!ec) {
|
|
|
|
ec = isNative() ? JSON.stringify : doEncode;
|
|
}
|
|
return ec(o);
|
|
};
|
|
}();
|
|
|
|
|
|
|
|
this.decode = function() {
|
|
var dc;
|
|
return function(json, safe) {
|
|
if (!dc) {
|
|
|
|
dc = isNative() ? JSON.parse : doDecode;
|
|
}
|
|
try {
|
|
return dc(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,
|
|
|
|
|
|
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) {
|
|
if (!me.uniqueGlobalNamespace) {
|
|
me.getUniqueGlobalNamespace();
|
|
}
|
|
sandboxPrefix = me.uniqueGlobalNamespace + '-';
|
|
}
|
|
el.id = sandboxPrefix + (prefix || "ext-gen") + (++Ext.idSeed);
|
|
}
|
|
return el.id;
|
|
},
|
|
|
|
|
|
getBody: function() {
|
|
return Ext.get(document.body || false);
|
|
},
|
|
|
|
|
|
getHead: function() {
|
|
var head;
|
|
|
|
return function() {
|
|
if (head == undefined) {
|
|
head = Ext.get(document.getElementsByTagName("head")[0]);
|
|
}
|
|
|
|
return head;
|
|
};
|
|
}(),
|
|
|
|
|
|
getDoc: function() {
|
|
return Ext.get(document);
|
|
},
|
|
|
|
|
|
getCmp: function(id) {
|
|
return Ext.ComponentManager.get(id);
|
|
},
|
|
|
|
|
|
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 (Ext.isFunction(arg.destroy)) {
|
|
arg.destroy();
|
|
}
|
|
else if (arg.dom) {
|
|
arg.remove();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
callback: function(callback, scope, args, delay){
|
|
if(Ext.isFunction(callback)){
|
|
args = args || [];
|
|
scope = scope || window;
|
|
if (delay) {
|
|
Ext.defer(callback, delay, scope, args);
|
|
} else {
|
|
callback.apply(scope, args);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
htmlEncode : function(value) {
|
|
return Ext.String.htmlEncode(value);
|
|
},
|
|
|
|
|
|
htmlDecode : function(value) {
|
|
return Ext.String.htmlDecode(value);
|
|
},
|
|
|
|
|
|
urlAppend : function(url, s) {
|
|
if (!Ext.isEmpty(s)) {
|
|
return url + (url.indexOf('?') === -1 ? '?' : '&') + s;
|
|
}
|
|
return url;
|
|
}
|
|
});
|
|
|
|
|
|
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 = isSafari && check(/version\/5/),
|
|
isIE = !isOpera && check(/msie/),
|
|
isIE7 = isIE && (check(/msie 7/) || docMode == 7),
|
|
isIE8 = isIE && (check(/msie 8/) && docMode != 7 && docMode != 9 || docMode == 8),
|
|
isIE9 = isIE && (check(/msie 9/) && docMode != 7 && docMode != 8 || docMode == 9),
|
|
isIE6 = isIE && check(/msie 6/),
|
|
isGecko = !isWebKit && check(/gecko/),
|
|
isGecko3 = isGecko && check(/rv:1\.9/),
|
|
isGecko4 = isGecko && check(/rv:2\.0/),
|
|
isGecko5 = isGecko && check(/rv:5\./),
|
|
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);
|
|
|
|
|
|
try {
|
|
document.execCommand("BackgroundImageCache", false, true);
|
|
} catch(e) {}
|
|
|
|
|
|
Ext.setVersion('extjs', '4.0.7');
|
|
Ext.apply(Ext, {
|
|
|
|
SSL_SECURE_URL : isSecure && isIE ? 'javascript:""' : 'about:blank',
|
|
|
|
|
|
|
|
|
|
scopeResetCSS : Ext.buildSettings.scopeResetCSS,
|
|
|
|
|
|
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 = document.getElementById(el);
|
|
|
|
|
|
if (e && isIE && strict) {
|
|
if (el == e.getAttribute('id')) {
|
|
return e;
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
return e;
|
|
} else {
|
|
return el;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
removeNode : isIE6 || isIE7 ? function() {
|
|
var d;
|
|
return function(n){
|
|
if(n && n.tagName != 'BODY'){
|
|
(Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
|
|
d = d || document.createElement('div');
|
|
d.appendChild(n);
|
|
d.innerHTML = '';
|
|
delete Ext.cache[n.id];
|
|
}
|
|
};
|
|
}() : function(n) {
|
|
if (n && n.parentNode && n.tagName != 'BODY') {
|
|
(Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
|
|
n.parentNode.removeChild(n);
|
|
delete Ext.cache[n.id];
|
|
}
|
|
},
|
|
|
|
isStrict: isStrict,
|
|
|
|
isIEQuirks: isIE && !isStrict,
|
|
|
|
|
|
isOpera : isOpera,
|
|
|
|
|
|
isOpera10_5 : isOpera10_5,
|
|
|
|
|
|
isWebKit : isWebKit,
|
|
|
|
|
|
isChrome : isChrome,
|
|
|
|
|
|
isSafari : isSafari,
|
|
|
|
|
|
isSafari3 : isSafari3,
|
|
|
|
|
|
isSafari4 : isSafari4,
|
|
|
|
|
|
isSafari5 : isSafari5,
|
|
|
|
|
|
isSafari2 : isSafari2,
|
|
|
|
|
|
isIE : isIE,
|
|
|
|
|
|
isIE6 : isIE6,
|
|
|
|
|
|
isIE7 : isIE7,
|
|
|
|
|
|
isIE8 : isIE8,
|
|
|
|
|
|
isIE9 : isIE9,
|
|
|
|
|
|
isGecko : isGecko,
|
|
|
|
|
|
isGecko3 : isGecko3,
|
|
|
|
|
|
isGecko4 : isGecko4,
|
|
|
|
|
|
isGecko5 : isGecko5,
|
|
|
|
|
|
isFF3_0 : isFF3_0,
|
|
|
|
|
|
isFF3_5 : isFF3_5,
|
|
|
|
|
|
isFF3_6 : isFF3_6,
|
|
|
|
|
|
isFF4 : 4 <= firefoxVersion && firefoxVersion < 5,
|
|
|
|
|
|
isFF5 : 5 <= firefoxVersion && firefoxVersion < 6,
|
|
|
|
|
|
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 0;
|
|
}
|
|
|
|
if(force === true || scrollbarSize === null){
|
|
|
|
|
|
|
|
var cssClass = Ext.isIE9 ? '' : Ext.baseCSSPrefix + 'hide-offsets',
|
|
|
|
div = Ext.getBody().createChild('<div class="' + cssClass + '" style="width:100px;height:50px;overflow:hidden;"><div style="height:200px;"></div></div>'),
|
|
child = div.child('div', true),
|
|
w1 = child.offsetWidth;
|
|
|
|
div.setStyle('overflow', (Ext.isWebKit || Ext.isGecko) ? 'auto' : 'scroll');
|
|
|
|
var w2 = child.offsetWidth, width = w1 - w2;
|
|
div.remove();
|
|
|
|
|
|
scrollbarSize = { width: width, height: width };
|
|
}
|
|
|
|
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]/);
|
|
}
|
|
Ext.each(names, function(name){
|
|
if(usePrototypeKeys || source.hasOwnProperty(name)){
|
|
dest[name] = source[name];
|
|
}
|
|
}, this);
|
|
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 :
|
|
Ext.emptyFn,
|
|
|
|
|
|
partition : function(arr, truth){
|
|
var ret = [[],[]];
|
|
Ext.each(arr, function(v, i, a) {
|
|
ret[ (truth && truth(v, i, a)) || (!truth && v) ? 0 : 1].push(v);
|
|
});
|
|
return ret;
|
|
},
|
|
|
|
|
|
invoke : function(arr, methodName){
|
|
var ret = [],
|
|
args = Array.prototype.slice.call(arguments, 2);
|
|
Ext.each(arr, function(v,i) {
|
|
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 = [];
|
|
|
|
for (var i = 0; i < len; i++) {
|
|
ret[i] = [];
|
|
if(fn){
|
|
ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
|
|
}else{
|
|
for (var j = 0, aLen = arrs.length; j < aLen; j++){
|
|
ret[i].push( arrs[j][i] );
|
|
}
|
|
}
|
|
}
|
|
return ret;
|
|
},
|
|
|
|
|
|
toSentence: function(items, connector) {
|
|
var length = items.length;
|
|
|
|
if (length <= 1) {
|
|
return items[0];
|
|
} else {
|
|
var head = items.slice(0, length - 1),
|
|
tail = items[length - 1];
|
|
|
|
return Ext.util.Format.format("{0} {1} {2}", head.join(", "), connector || 'and', tail);
|
|
}
|
|
},
|
|
|
|
|
|
useShims: isIE6
|
|
});
|
|
})();
|
|
|
|
|
|
Ext.application = function(config) {
|
|
Ext.require('Ext.app.Application');
|
|
|
|
Ext.onReady(function() {
|
|
Ext.create('Ext.app.Application', config);
|
|
});
|
|
};
|
|
|
|
|
|
(function() {
|
|
Ext.ns('Ext.util');
|
|
|
|
Ext.util.Format = {};
|
|
var UtilFormat = Ext.util.Format,
|
|
stripTagsRE = /<\/?[^>]+>/gi,
|
|
stripScriptsRe = /(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig,
|
|
nl2brRe = /\r?\n/g,
|
|
|
|
|
|
formatCleanRe = /[^\d\.]/g,
|
|
|
|
|
|
|
|
I18NFormatCleanRe;
|
|
|
|
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 : 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 = decimals || UtilFormat.currencyPrecision;
|
|
format += 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(size) {
|
|
if (size < 1024) {
|
|
return size + " bytes";
|
|
} else if (size < 1048576) {
|
|
return (Math.round(((size*10) / 1024))/10) + " KB";
|
|
} else {
|
|
return (Math.round(((size*10) / 1048576))/10) + " MB";
|
|
}
|
|
},
|
|
|
|
|
|
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;
|
|
}
|
|
v = Ext.Number.from(v, NaN);
|
|
if (isNaN(v)) {
|
|
return '';
|
|
}
|
|
var comma = UtilFormat.thousandSeparator,
|
|
dec = UtilFormat.decimalSeparator,
|
|
i18n = false,
|
|
neg = v < 0,
|
|
hasComma,
|
|
psplit;
|
|
|
|
v = Math.abs(v);
|
|
|
|
|
|
|
|
|
|
|
|
if (formatString.substr(formatString.length - 2) == '/i') {
|
|
if (!I18NFormatCleanRe) {
|
|
I18NFormatCleanRe = new RegExp('[^\\d\\' + UtilFormat.decimalSeparator + ']','g');
|
|
}
|
|
formatString = formatString.substr(0, formatString.length - 2);
|
|
i18n = true;
|
|
hasComma = formatString.indexOf(comma) != -1;
|
|
psplit = formatString.replace(I18NFormatCleanRe, '').split(dec);
|
|
} else {
|
|
hasComma = formatString.indexOf(',') != -1;
|
|
psplit = formatString.replace(formatCleanRe, '').split('.');
|
|
}
|
|
|
|
if (1 < psplit.length) {
|
|
v = v.toFixed(psplit[1].length);
|
|
} else if(2 < psplit.length) {
|
|
} else {
|
|
v = v.toFixed(0);
|
|
}
|
|
|
|
var fnum = v.toString();
|
|
|
|
psplit = fnum.split('.');
|
|
|
|
if (hasComma) {
|
|
var cnum = psplit[0],
|
|
parr = [],
|
|
j = cnum.length,
|
|
m = Math.floor(j / 3),
|
|
n = cnum.length % 3 || 3,
|
|
i;
|
|
|
|
for (i = 0; i < j; i += n) {
|
|
if (i !== 0) {
|
|
n = 3;
|
|
}
|
|
|
|
parr[parr.length] = cnum.substr(i, n);
|
|
m -= 1;
|
|
}
|
|
fnum = parr.join(comma);
|
|
if (psplit[1]) {
|
|
fnum += dec + psplit[1];
|
|
}
|
|
} else {
|
|
if (psplit[1]) {
|
|
fnum = psplit[0] + dec + psplit[1];
|
|
}
|
|
}
|
|
|
|
if (neg) {
|
|
|
|
neg = fnum.replace(/[^1-9]/g, '') !== '';
|
|
}
|
|
|
|
return (neg ? '-' : '') + formatString.replace(/[\d,?\.?]+/, fnum);
|
|
},
|
|
|
|
|
|
numberRenderer : function(format) {
|
|
return function(v) {
|
|
return UtilFormat.number(v, format);
|
|
};
|
|
},
|
|
|
|
|
|
plural : function(v, s, p) {
|
|
return v +' ' + (v == 1 ? s : (p ? p : s+'s'));
|
|
},
|
|
|
|
|
|
nl2br : function(v) {
|
|
return Ext.isEmpty(v) ? '' : v.replace(nl2brRe, '<br/>');
|
|
},
|
|
|
|
|
|
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) {
|
|
if (Ext.isNumber(box)) {
|
|
box = box.toString();
|
|
}
|
|
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.ns('Ext.util');
|
|
|
|
Ext.util.TaskRunner = function(interval) {
|
|
interval = interval || 10;
|
|
var tasks = [],
|
|
removeQueue = [],
|
|
id = 0,
|
|
running = false,
|
|
|
|
|
|
stopThread = function() {
|
|
running = false;
|
|
clearInterval(id);
|
|
id = 0;
|
|
},
|
|
|
|
|
|
startThread = function() {
|
|
if (!running) {
|
|
running = true;
|
|
id = setInterval(runTasks, interval);
|
|
}
|
|
},
|
|
|
|
|
|
removeTask = function(t) {
|
|
removeQueue.push(t);
|
|
if (t.onStop) {
|
|
t.onStop.apply(t.scope || t);
|
|
}
|
|
},
|
|
|
|
|
|
runTasks = function() {
|
|
var rqLen = removeQueue.length,
|
|
now = new Date().getTime(),
|
|
i;
|
|
|
|
if (rqLen > 0) {
|
|
for (i = 0; i < rqLen; i++) {
|
|
Ext.Array.remove(tasks, removeQueue[i]);
|
|
}
|
|
removeQueue = [];
|
|
if (tasks.length < 1) {
|
|
stopThread();
|
|
return;
|
|
}
|
|
}
|
|
i = 0;
|
|
var t,
|
|
itime,
|
|
rt,
|
|
len = tasks.length;
|
|
for (; i < len; ++i) {
|
|
t = tasks[i];
|
|
itime = now - t.taskRunTime;
|
|
if (t.interval <= itime) {
|
|
rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
|
|
t.taskRunTime = now;
|
|
if (rt === false || t.taskRunCount === t.repeat) {
|
|
removeTask(t);
|
|
return;
|
|
}
|
|
}
|
|
if (t.duration && t.duration <= (now - t.taskStartTime)) {
|
|
removeTask(t);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
this.start = function(task) {
|
|
tasks.push(task);
|
|
task.taskStartTime = new Date().getTime();
|
|
task.taskRunTime = 0;
|
|
task.taskRunCount = 0;
|
|
startThread();
|
|
return task;
|
|
};
|
|
|
|
|
|
this.stop = function(task) {
|
|
removeTask(task);
|
|
return task;
|
|
};
|
|
|
|
|
|
this.stopAll = function() {
|
|
stopThread();
|
|
for (var i = 0, len = tasks.length; i < len; i++) {
|
|
if (tasks[i].onStop) {
|
|
tasks[i].onStop();
|
|
}
|
|
}
|
|
tasks = [];
|
|
removeQueue = [];
|
|
};
|
|
};
|
|
|
|
|
|
Ext.TaskManager = Ext.create('Ext.util.TaskRunner');
|
|
|
|
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();
|
|
|
|
|
|
Ext.supports = {
|
|
init : function() {
|
|
var doc = document,
|
|
div = doc.createElement('div'),
|
|
tests = this.tests,
|
|
ln = tests.length,
|
|
i, test;
|
|
|
|
div.innerHTML = [
|
|
'<div style="height:30px;width:50px;">',
|
|
'<div style="height:20px;width:20px;"></div>',
|
|
'</div>',
|
|
'<div style="width: 200px; height: 200px; position: relative; padding: 5px;">',
|
|
'<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"></div>',
|
|
'</div>',
|
|
'<div style="float:left; background-color:transparent;"></div>'
|
|
].join('');
|
|
|
|
doc.body.appendChild(div);
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
test = tests[i];
|
|
this[test.identity] = test.fn.call(this, doc, div);
|
|
}
|
|
|
|
doc.body.removeChild(div);
|
|
},
|
|
|
|
|
|
CSS3BoxShadow: Ext.isDefined(document.documentElement.style.boxShadow),
|
|
|
|
|
|
ClassList: !!document.documentElement.classList,
|
|
|
|
|
|
OrientationChange: ((typeof window.orientation != 'undefined') && ('onorientationchange' in window)),
|
|
|
|
|
|
DeviceMotion: ('ondevicemotion' in window),
|
|
|
|
|
|
|
|
|
|
Touch: ('ontouchstart' in window) && (!Ext.is.Desktop),
|
|
|
|
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;
|
|
div = Ext.get(div);
|
|
for (; i < ln; i++) {
|
|
if (div.getStyle(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',
|
|
fn: function() {
|
|
var webKitVersion = Ext.webKitVersion;
|
|
|
|
return 0 < webKitVersion && webKitVersion < 533;
|
|
}
|
|
},
|
|
|
|
|
|
{
|
|
identity: 'DisplayChangeTextAreaSelectionBug',
|
|
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 = "<!--[if vml]><br><br><![endif]-->";
|
|
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() {
|
|
return !!(window.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,
|
|
options = [property + webkit, property + w3c, property + moz];
|
|
|
|
div.style.cssText = options.join(';');
|
|
|
|
return ("" + div.style.backgroundImage).indexOf('gradient') !== -1;
|
|
}
|
|
},
|
|
|
|
|
|
{
|
|
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' && typeof navigator.geolocation != 'undefined') || (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);
|
|
}
|
|
},
|
|
|
|
{
|
|
identity: 'BoundingClientRect',
|
|
fn: function(doc, div) {
|
|
return Ext.isFunction(div.getBoundingClientRect);
|
|
}
|
|
},
|
|
{
|
|
identity: 'IncludePaddingInWidthCalculation',
|
|
fn: function(doc, div){
|
|
var el = Ext.get(div.childNodes[1].firstChild);
|
|
return el.getWidth() == 210;
|
|
}
|
|
},
|
|
{
|
|
identity: 'IncludePaddingInHeightCalculation',
|
|
fn: function(doc, div){
|
|
var el = Ext.get(div.childNodes[1].firstChild);
|
|
return el.getHeight() == 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;
|
|
}
|
|
}
|
|
]
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Ext.ns('Ext.core');
|
|
Ext.core.DomHelper = Ext.DomHelper = function(){
|
|
var tempTableEl = null,
|
|
emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,
|
|
tableRe = /^table|tbody|tr|td$/i,
|
|
confRe = /tag|children|cn|html$/i,
|
|
tableElRe = /td|tr|tbody/i,
|
|
endRe = /end/i,
|
|
pub,
|
|
|
|
afterbegin = 'afterbegin',
|
|
afterend = 'afterend',
|
|
beforebegin = 'beforebegin',
|
|
beforeend = 'beforeend',
|
|
ts = '<table>',
|
|
te = '</table>',
|
|
tbs = ts+'<tbody>',
|
|
tbe = '</tbody>'+te,
|
|
trs = tbs + '<tr>',
|
|
tre = '</tr>'+tbe;
|
|
|
|
|
|
function doInsert(el, o, returnElement, pos, sibling, append){
|
|
el = Ext.getDom(el);
|
|
var newNode;
|
|
if (pub.useDom) {
|
|
newNode = createDom(o, null);
|
|
if (append) {
|
|
el.appendChild(newNode);
|
|
} else {
|
|
(sibling == 'firstChild' ? el : el.parentNode).insertBefore(newNode, el[sibling] || el);
|
|
}
|
|
} else {
|
|
newNode = Ext.DomHelper.insertHtml(pos, el, Ext.DomHelper.createHtml(o));
|
|
}
|
|
return returnElement ? Ext.get(newNode, true) : newNode;
|
|
}
|
|
|
|
function createDom(o, parentNode){
|
|
var el,
|
|
doc = document,
|
|
useSet,
|
|
attr,
|
|
val,
|
|
cn;
|
|
|
|
if (Ext.isArray(o)) {
|
|
el = doc.createDocumentFragment();
|
|
for (var i = 0, l = o.length; i < l; i++) {
|
|
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(!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)) {
|
|
createDom(cn, el);
|
|
} else if (o.html) {
|
|
el.innerHTML = o.html;
|
|
}
|
|
}
|
|
if(parentNode){
|
|
parentNode.appendChild(el);
|
|
}
|
|
return el;
|
|
}
|
|
|
|
|
|
function createHtml(o){
|
|
var b = '',
|
|
attr,
|
|
val,
|
|
key,
|
|
cn,
|
|
i;
|
|
|
|
if(typeof o == "string"){
|
|
b = o;
|
|
} else if (Ext.isArray(o)) {
|
|
for (i=0; i < o.length; i++) {
|
|
if(o[i]) {
|
|
b += createHtml(o[i]);
|
|
}
|
|
}
|
|
} else {
|
|
b += '<' + (o.tag = o.tag || 'div');
|
|
for (attr in o) {
|
|
val = o[attr];
|
|
if(!confRe.test(attr)){
|
|
if (typeof val == "object") {
|
|
b += ' ' + attr + '="';
|
|
for (key in val) {
|
|
b += key + ':' + val[key] + ';';
|
|
}
|
|
b += '"';
|
|
}else{
|
|
b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';
|
|
}
|
|
}
|
|
}
|
|
|
|
if (emptyTags.test(o.tag)) {
|
|
b += '/>';
|
|
} else {
|
|
b += '>';
|
|
if ((cn = o.children || o.cn)) {
|
|
b += createHtml(cn);
|
|
} else if(o.html){
|
|
b += o.html;
|
|
}
|
|
b += '</' + o.tag + '>';
|
|
}
|
|
}
|
|
return b;
|
|
}
|
|
|
|
function ieTable(depth, s, h, e){
|
|
tempTableEl.innerHTML = [s, h, e].join('');
|
|
var i = -1,
|
|
el = tempTableEl,
|
|
ns;
|
|
while(++i < depth){
|
|
el = el.firstChild;
|
|
}
|
|
|
|
ns = el.nextSibling;
|
|
if (ns){
|
|
var df = document.createDocumentFragment();
|
|
while(el){
|
|
ns = el.nextSibling;
|
|
df.appendChild(el);
|
|
el = ns;
|
|
}
|
|
el = df;
|
|
}
|
|
return el;
|
|
}
|
|
|
|
|
|
function insertIntoTable(tag, where, el, html) {
|
|
var node,
|
|
before;
|
|
|
|
tempTableEl = tempTableEl || document.createElement('div');
|
|
|
|
if(tag == 'td' && (where == afterbegin || where == beforeend) ||
|
|
!tableElRe.test(tag) && (where == beforebegin || where == afterend)) {
|
|
return null;
|
|
}
|
|
before = where == beforebegin ? el :
|
|
where == afterend ? el.nextSibling :
|
|
where == afterbegin ? el.firstChild : null;
|
|
|
|
if (where == beforebegin || where == afterend) {
|
|
el = el.parentNode;
|
|
}
|
|
|
|
if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {
|
|
node = ieTable(4, trs, html, tre);
|
|
} else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||
|
|
(tag == 'tr' && (where == beforebegin || where == afterend))) {
|
|
node = ieTable(3, tbs, html, tbe);
|
|
} else {
|
|
node = ieTable(2, ts, html, te);
|
|
}
|
|
el.insertBefore(node, before);
|
|
return node;
|
|
}
|
|
|
|
|
|
function createContextualFragment(html){
|
|
var div = document.createElement("div"),
|
|
fragment = document.createDocumentFragment(),
|
|
i = 0,
|
|
length, childNodes;
|
|
|
|
div.innerHTML = html;
|
|
childNodes = div.childNodes;
|
|
length = childNodes.length;
|
|
|
|
for (; i < length; i++) {
|
|
fragment.appendChild(childNodes[i].cloneNode(true));
|
|
}
|
|
|
|
return fragment;
|
|
}
|
|
|
|
pub = {
|
|
|
|
markup : function(o){
|
|
return createHtml(o);
|
|
},
|
|
|
|
|
|
applyStyles : function(el, styles){
|
|
if (styles) {
|
|
el = Ext.fly(el);
|
|
if (typeof styles == "function") {
|
|
styles = styles.call();
|
|
}
|
|
if (typeof styles == "string") {
|
|
styles = Ext.Element.parseStyles(styles);
|
|
}
|
|
if (typeof styles == "object") {
|
|
el.setStyle(styles);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
insertHtml : function(where, el, html){
|
|
var hash = {},
|
|
hashVal,
|
|
range,
|
|
rangeEl,
|
|
setStart,
|
|
frag,
|
|
rs;
|
|
|
|
where = where.toLowerCase();
|
|
|
|
hash[beforebegin] = ['BeforeBegin', 'previousSibling'];
|
|
hash[afterend] = ['AfterEnd', 'nextSibling'];
|
|
|
|
|
|
if (el.insertAdjacentHTML) {
|
|
if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){
|
|
return rs;
|
|
}
|
|
|
|
|
|
hash[afterbegin] = ['AfterBegin', 'firstChild'];
|
|
hash[beforeend] = ['BeforeEnd', 'lastChild'];
|
|
if ((hashVal = hash[where])) {
|
|
el.insertAdjacentHTML(hashVal[0], html);
|
|
return el[hashVal[1]];
|
|
}
|
|
|
|
} else {
|
|
|
|
if (Ext.isTextNode(el)) {
|
|
where = where === 'afterbegin' ? 'beforebegin' : where;
|
|
where = where === 'beforeend' ? 'afterend' : where;
|
|
}
|
|
range = Ext.supports.CreateContextualFragment ? el.ownerDocument.createRange() : undefined;
|
|
setStart = 'setStart' + (endRe.test(where) ? 'After' : 'Before');
|
|
if (hash[where]) {
|
|
if (range) {
|
|
range[setStart](el);
|
|
frag = range.createContextualFragment(html);
|
|
} else {
|
|
frag = 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 = createContextualFragment(html);
|
|
}
|
|
|
|
if(where == afterbegin){
|
|
el.insertBefore(frag, el.firstChild);
|
|
}else{
|
|
el.appendChild(frag);
|
|
}
|
|
} else {
|
|
el.innerHTML = html;
|
|
}
|
|
return el[rangeEl];
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
insertBefore : function(el, o, returnElement){
|
|
return doInsert(el, o, returnElement, beforebegin);
|
|
},
|
|
|
|
|
|
insertAfter : function(el, o, returnElement){
|
|
return doInsert(el, o, returnElement, afterend, 'nextSibling');
|
|
},
|
|
|
|
|
|
insertFirst : function(el, o, returnElement){
|
|
return doInsert(el, o, returnElement, afterbegin, 'firstChild');
|
|
},
|
|
|
|
|
|
append : function(el, o, returnElement){
|
|
return doInsert(el, o, returnElement, beforeend, '', true);
|
|
},
|
|
|
|
|
|
overwrite : function(el, o, returnElement){
|
|
el = Ext.getDom(el);
|
|
el.innerHTML = createHtml(o);
|
|
return returnElement ? Ext.get(el.firstChild) : el.firstChild;
|
|
},
|
|
|
|
createHtml : createHtml,
|
|
|
|
|
|
createDom: createDom,
|
|
|
|
|
|
useDom : false,
|
|
|
|
|
|
createTemplate : function(o){
|
|
var html = Ext.DomHelper.createHtml(o);
|
|
return Ext.create('Ext.Template', html);
|
|
}
|
|
};
|
|
return pub;
|
|
}();
|
|
|
|
|
|
|
|
Ext.ns('Ext.core');
|
|
|
|
Ext.core.DomQuery = Ext.DomQuery = function(){
|
|
var cache = {},
|
|
simpleCache = {},
|
|
valueCache = {},
|
|
nonSpace = /\S/,
|
|
trimRe = /^\s+|\s+$/g,
|
|
tplRe = /\{(\d+)\}/g,
|
|
modeRe = /^(\s?[\/>+~]\s?|\s|$)/,
|
|
tagTokenRe = /^(#)?([\w-\*]+)/,
|
|
nthRe = /(\d*)n\+?(\d*)/,
|
|
nthRe2 = /\D/,
|
|
startIdRe = /^\s*\#/,
|
|
|
|
|
|
|
|
isIE = window.ActiveXObject ? true : false,
|
|
key = 30803;
|
|
|
|
|
|
|
|
eval("var batch = 30803;");
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
function next(n){
|
|
while((n = n.nextSibling) && n.nodeType != 1);
|
|
return n;
|
|
}
|
|
|
|
|
|
function prev(n){
|
|
while((n = n.previousSibling) && n.nodeType != 1);
|
|
return n;
|
|
}
|
|
|
|
|
|
|
|
function children(parent){
|
|
var n = parent.firstChild,
|
|
nodeIndex = -1,
|
|
nextNode;
|
|
while(n){
|
|
nextNode = n.nextSibling;
|
|
|
|
if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
|
|
parent.removeChild(n);
|
|
}else{
|
|
|
|
n.nodeIndex = ++nodeIndex;
|
|
}
|
|
n = nextNode;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
|
|
|
|
|
|
function byClassName(nodeSet, cls){
|
|
if(!cls){
|
|
return nodeSet;
|
|
}
|
|
var result = [], ri = -1;
|
|
for(var i = 0, ci; ci = nodeSet[i]; i++){
|
|
if((' '+ci.className+' ').indexOf(cls) != -1){
|
|
result[++ri] = ci;
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
function attrValue(n, attr){
|
|
|
|
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];
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
function getNodes(ns, mode, tagName){
|
|
var result = [], ri = -1, cs;
|
|
if(!ns){
|
|
return result;
|
|
}
|
|
tagName = tagName || "*";
|
|
|
|
if(typeof ns.getElementsByTagName != "undefined"){
|
|
ns = [ns];
|
|
}
|
|
|
|
|
|
|
|
if(!mode){
|
|
for(var i = 0, ni; ni = ns[i]; i++){
|
|
cs = ni.getElementsByTagName(tagName);
|
|
for(var j = 0, ci; ci = cs[j]; j++){
|
|
result[++ri] = ci;
|
|
}
|
|
}
|
|
|
|
|
|
} else if(mode == "/" || mode == ">"){
|
|
var utag = tagName.toUpperCase();
|
|
for(var i = 0, ni, cn; ni = ns[i]; i++){
|
|
cn = ni.childNodes;
|
|
for(var j = 0, cj; cj = cn[j]; j++){
|
|
if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
|
|
result[++ri] = cj;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
}else if(mode == "+"){
|
|
var utag = tagName.toUpperCase();
|
|
for(var i = 0, n; 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 == "~"){
|
|
var utag = tagName.toUpperCase();
|
|
for(var i = 0, n; 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){
|
|
if(b.slice){
|
|
return a.concat(b);
|
|
}
|
|
for(var i = 0, l = b.length; i < l; i++){
|
|
a[a.length] = b[i];
|
|
}
|
|
return a;
|
|
}
|
|
|
|
function byTag(cs, tagName){
|
|
if(cs.tagName || cs == document){
|
|
cs = [cs];
|
|
}
|
|
if(!tagName){
|
|
return cs;
|
|
}
|
|
var result = [], ri = -1;
|
|
tagName = tagName.toLowerCase();
|
|
for(var i = 0, ci; ci = cs[i]; i++){
|
|
if(ci.nodeType == 1 && ci.tagName.toLowerCase() == tagName){
|
|
result[++ri] = ci;
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
function byId(cs, id){
|
|
if(cs.tagName || cs == document){
|
|
cs = [cs];
|
|
}
|
|
if(!id){
|
|
return cs;
|
|
}
|
|
var result = [], ri = -1;
|
|
for(var i = 0, ci; 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 = Ext.DomQuery.operators[op],
|
|
a,
|
|
xml,
|
|
hasXml;
|
|
|
|
for(var i = 0, ci; ci = cs[i]; i++){
|
|
|
|
if(ci.nodeType != 1){
|
|
continue;
|
|
}
|
|
|
|
if(!hasXml){
|
|
xml = Ext.DomQuery.isXml(ci);
|
|
hasXml = true;
|
|
}
|
|
|
|
|
|
if(!xml){
|
|
if(useGetStyle){
|
|
a = Ext.DomQuery.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){
|
|
return Ext.DomQuery.pseudos[name](cs, value);
|
|
}
|
|
|
|
function nodupIEXml(cs){
|
|
var d = ++key,
|
|
r;
|
|
cs[0].setAttribute("_nodup", d);
|
|
r = [cs[0]];
|
|
for(var i = 1, len = cs.length; i < len; i++){
|
|
var c = cs[i];
|
|
if(!c.getAttribute("_nodup") != d){
|
|
c.setAttribute("_nodup", d);
|
|
r[r.length] = c;
|
|
}
|
|
}
|
|
for(var 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;
|
|
if(!len || typeof cs.nodeType != "undefined" || len == 1){
|
|
return cs;
|
|
}
|
|
if(isIE && typeof cs[0].selectSingleNode != "undefined"){
|
|
return nodupIEXml(cs);
|
|
}
|
|
var d = ++key;
|
|
cs[0]._nodup = d;
|
|
for(i = 1; c = cs[i]; i++){
|
|
if(c._nodup != d){
|
|
c._nodup = d;
|
|
}else{
|
|
r = [];
|
|
for(var 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 = [];
|
|
for(var i = 0, len = c1.length; i < len; i++){
|
|
c1[i].setAttribute("_qdiff", d);
|
|
}
|
|
for(var i = 0, len = c2.length; i < len; i++){
|
|
if(c2[i].getAttribute("_qdiff") != d){
|
|
r[r.length] = c2[i];
|
|
}
|
|
}
|
|
for(var 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 = [];
|
|
if(!len1){
|
|
return c2;
|
|
}
|
|
if(isIE && typeof c1[0].selectSingleNode != "undefined"){
|
|
return quickDiffIEXml(c1, c2);
|
|
}
|
|
for(var i = 0; i < len1; i++){
|
|
c1[i]._qdiff = d;
|
|
}
|
|
for(var 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){
|
|
var d = root.ownerDocument || root;
|
|
return d.getElementById(id);
|
|
}
|
|
ns = getNodes(ns, mode, "*");
|
|
return byId(ns, id);
|
|
}
|
|
|
|
return {
|
|
getStyle : function(el, name){
|
|
return Ext.fly(el).getStyle(name);
|
|
},
|
|
|
|
compile : function(path, type){
|
|
type = type || "select";
|
|
|
|
|
|
var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"],
|
|
mode,
|
|
lastPath,
|
|
matchers = Ext.DomQuery.matchers,
|
|
matchersLn = matchers.length,
|
|
modeMatch,
|
|
|
|
lmode = path.match(modeRe);
|
|
|
|
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;
|
|
var 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))){
|
|
var matched = false;
|
|
for(var j = 0; j < matchersLn; j++){
|
|
var t = matchers[j];
|
|
var 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){
|
|
}
|
|
}
|
|
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 || document;
|
|
|
|
if(typeof root == "string"){
|
|
root = document.getElementById(root);
|
|
}
|
|
var paths = path.split(","),
|
|
results = [];
|
|
|
|
|
|
for(var i = 0, len = paths.length; i < len; i++){
|
|
var subPath = paths[i].replace(trimRe, "");
|
|
|
|
if(!cache[subPath]){
|
|
cache[subPath] = Ext.DomQuery.compile(subPath);
|
|
if(!cache[subPath]){
|
|
}
|
|
}
|
|
var result = cache[subPath](root);
|
|
if(result && result != document){
|
|
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 : document.querySelectorAll ? function(path, root, type) {
|
|
root = root || document;
|
|
|
|
if (!Ext.DomQuery.isXml(root) && !(Ext.isSafari3 && !Ext.isStrict)) {
|
|
try {
|
|
|
|
var isDocumentRoot = root.nodeType === 9,
|
|
_path = path,
|
|
_root = root;
|
|
|
|
if (!isDocumentRoot && path.indexOf(',') === -1 && !startIdRe.test(path)) {
|
|
_path = '#' + Ext.id(root) + ' ' + path;
|
|
_root = root.parentNode;
|
|
}
|
|
return Ext.Array.toArray(_root.querySelectorAll(_path));
|
|
}
|
|
catch (e) {
|
|
}
|
|
}
|
|
return Ext.DomQuery.jsSelect.call(this, path, root, type);
|
|
} : function(path, root, type) {
|
|
return Ext.DomQuery.jsSelect.call(this, path, root, type);
|
|
},
|
|
|
|
|
|
selectNode : function(path, root){
|
|
return Ext.DomQuery.select(path, root)[0];
|
|
},
|
|
|
|
|
|
selectValue : function(path, root, defaultValue){
|
|
path = path.replace(trimRe, "");
|
|
if(!valueCache[path]){
|
|
valueCache[path] = Ext.DomQuery.compile(path, "select");
|
|
}
|
|
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 = Ext.DomQuery.selectValue(path, root, defaultValue || 0);
|
|
return parseFloat(v);
|
|
},
|
|
|
|
|
|
is : function(el, ss){
|
|
if(typeof el == "string"){
|
|
el = document.getElementById(el);
|
|
}
|
|
var isArray = Ext.isArray(el),
|
|
result = Ext.DomQuery.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] = Ext.DomQuery.compile(ss, "simple");
|
|
}
|
|
var result = simpleCache[ss](els);
|
|
return nonMatches ? quickDiff(result, els) : result;
|
|
},
|
|
|
|
|
|
matchers : [{
|
|
re: /^\.([\w-]+)/,
|
|
select: '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;
|
|
for(var i = 0, ci; 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;
|
|
for(var i = 0, ci; 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;
|
|
for(var i = 0, n; n = c[i]; i++){
|
|
var pn = n.parentNode;
|
|
if (batch != pn._batch) {
|
|
var j = 0;
|
|
for(var 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;;
|
|
for(var i = 0, ci; ci = c[i]; i++){
|
|
if(!prev(ci) && !next(ci)){
|
|
r[++ri] = ci;
|
|
}
|
|
}
|
|
return r;
|
|
},
|
|
|
|
"empty" : function(c){
|
|
var r = [], ri = -1;
|
|
for(var i = 0, ci; ci = c[i]; i++){
|
|
var cns = ci.childNodes, j = 0, cn, 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;
|
|
for(var i = 0, ci; ci = c[i]; i++){
|
|
if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
|
|
r[++ri] = ci;
|
|
}
|
|
}
|
|
return r;
|
|
},
|
|
|
|
"nodeValue" : function(c, v){
|
|
var r = [], ri = -1;
|
|
for(var i = 0, ci; ci = c[i]; i++){
|
|
if(ci.firstChild && ci.firstChild.nodeValue == v){
|
|
r[++ri] = ci;
|
|
}
|
|
}
|
|
return r;
|
|
},
|
|
|
|
"checked" : function(c){
|
|
var r = [], ri = -1;
|
|
for(var i = 0, ci; ci = c[i]; i++){
|
|
if(ci.checked == true){
|
|
r[++ri] = ci;
|
|
}
|
|
}
|
|
return r;
|
|
},
|
|
|
|
"not" : function(c, ss){
|
|
return Ext.DomQuery.filter(c, ss, true);
|
|
},
|
|
|
|
"any" : function(c, selectors){
|
|
var ss = selectors.split('|'),
|
|
r = [], ri = -1, s;
|
|
for(var i = 0, ci; ci = c[i]; i++){
|
|
for(var j = 0; s = ss[j]; j++){
|
|
if(Ext.DomQuery.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 = Ext.DomQuery.select,
|
|
r = [], ri = -1;
|
|
for(var i = 0, ci; ci = c[i]; i++){
|
|
if(s(ss, ci).length > 0){
|
|
r[++ri] = ci;
|
|
}
|
|
}
|
|
return r;
|
|
},
|
|
|
|
"next" : function(c, ss){
|
|
var is = Ext.DomQuery.is,
|
|
r = [], ri = -1;
|
|
for(var i = 0, ci; ci = c[i]; i++){
|
|
var n = next(ci);
|
|
if(n && is(n, ss)){
|
|
r[++ri] = ci;
|
|
}
|
|
}
|
|
return r;
|
|
},
|
|
|
|
"prev" : function(c, ss){
|
|
var is = Ext.DomQuery.is,
|
|
r = [], ri = -1;
|
|
for(var i = 0, ci; ci = c[i]; i++){
|
|
var n = prev(ci);
|
|
if(n && is(n, ss)){
|
|
r[++ri] = ci;
|
|
}
|
|
}
|
|
return r;
|
|
}
|
|
}
|
|
};
|
|
}();
|
|
|
|
|
|
Ext.query = Ext.DomQuery.select;
|
|
|
|
|
|
(function() {
|
|
var DOC = document,
|
|
EC = Ext.cache;
|
|
|
|
Ext.Element = Ext.core.Element = function(element, forceNew) {
|
|
var dom = typeof element == "string" ? DOC.getElementById(element) : element,
|
|
id;
|
|
|
|
if (!dom) {
|
|
return null;
|
|
}
|
|
|
|
id = dom.id;
|
|
|
|
if (!forceNew && id && EC[id]) {
|
|
|
|
return EC[id].el;
|
|
}
|
|
|
|
|
|
this.dom = dom;
|
|
|
|
|
|
this.id = id || Ext.id(dom);
|
|
};
|
|
|
|
var DH = Ext.DomHelper,
|
|
El = Ext.Element;
|
|
|
|
|
|
El.prototype = {
|
|
|
|
set: function(o, useSet) {
|
|
var el = this.dom,
|
|
attr,
|
|
val;
|
|
useSet = (useSet !== false) && !!el.setAttribute;
|
|
|
|
for (attr in o) {
|
|
if (o.hasOwnProperty(attr)) {
|
|
val = o[attr];
|
|
if (attr == 'style') {
|
|
DH.applyStyles(el, val);
|
|
} else if (attr == 'cls') {
|
|
el.className = val;
|
|
} else if (useSet) {
|
|
el.setAttribute(attr, val);
|
|
} else {
|
|
el[attr] = val;
|
|
}
|
|
}
|
|
}
|
|
return this;
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defaultUnit: "px",
|
|
|
|
|
|
is: function(simpleSelector) {
|
|
return Ext.DomQuery.is(this.dom, simpleSelector);
|
|
},
|
|
|
|
|
|
focus: function(defer,
|
|
|
|
dom) {
|
|
var me = this;
|
|
dom = dom || me.dom;
|
|
try {
|
|
if (Number(defer)) {
|
|
Ext.defer(me.focus, defer, null, [null, dom]);
|
|
} else {
|
|
dom.focus();
|
|
}
|
|
} catch(e) {}
|
|
return me;
|
|
},
|
|
|
|
|
|
blur: function() {
|
|
try {
|
|
this.dom.blur();
|
|
} catch(e) {}
|
|
return this;
|
|
},
|
|
|
|
|
|
getValue: function(asNumber) {
|
|
var val = this.dom.value;
|
|
return asNumber ? parseInt(val, 10) : val;
|
|
},
|
|
|
|
|
|
addListener: function(eventName, fn, scope, options) {
|
|
Ext.EventManager.on(this.dom, eventName, fn, scope || this, options);
|
|
return this;
|
|
},
|
|
|
|
|
|
removeListener: function(eventName, fn, scope) {
|
|
Ext.EventManager.un(this.dom, eventName, fn, scope || this);
|
|
return this;
|
|
},
|
|
|
|
|
|
removeAllListeners: function() {
|
|
Ext.EventManager.removeAll(this.dom);
|
|
return this;
|
|
},
|
|
|
|
|
|
purgeAllListeners: function() {
|
|
Ext.EventManager.purgeElement(this);
|
|
return this;
|
|
},
|
|
|
|
|
|
addUnits: function(size, units) {
|
|
|
|
|
|
if (Ext.isNumber(size)) {
|
|
return size + (units || this.defaultUnit || 'px');
|
|
}
|
|
|
|
|
|
if (size === "" || size == "auto" || size == null) {
|
|
return size || '';
|
|
}
|
|
|
|
|
|
if (!unitPattern.test(size)) {
|
|
return size || '';
|
|
}
|
|
return size;
|
|
},
|
|
|
|
|
|
isBorderBox: function() {
|
|
return Ext.isBorderBox || noBoxAdjust[(this.dom.tagName || "").toLowerCase()];
|
|
},
|
|
|
|
|
|
remove: function() {
|
|
var me = this,
|
|
dom = me.dom;
|
|
|
|
if (dom) {
|
|
delete me.dom;
|
|
Ext.removeNode(dom);
|
|
}
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
contains: function(el) {
|
|
return ! el ? false: Ext.Element.isAncestor(this.dom, el.dom ? el.dom: el);
|
|
},
|
|
|
|
|
|
getAttributeNS: function(ns, name) {
|
|
return this.getAttribute(name, ns);
|
|
},
|
|
|
|
|
|
getAttribute: (Ext.isIE && !(Ext.isIE9 && document.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;
|
|
},
|
|
|
|
|
|
update: function(html) {
|
|
if (this.dom) {
|
|
this.dom.innerHTML = html;
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
|
|
var ep = El.prototype;
|
|
|
|
El.addMethods = function(o) {
|
|
Ext.apply(ep, o);
|
|
};
|
|
|
|
|
|
ep.on = ep.addListener;
|
|
|
|
|
|
ep.un = ep.removeListener;
|
|
|
|
|
|
ep.clearListeners = ep.removeAllListeners;
|
|
|
|
|
|
ep.destroy = ep.remove;
|
|
|
|
|
|
ep.autoBoxAdjust = true;
|
|
|
|
|
|
var unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
|
|
docEl;
|
|
|
|
|
|
El.get = function(el) {
|
|
var ex,
|
|
elm,
|
|
id;
|
|
if (!el) {
|
|
return null;
|
|
}
|
|
if (typeof el == "string") {
|
|
|
|
if (! (elm = DOC.getElementById(el))) {
|
|
return null;
|
|
}
|
|
if (EC[el] && EC[el].el) {
|
|
ex = EC[el].el;
|
|
ex.dom = elm;
|
|
} else {
|
|
ex = El.addToCache(new El(elm));
|
|
}
|
|
return ex;
|
|
} else if (el.tagName) {
|
|
|
|
if (! (id = el.id)) {
|
|
id = Ext.id(el);
|
|
}
|
|
if (EC[id] && EC[id].el) {
|
|
ex = EC[id].el;
|
|
ex.dom = el;
|
|
} else {
|
|
ex = El.addToCache(new El(el));
|
|
}
|
|
return ex;
|
|
} else if (el instanceof El) {
|
|
if (el != docEl) {
|
|
|
|
|
|
|
|
if (Ext.isIE && (el.id == undefined || el.id == '')) {
|
|
el.dom = el.dom;
|
|
} else {
|
|
el.dom = DOC.getElementById(el.id) || el.dom;
|
|
}
|
|
}
|
|
return el;
|
|
} else if (el.isComposite) {
|
|
return el;
|
|
} else if (Ext.isArray(el)) {
|
|
return El.select(el);
|
|
} else if (el == DOC) {
|
|
|
|
if (!docEl) {
|
|
var f = function() {};
|
|
f.prototype = El.prototype;
|
|
docEl = new f();
|
|
docEl.dom = DOC;
|
|
}
|
|
return docEl;
|
|
}
|
|
return null;
|
|
};
|
|
|
|
|
|
ep.getById = (!Ext.isIE6 && !Ext.isIE7 && !Ext.isIE8) ? El.get :
|
|
function (id) {
|
|
var dom = this.dom,
|
|
cached, el, ret;
|
|
|
|
if (dom) {
|
|
el = dom.all[id];
|
|
if (el) {
|
|
|
|
|
|
cached = EC[id];
|
|
if (cached && cached.el) {
|
|
ret = cached.el;
|
|
ret.dom = el;
|
|
} else {
|
|
ret = El.addToCache(new El(el));
|
|
}
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
return El.get(id);
|
|
};
|
|
|
|
El.addToCache = function(el, id) {
|
|
if (el) {
|
|
id = id || el.id;
|
|
EC[id] = {
|
|
el: el,
|
|
data: {},
|
|
events: {}
|
|
};
|
|
}
|
|
return el;
|
|
};
|
|
|
|
|
|
El.data = function(el, key, value) {
|
|
el = El.get(el);
|
|
if (!el) {
|
|
return null;
|
|
}
|
|
var c = EC[el.id].data;
|
|
if (arguments.length == 2) {
|
|
return c[key];
|
|
} else {
|
|
return (c[key] = value);
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
function garbageCollect() {
|
|
if (!Ext.enableGarbageCollector) {
|
|
clearInterval(El.collectorThreadId);
|
|
} else {
|
|
var eid,
|
|
el,
|
|
d,
|
|
o;
|
|
|
|
for (eid in EC) {
|
|
if (!EC.hasOwnProperty(eid)) {
|
|
continue;
|
|
}
|
|
o = EC[eid];
|
|
if (o.skipGarbageCollection) {
|
|
continue;
|
|
}
|
|
el = o.el;
|
|
d = el.dom;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!d || !d.parentNode || (!d.offsetParent && !DOC.getElementById(eid))) {
|
|
if (d && Ext.enableListenerCollection) {
|
|
Ext.EventManager.removeAll(d);
|
|
}
|
|
delete EC[eid];
|
|
}
|
|
}
|
|
|
|
if (Ext.isIE) {
|
|
var t = {};
|
|
for (eid in EC) {
|
|
if (!EC.hasOwnProperty(eid)) {
|
|
continue;
|
|
}
|
|
t[eid] = EC[eid];
|
|
}
|
|
EC = Ext.cache = t;
|
|
}
|
|
}
|
|
}
|
|
El.collectorThreadId = setInterval(garbageCollect, 30000);
|
|
|
|
var flyFn = function() {};
|
|
flyFn.prototype = El.prototype;
|
|
|
|
|
|
El.Flyweight = function(dom) {
|
|
this.dom = dom;
|
|
};
|
|
|
|
El.Flyweight.prototype = new flyFn();
|
|
El.Flyweight.prototype.isFlyweight = true;
|
|
El._flyweights = {};
|
|
|
|
|
|
El.fly = function(el, named) {
|
|
var ret = null;
|
|
named = named || '_global';
|
|
el = Ext.getDom(el);
|
|
if (el) {
|
|
(El._flyweights[named] = El._flyweights[named] || new El.Flyweight()).dom = el;
|
|
ret = El._flyweights[named];
|
|
}
|
|
return ret;
|
|
};
|
|
|
|
|
|
Ext.get = El.get;
|
|
|
|
|
|
Ext.fly = El.fly;
|
|
|
|
|
|
var noBoxAdjust = Ext.isStrict ? {
|
|
select: 1
|
|
}: {
|
|
input: 1,
|
|
select: 1,
|
|
textarea: 1
|
|
};
|
|
if (Ext.isIE || Ext.isGecko) {
|
|
noBoxAdjust['button'] = 1;
|
|
}
|
|
})();
|
|
|
|
|
|
Ext.Element.addMethods({
|
|
|
|
findParent : function(simpleSelector, maxDepth, returnEl) {
|
|
var p = this.dom,
|
|
b = document.body,
|
|
depth = 0,
|
|
stopEl;
|
|
|
|
maxDepth = maxDepth || 50;
|
|
if (isNaN(maxDepth)) {
|
|
stopEl = Ext.getDom(maxDepth);
|
|
maxDepth = Number.MAX_VALUE;
|
|
}
|
|
while (p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl) {
|
|
if (Ext.DomQuery.is(p, simpleSelector)) {
|
|
return returnEl ? Ext.get(p) : p;
|
|
}
|
|
depth++;
|
|
p = p.parentNode;
|
|
}
|
|
return null;
|
|
},
|
|
|
|
|
|
findParentNode : function(simpleSelector, maxDepth, returnEl) {
|
|
var p = Ext.fly(this.dom.parentNode, '_internal');
|
|
return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
|
|
},
|
|
|
|
|
|
up : function(simpleSelector, maxDepth) {
|
|
return this.findParentNode(simpleSelector, maxDepth, true);
|
|
},
|
|
|
|
|
|
select : function(selector) {
|
|
return Ext.Element.select(selector, false, this.dom);
|
|
},
|
|
|
|
|
|
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.get(me).id;
|
|
|
|
id = id.replace(/[\.:]/g, "\\$0");
|
|
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;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.Element.addMethods({
|
|
|
|
appendChild : function(el) {
|
|
return Ext.get(el).appendTo(this);
|
|
},
|
|
|
|
|
|
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, rt,
|
|
isAfter = (where || 'before').toLowerCase() == 'after',
|
|
insertEl;
|
|
|
|
if(Ext.isArray(el)){
|
|
insertEl = me;
|
|
Ext.each(el, function(e) {
|
|
rt = Ext.fly(insertEl, '_internal').insertSibling(e, where, returnDom);
|
|
if(isAfter){
|
|
insertEl = rt;
|
|
}
|
|
});
|
|
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 = Ext.DomHelper.append(me.dom.parentNode, el, !returnDom);
|
|
} else {
|
|
rt = Ext.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, me.dom);
|
|
}else{
|
|
el = Ext.DomHelper.insertBefore(me.dom, el);
|
|
}
|
|
|
|
delete Ext.cache[me.id];
|
|
Ext.removeNode(me.dom);
|
|
me.id = Ext.id(me.dom = el);
|
|
Ext.Element.addToCache(me.isFlyweight ? new Ext.Element(me.dom) : me);
|
|
return me;
|
|
},
|
|
|
|
|
|
createChild : function(config, insertBefore, returnDom) {
|
|
config = config || {tag:'div'};
|
|
if (insertBefore) {
|
|
return Ext.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
|
|
}
|
|
else {
|
|
return Ext.DomHelper[!this.dom.firstChild ? 'insertFirst' : 'append'](this.dom, config, returnDom !== true);
|
|
}
|
|
},
|
|
|
|
|
|
wrap : function(config, returnDom) {
|
|
var newEl = Ext.DomHelper.insertBefore(this.dom, config || {tag: "div"}, !returnDom),
|
|
d = newEl.dom || newEl;
|
|
|
|
d.appendChild(this.dom);
|
|
return newEl;
|
|
},
|
|
|
|
|
|
insertHtml : function(where, html, returnEl) {
|
|
var el = Ext.DomHelper.insertHtml(where, this.dom, html);
|
|
return returnEl ? Ext.get(el) : el;
|
|
}
|
|
});
|
|
|
|
|
|
(function(){
|
|
|
|
var ELEMENT = Ext.Element,
|
|
supports = Ext.supports,
|
|
view = document.defaultView,
|
|
opacityRe = /alpha\(opacity=(.*)\)/i,
|
|
trimRe = /^\s+|\s+$/g,
|
|
spacesRe = /\s+/,
|
|
wordsRe = /\w/g,
|
|
adjustDirect2DTableRe = /table-row|table-.*-group/,
|
|
INTERNAL = '_internal',
|
|
PADDING = 'padding',
|
|
MARGIN = 'margin',
|
|
BORDER = 'border',
|
|
LEFT = '-left',
|
|
RIGHT = '-right',
|
|
TOP = '-top',
|
|
BOTTOM = '-bottom',
|
|
WIDTH = '-width',
|
|
MATH = Math,
|
|
HIDDEN = 'hidden',
|
|
ISCLIPPED = 'isClipped',
|
|
OVERFLOW = 'overflow',
|
|
OVERFLOWX = 'overflow-x',
|
|
OVERFLOWY = 'overflow-y',
|
|
ORIGINALCLIP = 'originalClip',
|
|
|
|
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},
|
|
data = ELEMENT.data;
|
|
|
|
ELEMENT.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
|
|
|
|
|
|
|
|
ELEMENT.inheritedProps = {
|
|
fontSize: 1,
|
|
fontStyle: 1,
|
|
opacity: 1
|
|
};
|
|
|
|
Ext.override(ELEMENT, {
|
|
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
|
|
addCls : function(className){
|
|
var me = this,
|
|
cls = [],
|
|
space = ((me.dom.className.replace(trimRe, '') == '') ? "" : " "),
|
|
i, len, v;
|
|
if (className === undefined) {
|
|
return me;
|
|
}
|
|
|
|
if (Object.prototype.toString.call(className) !== '[object Array]') {
|
|
if (typeof className === 'string') {
|
|
className = className.replace(trimRe, '').split(spacesRe);
|
|
if (className.length === 1) {
|
|
className = className[0];
|
|
if (!me.hasCls(className)) {
|
|
me.dom.className += space + className;
|
|
}
|
|
} else {
|
|
this.addCls(className);
|
|
}
|
|
}
|
|
} else {
|
|
for (i = 0, len = className.length; i < len; i++) {
|
|
v = className[i];
|
|
if (typeof v == 'string' && (' ' + me.dom.className + ' ').indexOf(' ' + v + ' ') == -1) {
|
|
cls.push(v);
|
|
}
|
|
}
|
|
if (cls.length) {
|
|
me.dom.className += space + cls.join(" ");
|
|
}
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
removeCls : function(className){
|
|
var me = this,
|
|
i, idx, len, cls, elClasses;
|
|
if (className === undefined) {
|
|
return me;
|
|
}
|
|
if (Object.prototype.toString.call(className) !== '[object Array]') {
|
|
className = className.replace(trimRe, '').split(spacesRe);
|
|
}
|
|
if (me.dom && me.dom.className) {
|
|
elClasses = me.dom.className.replace(trimRe, '').split(spacesRe);
|
|
for (i = 0, len = className.length; i < len; i++) {
|
|
cls = className[i];
|
|
if (typeof cls == 'string') {
|
|
cls = cls.replace(trimRe, '');
|
|
idx = Ext.Array.indexOf(elClasses, cls);
|
|
if (idx != -1) {
|
|
Ext.Array.erase(elClasses, idx, 1);
|
|
}
|
|
}
|
|
}
|
|
me.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) {
|
|
Ext.fly(v, '_internal').removeCls(className);
|
|
}
|
|
}
|
|
return this.addCls(className);
|
|
},
|
|
|
|
|
|
toggleCls : Ext.supports.ClassList ?
|
|
function(className) {
|
|
this.dom.classList.toggle(Ext.String.trim(className));
|
|
return this;
|
|
} :
|
|
function(className) {
|
|
return this.hasCls(className) ? this.removeCls(className) : this.addCls(className);
|
|
},
|
|
|
|
|
|
hasCls : Ext.supports.ClassList ?
|
|
function(className) {
|
|
if (!className) {
|
|
return false;
|
|
}
|
|
className = className.split(spacesRe);
|
|
var ln = className.length,
|
|
i = 0;
|
|
for (; i < ln; i++) {
|
|
if (className[i] && this.dom.classList.contains(className[i])) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
} :
|
|
function(className){
|
|
return className && (' ' + this.dom.className + ' ').indexOf(' ' + className + ' ') != -1;
|
|
},
|
|
|
|
|
|
replaceCls : function(oldClassName, newClassName){
|
|
return this.removeCls(oldClassName).addCls(newClassName);
|
|
},
|
|
|
|
isStyle : function(style, val) {
|
|
return this.getStyle(style) == val;
|
|
},
|
|
|
|
|
|
getStyle : function() {
|
|
return view && view.getComputedStyle ?
|
|
function(prop){
|
|
var el = this.dom,
|
|
v, cs, out, display, cleaner;
|
|
|
|
if(el == document){
|
|
return null;
|
|
}
|
|
prop = ELEMENT.normalize(prop);
|
|
out = (v = el.style[prop]) ? v :
|
|
(cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
|
|
|
|
|
|
|
|
if(prop == 'marginRight' && out != '0px' && !supports.RightMargin){
|
|
cleaner = ELEMENT.getRightMarginFixCleaner(el);
|
|
display = this.getStyle('display');
|
|
el.style.display = 'inline-block';
|
|
out = view.getComputedStyle(el, '').marginRight;
|
|
el.style.display = display;
|
|
cleaner();
|
|
}
|
|
|
|
if(prop == 'backgroundColor' && out == 'rgba(0, 0, 0, 0)' && !supports.TransparentColor){
|
|
out = 'transparent';
|
|
}
|
|
return out;
|
|
} :
|
|
function (prop) {
|
|
var el = this.dom,
|
|
m, cs;
|
|
|
|
if (el == document) {
|
|
return null;
|
|
}
|
|
prop = ELEMENT.normalize(prop);
|
|
|
|
do {
|
|
if (prop == 'opacity') {
|
|
if (el.style.filter.match) {
|
|
m = el.style.filter.match(opacityRe);
|
|
if(m){
|
|
var fv = parseFloat(m[1]);
|
|
if(!isNaN(fv)){
|
|
return fv ? fv / 100 : 0;
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
|
|
if (!Ext.isIE6) {
|
|
return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
|
|
}
|
|
|
|
try {
|
|
return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
|
|
} catch (e) {
|
|
|
|
|
|
}
|
|
|
|
if (!ELEMENT.inheritedProps[prop]) {
|
|
break;
|
|
}
|
|
|
|
el = el.parentNode;
|
|
|
|
|
|
|
|
} while (el);
|
|
|
|
return null;
|
|
}
|
|
}(),
|
|
|
|
|
|
getColor : function(attr, defaultValue, prefix){
|
|
var v = this.getStyle(attr),
|
|
color = prefix || prefix === '' ? prefix : '#',
|
|
h;
|
|
|
|
if(!v || (/transparent|inherit/.test(v))) {
|
|
return defaultValue;
|
|
}
|
|
if(/^r/.test(v)){
|
|
Ext.each(v.slice(4, v.length -1).split(','), function(s){
|
|
h = parseInt(s, 10);
|
|
color += (h < 16 ? '0' : '') + h.toString(16);
|
|
});
|
|
}else{
|
|
v = v.replace('#', '');
|
|
color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;
|
|
}
|
|
return(color.length > 5 ? color.toLowerCase() : defaultValue);
|
|
},
|
|
|
|
|
|
setStyle : function(prop, value){
|
|
var me = this,
|
|
tmp, style;
|
|
|
|
if (!me.dom) {
|
|
return me;
|
|
}
|
|
if (typeof prop === 'string') {
|
|
tmp = {};
|
|
tmp[prop] = value;
|
|
prop = tmp;
|
|
}
|
|
for (style in prop) {
|
|
if (prop.hasOwnProperty(style)) {
|
|
value = Ext.value(prop[style], '');
|
|
if (style == 'opacity') {
|
|
me.setOpacity(value);
|
|
}
|
|
else {
|
|
me.dom.style[ELEMENT.normalize(style)] = value;
|
|
}
|
|
}
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
setOpacity: function(opacity, animate) {
|
|
var me = this,
|
|
dom = me.dom,
|
|
val,
|
|
style;
|
|
|
|
if (!me.dom) {
|
|
return me;
|
|
}
|
|
|
|
style = me.dom.style;
|
|
|
|
if (!animate || !me.anim) {
|
|
if (!Ext.supports.Opacity) {
|
|
opacity = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')': '';
|
|
val = style.filter.replace(opacityRe, '').replace(trimRe, '');
|
|
|
|
style.zoom = 1;
|
|
style.filter = val + (val.length > 0 ? ' ': '') + opacity;
|
|
}
|
|
else {
|
|
style.opacity = opacity;
|
|
}
|
|
}
|
|
else {
|
|
if (!Ext.isObject(animate)) {
|
|
animate = {
|
|
duration: 350,
|
|
easing: 'ease-in'
|
|
};
|
|
}
|
|
me.animate(Ext.applyIf({
|
|
to: {
|
|
opacity: opacity
|
|
}
|
|
},
|
|
animate));
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
|
|
clearOpacity : function(){
|
|
var style = this.dom.style;
|
|
if(!Ext.supports.Opacity){
|
|
if(!Ext.isEmpty(style.filter)){
|
|
style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
|
|
}
|
|
}else{
|
|
style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
|
|
}
|
|
return this;
|
|
},
|
|
|
|
|
|
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,
|
|
floating;
|
|
|
|
if (display === 'inline') {
|
|
dom.style['display'] = 'inline-block';
|
|
}
|
|
|
|
dom.style['position'] = display.match(adjustDirect2DTableRe) ? 'absolute' : 'static';
|
|
|
|
|
|
|
|
floating = (parseFloat(me.getStyle(dimension)) || parseFloat(dom.currentStyle.msTransformOrigin.split(' ')[originIndex]) * 2) % 1;
|
|
|
|
dom.style['position'] = inlinePosition;
|
|
|
|
if (display === 'inline') {
|
|
dom.style['display'] = inlineDisplay;
|
|
}
|
|
|
|
return floating;
|
|
},
|
|
|
|
|
|
getHeight: function(contentHeight, preciseHeight) {
|
|
var me = this,
|
|
dom = me.dom,
|
|
hidden = Ext.isIE && me.isStyle('display', 'none'),
|
|
height, overflow, style, floating;
|
|
|
|
|
|
|
|
if (Ext.isIEQuirks) {
|
|
style = dom.style;
|
|
overflow = style.overflow;
|
|
me.setStyle({ overflow: 'hidden'});
|
|
}
|
|
|
|
height = dom.offsetHeight;
|
|
|
|
height = MATH.max(height, hidden ? 0 : dom.clientHeight) || 0;
|
|
|
|
|
|
if (!hidden && 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"));
|
|
}
|
|
|
|
if (Ext.isIEQuirks) {
|
|
me.setStyle({ overflow: overflow});
|
|
}
|
|
|
|
if (height < 0) {
|
|
height = 0;
|
|
}
|
|
return height;
|
|
},
|
|
|
|
|
|
getWidth: function(contentWidth, preciseWidth) {
|
|
var me = this,
|
|
dom = me.dom,
|
|
hidden = Ext.isIE && me.isStyle('display', 'none'),
|
|
rect, width, overflow, style, floating, parentPosition;
|
|
|
|
|
|
|
|
if (Ext.isIEQuirks) {
|
|
style = dom.style;
|
|
overflow = style.overflow;
|
|
me.setStyle({overflow: 'hidden'});
|
|
}
|
|
|
|
|
|
if (Ext.isOpera10_5) {
|
|
if (dom.parentNode.currentStyle.position === 'relative') {
|
|
parentPosition = dom.parentNode.style.position;
|
|
dom.parentNode.style.position = 'static';
|
|
width = dom.offsetWidth;
|
|
dom.parentNode.style.position = parentPosition;
|
|
}
|
|
width = Math.max(width || 0, dom.offsetWidth);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (Ext.supports.BoundingClientRect) {
|
|
rect = dom.getBoundingClientRect();
|
|
width = rect.right - rect.left;
|
|
width = preciseWidth ? width : Math.ceil(width);
|
|
} else {
|
|
width = dom.offsetWidth;
|
|
}
|
|
|
|
width = MATH.max(width, hidden ? 0 : dom.clientWidth) || 0;
|
|
|
|
|
|
if (!hidden && Ext.supports.Direct2DBug) {
|
|
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"));
|
|
}
|
|
|
|
if (Ext.isIEQuirks) {
|
|
me.setStyle({ overflow: overflow});
|
|
}
|
|
|
|
if (width < 0) {
|
|
width = 0;
|
|
}
|
|
return 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;
|
|
},
|
|
|
|
|
|
getBorderWidth : function(side){
|
|
return this.addStyles(side, borders);
|
|
},
|
|
|
|
|
|
getPadding : function(side){
|
|
return this.addStyles(side, paddings);
|
|
},
|
|
|
|
|
|
clip : function(){
|
|
var me = this,
|
|
dom = me.dom;
|
|
|
|
if(!data(dom, ISCLIPPED)){
|
|
data(dom, ISCLIPPED, true);
|
|
data(dom, ORIGINALCLIP, {
|
|
o: me.getStyle(OVERFLOW),
|
|
x: me.getStyle(OVERFLOWX),
|
|
y: me.getStyle(OVERFLOWY)
|
|
});
|
|
me.setStyle(OVERFLOW, HIDDEN);
|
|
me.setStyle(OVERFLOWX, HIDDEN);
|
|
me.setStyle(OVERFLOWY, HIDDEN);
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
unclip : function(){
|
|
var me = this,
|
|
dom = me.dom,
|
|
clip;
|
|
|
|
if(data(dom, ISCLIPPED)){
|
|
data(dom, ISCLIPPED, false);
|
|
clip = data(dom, 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;
|
|
},
|
|
|
|
|
|
addStyles : function(sides, styles){
|
|
var totalSize = 0,
|
|
sidesArr = sides.match(wordsRe),
|
|
i = 0,
|
|
len = sidesArr.length,
|
|
side, size;
|
|
for (; i < len; i++) {
|
|
side = sidesArr[i];
|
|
size = side && parseInt(this.getStyle(styles[side]), 10);
|
|
if (size) {
|
|
totalSize += MATH.abs(size);
|
|
}
|
|
}
|
|
return totalSize;
|
|
},
|
|
|
|
margins : margins,
|
|
|
|
|
|
applyStyles : function(style){
|
|
Ext.DomHelper.applyStyles(this.dom, style);
|
|
return this;
|
|
},
|
|
|
|
|
|
getStyles : function(){
|
|
var styles = {},
|
|
len = arguments.length,
|
|
i = 0, style;
|
|
|
|
for(; i < len; ++i) {
|
|
style = arguments[i];
|
|
styles[style] = this.getStyle(style);
|
|
}
|
|
return styles;
|
|
},
|
|
|
|
|
|
boxWrap : function(cls){
|
|
cls = cls || Ext.baseCSSPrefix + 'box';
|
|
var el = Ext.get(this.insertHtml("beforeBegin", "<div class='" + cls + "'>" + Ext.String.format(ELEMENT.boxMarkup, cls) + "</div>"));
|
|
Ext.DomQuery.selectNode('.' + cls + '-mc', el.dom).appendChild(this.dom);
|
|
return el;
|
|
},
|
|
|
|
|
|
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){
|
|
|
|
|
|
if (!Ext.isIEQuirks && (Ext.isIE6 || Ext.isIE7)) {
|
|
me.dom.offsetTop;
|
|
}
|
|
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;
|
|
},
|
|
|
|
|
|
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){
|
|
var dom = this.dom;
|
|
this.hover(
|
|
function(){
|
|
Ext.fly(dom, INTERNAL).addCls(className);
|
|
},
|
|
function(){
|
|
Ext.fly(dom, INTERNAL).removeCls(className);
|
|
}
|
|
);
|
|
return this;
|
|
},
|
|
|
|
|
|
addClsOnFocus : function(className){
|
|
var me = this,
|
|
dom = me.dom;
|
|
me.on("focus", function(){
|
|
Ext.fly(dom, INTERNAL).addCls(className);
|
|
});
|
|
me.on("blur", function(){
|
|
Ext.fly(dom, INTERNAL).removeCls(className);
|
|
});
|
|
return me;
|
|
},
|
|
|
|
|
|
addClsOnClick : function(className){
|
|
var dom = this.dom;
|
|
this.on("mousedown", function(){
|
|
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 this;
|
|
},
|
|
|
|
|
|
|
|
getViewSize : function(){
|
|
var me = this,
|
|
dom = me.dom,
|
|
isDoc = (dom == Ext.getDoc().dom || dom == Ext.getBody().dom),
|
|
style, overflow, ret;
|
|
|
|
|
|
if (isDoc) {
|
|
ret = {
|
|
width : ELEMENT.getViewWidth(),
|
|
height : ELEMENT.getViewHeight()
|
|
};
|
|
|
|
|
|
}
|
|
else {
|
|
|
|
|
|
if (Ext.isIE6 || Ext.isIEQuirks) {
|
|
style = dom.style;
|
|
overflow = style.overflow;
|
|
me.setStyle({ overflow: 'hidden'});
|
|
}
|
|
ret = {
|
|
width : dom.clientWidth,
|
|
height : dom.clientHeight
|
|
};
|
|
if (Ext.isIE6 || Ext.isIEQuirks) {
|
|
me.setStyle({ overflow: overflow });
|
|
}
|
|
}
|
|
return ret;
|
|
},
|
|
|
|
|
|
|
|
getStyleSize : function(){
|
|
var me = this,
|
|
doc = document,
|
|
d = this.dom,
|
|
isDoc = (d == doc || d == doc.body),
|
|
s = d.style,
|
|
w, h;
|
|
|
|
|
|
if (isDoc) {
|
|
return {
|
|
width : ELEMENT.getViewWidth(),
|
|
height : ELEMENT.getViewHeight()
|
|
};
|
|
}
|
|
|
|
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)};
|
|
},
|
|
|
|
|
|
getSize : function(contentSize){
|
|
return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
|
|
},
|
|
|
|
|
|
repaint : function(){
|
|
var dom = this.dom;
|
|
this.addCls(Ext.baseCSSPrefix + 'repaint');
|
|
setTimeout(function(){
|
|
Ext.fly(dom).removeCls(Ext.baseCSSPrefix + 'repaint');
|
|
}, 1);
|
|
return this;
|
|
},
|
|
|
|
|
|
selectable : function() {
|
|
var me = this;
|
|
me.dom.unselectable = "off";
|
|
|
|
me.on('selectstart', function (e) {
|
|
e.stopPropagation();
|
|
return true;
|
|
});
|
|
me.applyStyles("-moz-user-select: text; -khtml-user-select: text;");
|
|
me.removeCls(Ext.baseCSSPrefix + 'unselectable');
|
|
return me;
|
|
},
|
|
|
|
|
|
unselectable : function(){
|
|
var me = this;
|
|
me.dom.unselectable = "on";
|
|
|
|
me.swallowEvent("selectstart", true);
|
|
me.applyStyles("-moz-user-select:-moz-none;-khtml-user-select:none;");
|
|
me.addCls(Ext.baseCSSPrefix + 'unselectable');
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
getMargin : function(side){
|
|
var me = this,
|
|
hash = {t:"top", l:"left", r:"right", b: "bottom"},
|
|
o = {},
|
|
key;
|
|
|
|
if (!side) {
|
|
for (key in me.margins){
|
|
o[hash[key]] = parseFloat(me.getStyle(me.margins[key])) || 0;
|
|
}
|
|
return o;
|
|
} else {
|
|
return me.addStyles.call(me, side, me.margins);
|
|
}
|
|
}
|
|
});
|
|
})();
|
|
|
|
|
|
Ext.Element.VISIBILITY = 1;
|
|
|
|
Ext.Element.DISPLAY = 2;
|
|
|
|
|
|
Ext.Element.OFFSETS = 3;
|
|
|
|
|
|
Ext.Element.ASCLASS = 4;
|
|
|
|
|
|
Ext.Element.visibilityCls = Ext.baseCSSPrefix + 'hide-nosize';
|
|
|
|
Ext.Element.addMethods(function(){
|
|
var El = Ext.Element,
|
|
OPACITY = "opacity",
|
|
VISIBILITY = "visibility",
|
|
DISPLAY = "display",
|
|
HIDDEN = "hidden",
|
|
OFFSETS = "offsets",
|
|
ASCLASS = "asclass",
|
|
NONE = "none",
|
|
NOSIZE = 'nosize',
|
|
ORIGINALDISPLAY = 'originalDisplay',
|
|
VISMODE = 'visibilityMode',
|
|
ISVISIBLE = 'isVisible',
|
|
data = El.data,
|
|
getDisplay = function(dom){
|
|
var d = data(dom, ORIGINALDISPLAY);
|
|
if(d === undefined){
|
|
data(dom, ORIGINALDISPLAY, d = '');
|
|
}
|
|
return d;
|
|
},
|
|
getVisMode = function(dom){
|
|
var m = data(dom, VISMODE);
|
|
if(m === undefined){
|
|
data(dom, VISMODE, m = 1);
|
|
}
|
|
return m;
|
|
};
|
|
|
|
return {
|
|
|
|
originalDisplay : "",
|
|
visibilityMode : 1,
|
|
|
|
|
|
setVisibilityMode : function(visMode){
|
|
data(this.dom, VISMODE, visMode);
|
|
return this;
|
|
},
|
|
|
|
|
|
isVisible : function() {
|
|
var me = this,
|
|
dom = me.dom,
|
|
visible = data(dom, ISVISIBLE);
|
|
|
|
if(typeof visible == 'boolean'){
|
|
return visible;
|
|
}
|
|
|
|
visible = !me.isStyle(VISIBILITY, HIDDEN) &&
|
|
!me.isStyle(DISPLAY, NONE) &&
|
|
!((getVisMode(dom) == El.ASCLASS) && me.hasCls(me.visibilityCls || El.visibilityCls));
|
|
|
|
data(dom, ISVISIBLE, visible);
|
|
return visible;
|
|
},
|
|
|
|
|
|
setVisible : function(visible, animate){
|
|
var me = this, isDisplay, isVisibility, isOffsets, isNosize,
|
|
dom = me.dom,
|
|
visMode = getVisMode(dom);
|
|
|
|
|
|
|
|
if (typeof animate == 'string'){
|
|
switch (animate) {
|
|
case DISPLAY:
|
|
visMode = El.DISPLAY;
|
|
break;
|
|
case VISIBILITY:
|
|
visMode = El.VISIBILITY;
|
|
break;
|
|
case OFFSETS:
|
|
visMode = El.OFFSETS;
|
|
break;
|
|
case NOSIZE:
|
|
case ASCLASS:
|
|
visMode = El.ASCLASS;
|
|
break;
|
|
}
|
|
me.setVisibilityMode(visMode);
|
|
animate = false;
|
|
}
|
|
|
|
if (!animate || !me.anim) {
|
|
if(visMode == El.ASCLASS ){
|
|
|
|
me[visible?'removeCls':'addCls'](me.visibilityCls || El.visibilityCls);
|
|
|
|
} else if (visMode == El.DISPLAY){
|
|
|
|
return me.setDisplayed(visible);
|
|
|
|
} else if (visMode == El.OFFSETS){
|
|
|
|
if (!visible){
|
|
|
|
if (!me.hideModeStyles) {
|
|
me.hideModeStyles = {
|
|
position: me.getStyle('position'),
|
|
top: me.getStyle('top'),
|
|
left: me.getStyle('left')
|
|
};
|
|
}
|
|
me.applyStyles({position: 'absolute', top: '-10000px', left: '-10000px'});
|
|
}
|
|
|
|
|
|
|
|
else if (me.hideModeStyles) {
|
|
me.applyStyles(me.hideModeStyles || {position: '', top: '', left: ''});
|
|
delete me.hideModeStyles;
|
|
}
|
|
|
|
}else{
|
|
me.fixDisplay();
|
|
|
|
dom.style.visibility = visible ? '' : HIDDEN;
|
|
}
|
|
}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() {
|
|
visible || me.setVisible(false).setOpacity(1);
|
|
},
|
|
to: {
|
|
opacity: (visible) ? 1 : 0
|
|
}
|
|
}, animate));
|
|
}
|
|
data(dom, ISVISIBLE, visible);
|
|
return me;
|
|
},
|
|
|
|
|
|
|
|
hasMetrics : function(){
|
|
var dom = this.dom;
|
|
return this.isVisible() || (getVisMode(dom) == El.OFFSETS) || (getVisMode(dom) == El.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.dom) : 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(this.dom));
|
|
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.applyIf(Ext.Element.prototype, {
|
|
|
|
animate: function(config) {
|
|
var me = this;
|
|
if (!me.id) {
|
|
me = Ext.get(me.dom);
|
|
}
|
|
if (Ext.fx.Manager.hasFxBlock(me.id)) {
|
|
return me;
|
|
}
|
|
Ext.fx.Manager.queueFx(Ext.create('Ext.fx.Anim', me.anim(config)));
|
|
return this;
|
|
},
|
|
|
|
|
|
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,
|
|
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,
|
|
elStyle = me.dom.style,
|
|
beforeAnim, wrapAnim;
|
|
|
|
anchor = anchor || "t";
|
|
obj = obj || {};
|
|
|
|
beforeAnim = function() {
|
|
var animScope = this,
|
|
listeners = obj.listeners,
|
|
box, position, restoreSize, wrap, anim;
|
|
|
|
if (!slideOut) {
|
|
me.fixDisplay();
|
|
}
|
|
|
|
box = me.getBox();
|
|
if ((anchor == 't' || anchor == 'b') && box.height === 0) {
|
|
box.height = me.dom.scrollHeight;
|
|
}
|
|
else if ((anchor == 'l' || anchor == 'r') && box.width === 0) {
|
|
box.width = me.dom.scrollWidth;
|
|
}
|
|
|
|
position = me.getPositioning();
|
|
me.setSize(box.width, box.height);
|
|
|
|
wrap = me.wrap({
|
|
style: {
|
|
visibility: slideOut ? 'visible' : 'hidden'
|
|
}
|
|
});
|
|
wrap.setPositioning(position);
|
|
if (wrap.isStyle('position', 'static')) {
|
|
wrap.position('relative');
|
|
}
|
|
me.clearPositioning('auto');
|
|
wrap.clip();
|
|
|
|
|
|
|
|
|
|
me.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'
|
|
}
|
|
};
|
|
elStyle.right = '0px';
|
|
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'
|
|
}
|
|
};
|
|
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';
|
|
elStyle.right = '0px';
|
|
break;
|
|
case 'bl':
|
|
anim = {
|
|
from: {
|
|
x: box.x + box.width,
|
|
width: '0px',
|
|
height: '0px'
|
|
},
|
|
to: {
|
|
x: box.x,
|
|
width: box.width + 'px',
|
|
height: box.height + 'px'
|
|
}
|
|
};
|
|
elStyle.right = '0px';
|
|
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'
|
|
}
|
|
};
|
|
break;
|
|
case 'tr':
|
|
anim = {
|
|
from: {
|
|
y: box.y + box.height,
|
|
width: '0px',
|
|
height: '0px'
|
|
},
|
|
to: {
|
|
y: box.y,
|
|
width: box.width + 'px',
|
|
height: box.height + 'px'
|
|
}
|
|
};
|
|
elStyle.bottom = '0px';
|
|
break;
|
|
}
|
|
|
|
wrap.show();
|
|
wrapAnim = Ext.apply({}, obj);
|
|
delete wrapAnim.listeners;
|
|
wrapAnim = Ext.create('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() {
|
|
if (slideOut) {
|
|
me.setPositioning(position);
|
|
if (obj.useDisplay) {
|
|
me.setDisplayed(false);
|
|
} else {
|
|
me.hide();
|
|
}
|
|
}
|
|
else {
|
|
me.clearPositioning();
|
|
me.setPositioning(position);
|
|
}
|
|
if (wrap.dom) {
|
|
wrap.dom.parentNode.insertBefore(me.dom, wrap.dom);
|
|
wrap.remove();
|
|
}
|
|
me.setSize(box.width, box.height);
|
|
animScope.end();
|
|
});
|
|
|
|
if (listeners) {
|
|
wrapAnim.on(listeners);
|
|
}
|
|
};
|
|
|
|
me.animate({
|
|
duration: obj.duration ? obj.duration * 2 : 1000,
|
|
listeners: {
|
|
beforeanimate: {
|
|
fn: beforeAnim
|
|
},
|
|
afteranimate: {
|
|
fn: function() {
|
|
if (wrapAnim && wrapAnim.running) {
|
|
wrapAnim.end();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
return me;
|
|
},
|
|
|
|
|
|
|
|
slideOut: function(anchor, o) {
|
|
return this.slideIn(anchor, o, true);
|
|
},
|
|
|
|
|
|
puff: function(obj) {
|
|
var me = this,
|
|
beforeAnim;
|
|
obj = Ext.applyIf(obj || {}, {
|
|
easing: 'ease-out',
|
|
duration: 500,
|
|
useDisplay: false
|
|
});
|
|
|
|
beforeAnim = function() {
|
|
me.clearOpacity();
|
|
me.show();
|
|
|
|
var box = me.getBox(),
|
|
fontSize = me.getStyle('fontSize'),
|
|
position = me.getPositioning();
|
|
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() {
|
|
if (me.dom) {
|
|
if (obj.useDisplay) {
|
|
me.setDisplayed(false);
|
|
} else {
|
|
me.hide();
|
|
}
|
|
me.clearOpacity();
|
|
me.setPositioning(position);
|
|
me.setStyle({fontSize: fontSize});
|
|
}
|
|
});
|
|
};
|
|
|
|
me.animate({
|
|
duration: obj.duration,
|
|
easing: obj.easing,
|
|
listeners: {
|
|
beforeanimate: {
|
|
fn: beforeAnim
|
|
}
|
|
}
|
|
});
|
|
return me;
|
|
},
|
|
|
|
|
|
switchOff: function(obj) {
|
|
var me = this,
|
|
beforeAnim;
|
|
|
|
obj = Ext.applyIf(obj || {}, {
|
|
easing: 'ease-in',
|
|
duration: 500,
|
|
remove: false,
|
|
useDisplay: false
|
|
});
|
|
|
|
beforeAnim = function() {
|
|
var animScope = this,
|
|
size = me.getSize(),
|
|
xy = me.getXY(),
|
|
keyframe, position;
|
|
me.clearOpacity();
|
|
me.clip();
|
|
position = me.getPositioning();
|
|
|
|
keyframe = Ext.create('Ext.fx.Animator', {
|
|
target: me,
|
|
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() {
|
|
if (obj.useDisplay) {
|
|
me.setDisplayed(false);
|
|
} else {
|
|
me.hide();
|
|
}
|
|
me.clearOpacity();
|
|
me.setPositioning(position);
|
|
me.setSize(size);
|
|
animScope.end();
|
|
});
|
|
};
|
|
me.animate({
|
|
duration: (obj.duration * 2),
|
|
listeners: {
|
|
beforeanimate: {
|
|
fn: beforeAnim
|
|
}
|
|
}
|
|
});
|
|
return me;
|
|
},
|
|
|
|
|
|
frame : function(color, count, obj){
|
|
var me = this,
|
|
beforeAnim;
|
|
|
|
color = color || '#C3DAF9';
|
|
count = count || 1;
|
|
obj = obj || {};
|
|
|
|
beforeAnim = function() {
|
|
me.show();
|
|
var animScope = this,
|
|
box = me.getBox(),
|
|
proxy = Ext.getBody().createChild({
|
|
style: {
|
|
position : 'absolute',
|
|
'pointer-events': 'none',
|
|
'z-index': 35000,
|
|
border : '0px solid ' + color
|
|
}
|
|
}),
|
|
proxyAnim;
|
|
proxyAnim = Ext.create('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: (obj.duration * 2) || 2000,
|
|
listeners: {
|
|
beforeanimate: {
|
|
fn: beforeAnim
|
|
}
|
|
}
|
|
});
|
|
return me;
|
|
},
|
|
|
|
|
|
ghost: function(anchor, obj) {
|
|
var me = this,
|
|
beforeAnim;
|
|
|
|
anchor = anchor || "b";
|
|
beforeAnim = function() {
|
|
var width = me.getWidth(),
|
|
height = me.getHeight(),
|
|
xy = me.getXY(),
|
|
position = me.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 () {
|
|
if (me.dom) {
|
|
me.hide();
|
|
me.clearOpacity();
|
|
me.setPositioning(position);
|
|
}
|
|
});
|
|
};
|
|
|
|
me.animate(Ext.applyIf(obj || {}, {
|
|
duration: 500,
|
|
easing: 'ease-out',
|
|
listeners: {
|
|
beforeanimate: {
|
|
fn: beforeAnim
|
|
}
|
|
}
|
|
}));
|
|
return me;
|
|
},
|
|
|
|
|
|
highlight: function(color, o) {
|
|
var me = this,
|
|
dom = me.dom,
|
|
from = {},
|
|
restore, to, attr, lns, event, fn;
|
|
|
|
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];
|
|
me.clearOpacity();
|
|
me.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) {
|
|
this.animate(Ext.apply({}, o, {
|
|
opacity: 1
|
|
}));
|
|
return this;
|
|
},
|
|
|
|
|
|
fadeOut: function(o) {
|
|
this.animate(Ext.apply({}, o, {
|
|
opacity: 0
|
|
}));
|
|
return this;
|
|
},
|
|
|
|
|
|
scale: function(w, h, o) {
|
|
this.animate(Ext.apply({}, o, {
|
|
width: w,
|
|
height: h
|
|
}));
|
|
return this;
|
|
},
|
|
|
|
|
|
shift: function(config) {
|
|
this.animate(config);
|
|
return this;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.applyIf(Ext.Element, {
|
|
unitRe: /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i,
|
|
camelRe: /(-[a-z])/gi,
|
|
opacityRe: /alpha\(opacity=(.*)\)/i,
|
|
cssRe: /([a-z0-9-]+)\s*:\s*([^;\s]+(?:\s*[^;\s]+)*);?/gi,
|
|
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 : Ext.Element.prototype.addUnits,
|
|
|
|
|
|
parseBox : function(box) {
|
|
if (Ext.isObject(box)) {
|
|
return {
|
|
top: box.top || 0,
|
|
right: box.right || 0,
|
|
bottom: box.bottom || 0,
|
|
left: box.left || 0
|
|
};
|
|
} else {
|
|
if (typeof box != 'string') {
|
|
box = box.toString();
|
|
}
|
|
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 :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.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;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.CompositeElementLite = function(els, root){
|
|
|
|
this.elements = [];
|
|
this.add(els, root);
|
|
this.el = new Ext.Element.Flyweight();
|
|
};
|
|
|
|
Ext.CompositeElementLite.prototype = {
|
|
isComposite: true,
|
|
|
|
|
|
getElement : function(el){
|
|
|
|
var e = this.el;
|
|
e.dom = el;
|
|
e.id = el.id;
|
|
return e;
|
|
},
|
|
|
|
|
|
transformElement : function(el){
|
|
return Ext.getDom(el);
|
|
},
|
|
|
|
|
|
getCount : function(){
|
|
return this.elements.length;
|
|
},
|
|
|
|
add : function(els, root){
|
|
var me = this,
|
|
elements = me.elements;
|
|
if(!els){
|
|
return this;
|
|
}
|
|
if(typeof els == "string"){
|
|
els = Ext.Element.selectorFunction(els, root);
|
|
}else if(els.isComposite){
|
|
els = els.elements;
|
|
}else if(!Ext.isIterable(els)){
|
|
els = [els];
|
|
}
|
|
|
|
for(var i = 0, len = els.length; i < len; ++i){
|
|
elements.push(me.transformElement(els[i]));
|
|
}
|
|
return me;
|
|
},
|
|
|
|
invoke : function(fn, args){
|
|
var me = this,
|
|
els = me.elements,
|
|
len = els.length,
|
|
e,
|
|
i;
|
|
|
|
for(i = 0; i < len; i++) {
|
|
e = els[i];
|
|
if(e){
|
|
Ext.Element.prototype[fn].apply(me.getElement(e), args);
|
|
}
|
|
}
|
|
return me;
|
|
},
|
|
|
|
item : function(index){
|
|
var me = this,
|
|
el = me.elements[index],
|
|
out = null;
|
|
|
|
if(el){
|
|
out = me.getElement(el);
|
|
}
|
|
return out;
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
filter : function(selector){
|
|
var els = [],
|
|
me = this,
|
|
fn = Ext.isFunction(selector) ? selector
|
|
: function(el){
|
|
return el.is(selector);
|
|
};
|
|
|
|
me.each(function(el, self, i) {
|
|
if (fn(el, i) !== false) {
|
|
els[els.length] = me.transformElement(el);
|
|
}
|
|
});
|
|
|
|
me.elements = els;
|
|
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(){
|
|
this.elements = [];
|
|
}
|
|
};
|
|
|
|
Ext.CompositeElementLite.prototype.on = Ext.CompositeElementLite.prototype.addListener;
|
|
|
|
|
|
Ext.CompositeElementLite.importElementMethods = function() {
|
|
var fnName,
|
|
ElProto = Ext.Element.prototype,
|
|
CelProto = Ext.CompositeElementLite.prototype;
|
|
|
|
for (fnName in ElProto) {
|
|
if (typeof ElProto[fnName] == 'function'){
|
|
(function(fnName) {
|
|
CelProto[fnName] = CelProto[fnName] || function() {
|
|
return this.invoke(fnName, arguments);
|
|
};
|
|
}).call(CelProto, fnName);
|
|
|
|
}
|
|
}
|
|
};
|
|
|
|
Ext.CompositeElementLite.importElementMethods();
|
|
|
|
if(Ext.DomQuery){
|
|
Ext.Element.selectorFunction = Ext.DomQuery.select;
|
|
}
|
|
|
|
|
|
Ext.Element.select = function(selector, root){
|
|
var els;
|
|
if(typeof selector == "string"){
|
|
els = Ext.Element.selectorFunction(selector, root);
|
|
}else if(selector.length !== undefined){
|
|
els = selector;
|
|
}else{
|
|
}
|
|
return new Ext.CompositeElementLite(els);
|
|
};
|
|
|
|
Ext.select = Ext.Element.select;
|
|
|
|
|
|
Ext.util.DelayedTask = function(fn, scope, args) {
|
|
var me = this,
|
|
id,
|
|
call = function() {
|
|
clearInterval(id);
|
|
id = null;
|
|
fn.apply(scope, args || []);
|
|
};
|
|
|
|
|
|
this.delay = function(delay, newFn, newScope, newArgs) {
|
|
me.cancel();
|
|
fn = newFn || fn;
|
|
scope = newScope || scope;
|
|
args = newArgs || args;
|
|
id = setInterval(call, delay);
|
|
};
|
|
|
|
|
|
this.cancel = function(){
|
|
if (id) {
|
|
clearInterval(id);
|
|
id = null;
|
|
}
|
|
};
|
|
};
|
|
Ext.require('Ext.util.DelayedTask', function() {
|
|
|
|
Ext.util.Event = Ext.extend(Object, (function() {
|
|
function createBuffered(handler, listener, o, scope) {
|
|
listener.task = new Ext.util.DelayedTask();
|
|
return function() {
|
|
listener.task.delay(o.buffer, handler, scope, Ext.Array.toArray(arguments));
|
|
};
|
|
}
|
|
|
|
function createDelayed(handler, listener, o, scope) {
|
|
return function() {
|
|
var task = new Ext.util.DelayedTask();
|
|
if (!listener.tasks) {
|
|
listener.tasks = [];
|
|
}
|
|
listener.tasks.push(task);
|
|
task.delay(o.delay || 10, handler, scope, Ext.Array.toArray(arguments));
|
|
};
|
|
}
|
|
|
|
function createSingle(handler, listener, o, scope) {
|
|
return function() {
|
|
listener.ev.removeListener(listener.fn, scope);
|
|
return handler.apply(scope, arguments);
|
|
};
|
|
}
|
|
|
|
return {
|
|
isEvent: true,
|
|
|
|
constructor: function(observable, name) {
|
|
this.name = name;
|
|
this.observable = observable;
|
|
this.listeners = [];
|
|
},
|
|
|
|
addListener: function(fn, scope, options) {
|
|
var me = this,
|
|
listener;
|
|
scope = scope || me.observable;
|
|
|
|
|
|
if (!me.isListening(fn, scope)) {
|
|
listener = me.createListener(fn, scope, options);
|
|
if (me.firing) {
|
|
|
|
me.listeners = me.listeners.slice(0);
|
|
}
|
|
me.listeners.push(listener);
|
|
}
|
|
},
|
|
|
|
createListener: function(fn, scope, o) {
|
|
o = o || {};
|
|
scope = scope || this.observable;
|
|
|
|
var listener = {
|
|
fn: fn,
|
|
scope: scope,
|
|
o: o,
|
|
ev: this
|
|
},
|
|
handler = fn;
|
|
|
|
|
|
|
|
if (o.single) {
|
|
handler = createSingle(handler, listener, o, scope);
|
|
}
|
|
if (o.delay) {
|
|
handler = createDelayed(handler, listener, o, scope);
|
|
}
|
|
if (o.buffer) {
|
|
handler = 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 || s == 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,
|
|
k;
|
|
index = me.findListener(fn, scope);
|
|
if (index != -1) {
|
|
listener = me.listeners[index];
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
Ext.Array.erase(me.listeners, index, 1);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
|
|
clearListeners: function() {
|
|
var listeners = this.listeners,
|
|
i = listeners.length;
|
|
|
|
while (i--) {
|
|
this.removeListener(listeners[i].fn, listeners[i].scope);
|
|
}
|
|
},
|
|
|
|
fire: function() {
|
|
var me = this,
|
|
listeners = me.listeners,
|
|
count = listeners.length,
|
|
i,
|
|
args,
|
|
listener;
|
|
|
|
if (count > 0) {
|
|
me.firing = true;
|
|
for (i = 0; i < count; i++) {
|
|
listener = listeners[i];
|
|
args = arguments.length ? Array.prototype.slice.call(arguments, 0) : [];
|
|
if (listener.o) {
|
|
args.push(listener.o);
|
|
}
|
|
if (listener && listener.fireFn.apply(listener.scope || me.observable, args) === false) {
|
|
return (me.firing = false);
|
|
}
|
|
}
|
|
}
|
|
me.firing = false;
|
|
return true;
|
|
}
|
|
};
|
|
})());
|
|
});
|
|
|
|
|
|
Ext.EventManager = {
|
|
|
|
|
|
|
|
|
|
hasBoundOnReady: false,
|
|
|
|
|
|
hasFiredReady: false,
|
|
|
|
|
|
readyTimeout: null,
|
|
|
|
|
|
hasOnReadyStateChange: false,
|
|
|
|
|
|
readyEvent: new Ext.util.Event(),
|
|
|
|
|
|
checkReadyState: function(){
|
|
var me = Ext.EventManager;
|
|
|
|
if(window.attachEvent){
|
|
|
|
|
|
if (window != top) {
|
|
return false;
|
|
}
|
|
try{
|
|
document.documentElement.doScroll('left');
|
|
}catch(e){
|
|
return false;
|
|
}
|
|
me.fireDocReady();
|
|
return true;
|
|
}
|
|
if (document.readyState == 'complete') {
|
|
me.fireDocReady();
|
|
return true;
|
|
}
|
|
me.readyTimeout = setTimeout(arguments.callee, 2);
|
|
return false;
|
|
},
|
|
|
|
|
|
bindReadyEvent: function(){
|
|
var me = Ext.EventManager;
|
|
if (me.hasBoundOnReady) {
|
|
return;
|
|
}
|
|
|
|
if (document.addEventListener) {
|
|
document.addEventListener('DOMContentLoaded', me.fireDocReady, false);
|
|
|
|
window.addEventListener('load', me.fireDocReady, false);
|
|
} else {
|
|
|
|
if (!me.checkReadyState()) {
|
|
document.attachEvent('onreadystatechange', me.checkReadyState);
|
|
me.hasOnReadyStateChange = true;
|
|
}
|
|
|
|
window.attachEvent('onload', me.fireDocReady, false);
|
|
}
|
|
me.hasBoundOnReady = true;
|
|
},
|
|
|
|
|
|
fireDocReady: function(){
|
|
var me = Ext.EventManager;
|
|
|
|
|
|
if (!me.hasFiredReady) {
|
|
me.hasFiredReady = true;
|
|
|
|
if (document.addEventListener) {
|
|
document.removeEventListener('DOMContentLoaded', me.fireDocReady, false);
|
|
window.removeEventListener('load', me.fireDocReady, false);
|
|
} else {
|
|
if (me.readyTimeout !== null) {
|
|
clearTimeout(me.readyTimeout);
|
|
}
|
|
if (me.hasOnReadyStateChange) {
|
|
document.detachEvent('onreadystatechange', me.checkReadyState);
|
|
}
|
|
window.detachEvent('onload', me.fireDocReady);
|
|
}
|
|
Ext.supports.init();
|
|
}
|
|
if (!Ext.isReady) {
|
|
Ext.isReady = true;
|
|
me.onWindowUnload();
|
|
me.readyEvent.fire();
|
|
}
|
|
},
|
|
|
|
|
|
onDocumentReady: function(fn, scope, options){
|
|
options = options || {};
|
|
var me = Ext.EventManager,
|
|
readyEvent = me.readyEvent;
|
|
|
|
|
|
options.single = true;
|
|
|
|
|
|
if (Ext.isReady) {
|
|
readyEvent.addListener(fn, scope, options);
|
|
readyEvent.fire();
|
|
} else {
|
|
options.delay = options.delay || 1;
|
|
readyEvent.addListener(fn, scope, options);
|
|
me.bindReadyEvent();
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
stoppedMouseDownEvent: new Ext.util.Event(),
|
|
|
|
|
|
propRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|freezeEvent)$/,
|
|
|
|
|
|
getId : function(element) {
|
|
var skipGarbageCollection = false,
|
|
id;
|
|
|
|
element = Ext.getDom(element);
|
|
|
|
if (element === document || element === window) {
|
|
id = element === document ? Ext.documentId : Ext.windowId;
|
|
}
|
|
else {
|
|
id = Ext.id(element);
|
|
}
|
|
|
|
if (element && (element.getElementById || element.navigator)) {
|
|
skipGarbageCollection = true;
|
|
}
|
|
|
|
if (!Ext.cache[id]){
|
|
Ext.Element.addToCache(new Ext.Element(element), id);
|
|
if (skipGarbageCollection) {
|
|
Ext.cache[id].skipGarbageCollection = true;
|
|
}
|
|
}
|
|
return id;
|
|
},
|
|
|
|
|
|
prepareListenerConfig: function(element, config, isRemove){
|
|
var me = this,
|
|
propRe = me.propRe,
|
|
key, value, args;
|
|
|
|
|
|
for (key in config) {
|
|
if (config.hasOwnProperty(key)) {
|
|
|
|
if (!propRe.test(key)) {
|
|
value = config[key];
|
|
|
|
|
|
if (Ext.isFunction(value)) {
|
|
|
|
args = [element, key, value, config.scope, config];
|
|
} else {
|
|
|
|
args = [element, key, value.fn, value.scope, value];
|
|
}
|
|
|
|
if (isRemove === true) {
|
|
me.removeListener.apply(this, args);
|
|
} else {
|
|
me.addListener.apply(me, args);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
normalizeEvent: function(eventName, fn){
|
|
if (/mouseenter|mouseleave/.test(eventName) && !Ext.supports.MouseEnterLeave) {
|
|
if (fn) {
|
|
fn = Ext.Function.createInterceptor(fn, this.contains, this);
|
|
}
|
|
eventName = eventName == 'mouseenter' ? 'mouseover' : 'mouseout';
|
|
} else if (eventName == 'mousewheel' && !Ext.supports.MouseWheel && !Ext.isOpera){
|
|
eventName = 'DOMMouseScroll';
|
|
}
|
|
return {
|
|
eventName: eventName,
|
|
fn: fn
|
|
};
|
|
},
|
|
|
|
|
|
contains: function(event){
|
|
var parent = event.browserEvent.currentTarget,
|
|
child = this.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') {
|
|
this.prepareListenerConfig(element, eventName);
|
|
return;
|
|
}
|
|
|
|
var dom = Ext.getDom(element),
|
|
bind,
|
|
wrap;
|
|
|
|
|
|
|
|
options = options || {};
|
|
|
|
bind = this.normalizeEvent(eventName, fn);
|
|
wrap = this.createListenerWrap(dom, eventName, bind.fn, scope, options);
|
|
|
|
|
|
if (dom.attachEvent) {
|
|
dom.attachEvent('on' + bind.eventName, wrap);
|
|
} else {
|
|
dom.addEventListener(bind.eventName, wrap, options.capture || false);
|
|
}
|
|
|
|
if (dom == document && eventName == 'mousedown') {
|
|
this.stoppedMouseDownEvent.addListener(wrap);
|
|
}
|
|
|
|
|
|
this.getEventListenerCache(dom, eventName).push({
|
|
fn: fn,
|
|
wrap: wrap,
|
|
scope: scope
|
|
});
|
|
},
|
|
|
|
|
|
removeListener : function(element, eventName, fn, scope) {
|
|
|
|
if (typeof eventName !== 'string') {
|
|
this.prepareListenerConfig(element, eventName, true);
|
|
return;
|
|
}
|
|
|
|
var dom = Ext.getDom(element),
|
|
cache = this.getEventListenerCache(dom, eventName),
|
|
bindName = this.normalizeEvent(eventName).eventName,
|
|
i = cache.length, j,
|
|
listener, wrap, tasks;
|
|
|
|
|
|
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 (dom.detachEvent) {
|
|
dom.detachEvent('on' + bindName, wrap);
|
|
} else {
|
|
dom.removeEventListener(bindName, wrap, false);
|
|
}
|
|
|
|
if (wrap && dom == document && eventName == 'mousedown') {
|
|
this.stoppedMouseDownEvent.removeListener(wrap);
|
|
}
|
|
|
|
|
|
Ext.Array.erase(cache, i, 1);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
removeAll : function(element){
|
|
var dom = Ext.getDom(element),
|
|
cache, ev;
|
|
if (!dom) {
|
|
return;
|
|
}
|
|
cache = this.getElementEventCache(dom);
|
|
|
|
for (ev in cache) {
|
|
if (cache.hasOwnProperty(ev)) {
|
|
this.removeListener(dom, ev);
|
|
}
|
|
}
|
|
Ext.cache[dom.id].events = {};
|
|
},
|
|
|
|
|
|
purgeElement : function(element, eventName) {
|
|
var dom = Ext.getDom(element),
|
|
i = 0, len;
|
|
|
|
if(eventName) {
|
|
this.removeListener(dom, eventName);
|
|
}
|
|
else {
|
|
this.removeAll(dom);
|
|
}
|
|
|
|
if(dom && dom.childNodes) {
|
|
for(len = element.childNodes.length; i < len; i++) {
|
|
this.purgeElement(element.childNodes[i], eventName);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
createListenerWrap : function(dom, ename, fn, scope, options) {
|
|
options = options || {};
|
|
|
|
var f, gen;
|
|
|
|
return function wrap(e, args) {
|
|
|
|
if (!gen) {
|
|
f = ['if(!Ext) {return;}'];
|
|
|
|
if(options.buffer || options.delay || options.freezeEvent) {
|
|
f.push('e = new Ext.EventObjectImpl(e, ' + (options.freezeEvent ? 'true' : 'false' ) + ');');
|
|
} else {
|
|
f.push('e = Ext.EventObject.setEvent(e);');
|
|
}
|
|
|
|
if (options.delegate) {
|
|
f.push('var t = e.getTarget("' + options.delegate + '", this);');
|
|
f.push('if(!t) {return;}');
|
|
} else {
|
|
f.push('var t = e.target;');
|
|
}
|
|
|
|
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('fn.call(scope || dom, e, t, options);');
|
|
|
|
if(options.single) {
|
|
f.push('Ext.EventManager.removeListener(dom, ename, fn, scope);');
|
|
}
|
|
|
|
if(options.delay) {
|
|
f.push('}, ' + options.delay + '));');
|
|
}
|
|
|
|
if(options.buffer) {
|
|
f.push('}, ' + options.buffer + ');');
|
|
}
|
|
|
|
gen = Ext.functionFactory('e', 'options', 'fn', 'scope', 'ename', 'dom', 'wrap', 'args', f.join('\n'));
|
|
}
|
|
|
|
gen.call(dom, e, options, fn, scope, ename, dom, wrap, args);
|
|
};
|
|
},
|
|
|
|
|
|
getEventListenerCache : function(element, eventName) {
|
|
if (!element) {
|
|
return [];
|
|
}
|
|
|
|
var eventCache = this.getElementEventCache(element);
|
|
return eventCache[eventName] || (eventCache[eventName] = []);
|
|
},
|
|
|
|
|
|
getElementEventCache : function(element) {
|
|
if (!element) {
|
|
return {};
|
|
}
|
|
var elementCache = Ext.cache[this.getId(element)];
|
|
return elementCache.events || (elementCache.events = {});
|
|
},
|
|
|
|
|
|
mouseLeaveRe: /(mouseout|mouseleave)/,
|
|
mouseEnterRe: /(mouseover|mouseenter)/,
|
|
|
|
|
|
stopEvent: function(event) {
|
|
this.stopPropagation(event);
|
|
this.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 (this.mouseLeaveRe.test(event.type)) {
|
|
target = event.toElement;
|
|
} else if (this.mouseEnterRe.test(event.type)) {
|
|
target = event.fromElement;
|
|
}
|
|
}
|
|
return this.resolveTextNode(target);
|
|
},
|
|
|
|
|
|
getPageX: function(event) {
|
|
return this.getXY(event)[0];
|
|
},
|
|
|
|
|
|
getPageY: function(event) {
|
|
return this.getXY(event)[1];
|
|
},
|
|
|
|
|
|
getPageXY: function(event) {
|
|
event = event.browserEvent || event;
|
|
var x = event.pageX,
|
|
y = event.pageY,
|
|
doc = document.documentElement,
|
|
body = document.body;
|
|
|
|
|
|
if (!x && x !== 0) {
|
|
x = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
|
|
y = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0);
|
|
}
|
|
return [x, y];
|
|
},
|
|
|
|
|
|
getTarget: function(event) {
|
|
event = event.browserEvent || event;
|
|
return this.resolveTextNode(event.target || event.srcElement);
|
|
},
|
|
|
|
|
|
|
|
resolveTextNode: Ext.isGecko ?
|
|
function(node) {
|
|
if (!node) {
|
|
return;
|
|
}
|
|
|
|
var s = HTMLElement.prototype.toString.call(node);
|
|
if (s == '[xpconnect wrapped native prototype]' || s == '[object XULElement]') {
|
|
return;
|
|
}
|
|
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 = this.resizeEvent;
|
|
if(!resize){
|
|
this.resizeEvent = resize = new Ext.util.Event();
|
|
this.on(window, 'resize', this.fireResize, this, {buffer: 100});
|
|
}
|
|
resize.addListener(fn, scope, options);
|
|
},
|
|
|
|
|
|
fireResize: function(){
|
|
var me = this,
|
|
w = Ext.Element.getViewWidth(),
|
|
h = Ext.Element.getViewHeight();
|
|
|
|
|
|
if(me.curHeight != h || me.curWidth != w){
|
|
me.curHeight = h;
|
|
me.curWidth = w;
|
|
me.resizeEvent.fire(w, h);
|
|
}
|
|
},
|
|
|
|
|
|
removeResizeListener: function(fn, scope){
|
|
if (this.resizeEvent) {
|
|
this.resizeEvent.removeListener(fn, scope);
|
|
}
|
|
},
|
|
|
|
onWindowUnload: function() {
|
|
var unload = this.unloadEvent;
|
|
if (!unload) {
|
|
this.unloadEvent = unload = new Ext.util.Event();
|
|
this.addListener(window, 'unload', this.fireUnload, this);
|
|
}
|
|
},
|
|
|
|
|
|
fireUnload: function() {
|
|
|
|
try {
|
|
this.removeUnloadListener();
|
|
|
|
if (Ext.isGecko3) {
|
|
var gridviews = Ext.ComponentQuery.query('gridview'),
|
|
i = 0,
|
|
ln = gridviews.length;
|
|
for (; i < ln; i++) {
|
|
gridviews[i].scrollToTop();
|
|
}
|
|
}
|
|
|
|
var el,
|
|
cache = Ext.cache;
|
|
for (el in cache) {
|
|
if (cache.hasOwnProperty(el)) {
|
|
Ext.EventManager.removeAll(el);
|
|
}
|
|
}
|
|
} catch(e) {
|
|
}
|
|
},
|
|
|
|
|
|
removeUnloadListener: function(){
|
|
if (this.unloadEvent) {
|
|
this.removeListener(window, 'unload', this.fireUnload);
|
|
}
|
|
},
|
|
|
|
|
|
useKeyDown: Ext.isWebKit ?
|
|
parseInt(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1], 10) >= 525 :
|
|
!((Ext.isGecko && !Ext.isWindows) || Ext.isOpera),
|
|
|
|
|
|
getKeyEvent: function(){
|
|
return this.useKeyDown ? 'keydown' : 'keypress';
|
|
}
|
|
};
|
|
|
|
|
|
Ext.onReady = function(fn, scope, options) {
|
|
Ext.Loader.onReady(fn, scope, true, options);
|
|
};
|
|
|
|
|
|
Ext.onDocumentReady = Ext.EventManager.onDocumentReady;
|
|
|
|
|
|
Ext.EventManager.on = Ext.EventManager.addListener;
|
|
|
|
|
|
Ext.EventManager.un = Ext.EventManager.removeListener;
|
|
|
|
(function(){
|
|
var initExtCss = function() {
|
|
|
|
var bd = document.body || document.getElementsByTagName('body')[0],
|
|
baseCSSPrefix = Ext.baseCSSPrefix,
|
|
cls = [baseCSSPrefix + 'body'],
|
|
htmlCls = [],
|
|
html;
|
|
|
|
if (!bd) {
|
|
return false;
|
|
}
|
|
|
|
html = bd.parentNode;
|
|
|
|
function add (c) {
|
|
cls.push(baseCSSPrefix + c);
|
|
}
|
|
|
|
|
|
if (Ext.isIE) {
|
|
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.isIE6 || Ext.isIE7) {
|
|
add('ie7m');
|
|
}
|
|
if (Ext.isIE6 || Ext.isIE7 || Ext.isIE8) {
|
|
add('ie8m');
|
|
}
|
|
if (Ext.isIE7 || Ext.isIE8) {
|
|
add('ie78');
|
|
}
|
|
}
|
|
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.isChrome) {
|
|
add('chrome');
|
|
}
|
|
if (Ext.isMac) {
|
|
add('mac');
|
|
}
|
|
if (Ext.isLinux) {
|
|
add('linux');
|
|
}
|
|
if (!Ext.supports.CSS3BorderRadius) {
|
|
add('nbr');
|
|
}
|
|
if (!Ext.supports.CSS3LinearGradient) {
|
|
add('nlg');
|
|
}
|
|
if (!Ext.scopeResetCSS) {
|
|
add('reset');
|
|
}
|
|
|
|
|
|
if (html) {
|
|
if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
|
|
Ext.isBorderBox = false;
|
|
}
|
|
else {
|
|
Ext.isBorderBox = true;
|
|
}
|
|
|
|
htmlCls.push(baseCSSPrefix + (Ext.isBorderBox ? 'border-box' : 'strict'));
|
|
if (!Ext.isStrict) {
|
|
htmlCls.push(baseCSSPrefix + 'quirks');
|
|
}
|
|
Ext.fly(html, '_internal').addCls(htmlCls);
|
|
}
|
|
|
|
Ext.fly(bd, '_internal').addCls(cls);
|
|
return true;
|
|
};
|
|
|
|
Ext.onReady(initExtCss);
|
|
})();
|
|
|
|
|
|
Ext.define('Ext.EventObjectImpl', {
|
|
uses: ['Ext.util.Point'],
|
|
|
|
|
|
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, options;
|
|
|
|
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;
|
|
}
|
|
options = {
|
|
type: event.type,
|
|
button: button,
|
|
shiftKey: event.shiftKey,
|
|
|
|
ctrlKey: event.ctrlKey || event.metaKey || false,
|
|
altKey: event.altKey,
|
|
|
|
keyCode: event.keyCode,
|
|
charCode: event.charCode,
|
|
|
|
target: Ext.EventManager.getTarget(event),
|
|
relatedTarget: Ext.EventManager.getRelatedTarget(event),
|
|
currentTarget: event.currentTarget,
|
|
xy: (freezeEvent ? me.getXY() : null)
|
|
};
|
|
} else {
|
|
options = {
|
|
button: -1,
|
|
shiftKey: false,
|
|
ctrlKey: false,
|
|
altKey: false,
|
|
keyCode: 0,
|
|
charCode: 0,
|
|
target: null,
|
|
xy: [0, 0]
|
|
};
|
|
}
|
|
Ext.apply(me, options);
|
|
return me;
|
|
},
|
|
|
|
|
|
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) {
|
|
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).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 Ext.create('Ext.util.Point', xy[0], xy[1]);
|
|
},
|
|
|
|
|
|
hasModifier : function(){
|
|
return this.ctrlKey || this.altKey || this.shiftKey || this.metaKey;
|
|
},
|
|
|
|
|
|
injectEvent: function () {
|
|
var API,
|
|
dispatchers = {};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!Ext.isIE && 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) {
|
|
var 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: function (t) {
|
|
return t;
|
|
}
|
|
};
|
|
}
|
|
|
|
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();
|
|
|
|
});
|
|
|
|
|
|
|
|
(function(){
|
|
var doc = document,
|
|
activeElement = null,
|
|
isCSS1 = doc.compatMode == "CSS1Compat",
|
|
ELEMENT = Ext.Element,
|
|
fly = function(el){
|
|
if (!_fly) {
|
|
_fly = new Ext.Element.Flyweight();
|
|
}
|
|
_fly.dom = el;
|
|
return _fly;
|
|
}, _fly;
|
|
|
|
|
|
|
|
|
|
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;
|
|
};
|
|
}
|
|
|
|
Ext.apply(ELEMENT, {
|
|
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;
|
|
},
|
|
|
|
|
|
getActiveElement: function () {
|
|
return doc.activeElement || activeElement;
|
|
},
|
|
|
|
|
|
getRightMarginFixCleaner: function (target) {
|
|
var supports = Ext.supports,
|
|
hasInputBug = supports.DisplayChangeInputSelectionBug,
|
|
hasTextAreaBug = supports.DisplayChangeTextAreaSelectionBug;
|
|
|
|
if (hasInputBug || hasTextAreaBug) {
|
|
var activeEl = doc.activeElement || activeElement,
|
|
tag = activeEl && activeEl.tagName,
|
|
start,
|
|
end;
|
|
|
|
if ((hasTextAreaBug && tag == 'TEXTAREA') ||
|
|
(hasInputBug && tag == 'INPUT' && activeEl.type == 'text')) {
|
|
if (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 ? ELEMENT.getDocumentWidth() : ELEMENT.getViewportWidth();
|
|
},
|
|
|
|
getViewHeight : function(full) {
|
|
return full ? ELEMENT.getDocumentHeight() : ELEMENT.getViewportHeight();
|
|
},
|
|
|
|
getDocumentHeight: function() {
|
|
return Math.max(!isCSS1 ? doc.body.scrollHeight : doc.documentElement.scrollHeight, ELEMENT.getViewportHeight());
|
|
},
|
|
|
|
getDocumentWidth: function() {
|
|
return Math.max(!isCSS1 ? doc.body.scrollWidth : doc.documentElement.scrollWidth, ELEMENT.getViewportWidth());
|
|
},
|
|
|
|
getViewportHeight: function(){
|
|
return Ext.isIE ?
|
|
(Ext.isStrict ? doc.documentElement.clientHeight : doc.body.clientHeight) :
|
|
self.innerHeight;
|
|
},
|
|
|
|
getViewportWidth : function() {
|
|
return (!Ext.isStrict && !Ext.isOpera) ? doc.body.clientWidth :
|
|
Ext.isIE ? doc.documentElement.clientWidth : self.innerWidth;
|
|
},
|
|
|
|
getY : function(el) {
|
|
return ELEMENT.getXY(el)[1];
|
|
},
|
|
|
|
getX : function(el) {
|
|
return ELEMENT.getXY(el)[0];
|
|
},
|
|
|
|
getOffsetParent: function (el) {
|
|
el = Ext.getDom(el);
|
|
try {
|
|
|
|
return el.offsetParent;
|
|
} catch (e) {
|
|
var body = document.body;
|
|
return (el == body) ? null : body;
|
|
}
|
|
},
|
|
|
|
getXY : function(el) {
|
|
var p,
|
|
pe,
|
|
b,
|
|
bt,
|
|
bl,
|
|
dbd,
|
|
x = 0,
|
|
y = 0,
|
|
scroll,
|
|
hasAbsolute,
|
|
bd = (doc.body || doc.documentElement),
|
|
ret;
|
|
|
|
el = Ext.getDom(el);
|
|
|
|
if(el != bd){
|
|
hasAbsolute = fly(el).isStyle("position", "absolute");
|
|
|
|
if (el.getBoundingClientRect) {
|
|
try {
|
|
b = el.getBoundingClientRect();
|
|
scroll = fly(document).getScroll();
|
|
ret = [ Math.round(b.left + scroll.left), Math.round(b.top + scroll.top) ];
|
|
} catch (e) {
|
|
|
|
}
|
|
}
|
|
|
|
if (!ret) {
|
|
for (p = el; p; p = ELEMENT.getOffsetParent(p)) {
|
|
pe = fly(p);
|
|
x += p.offsetLeft;
|
|
y += p.offsetTop;
|
|
|
|
hasAbsolute = hasAbsolute || pe.isStyle("position", "absolute");
|
|
|
|
if (Ext.isGecko) {
|
|
y += bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
|
|
x += bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
|
|
|
|
if (p != el && !pe.isStyle('overflow','visible')) {
|
|
x += bl;
|
|
y += bt;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Ext.isSafari && hasAbsolute) {
|
|
x -= bd.offsetLeft;
|
|
y -= bd.offsetTop;
|
|
}
|
|
|
|
if (Ext.isGecko && !hasAbsolute) {
|
|
dbd = fly(bd);
|
|
x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
|
|
y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
|
|
}
|
|
|
|
p = el.parentNode;
|
|
while (p && p != bd) {
|
|
if (!Ext.isOpera || (p.tagName != 'TR' && !fly(p).isStyle("display", "inline"))) {
|
|
x -= p.scrollLeft;
|
|
y -= p.scrollTop;
|
|
}
|
|
p = p.parentNode;
|
|
}
|
|
ret = [x,y];
|
|
}
|
|
}
|
|
return ret || [0,0];
|
|
},
|
|
|
|
setXY : function(el, xy) {
|
|
(el = Ext.fly(el, '_setXY')).position();
|
|
|
|
var pts = el.translatePoints(xy),
|
|
style = el.dom.style,
|
|
pos;
|
|
|
|
for (pos in pts) {
|
|
if (!isNaN(pts[pos])) {
|
|
style[pos] = pts[pos] + "px";
|
|
}
|
|
}
|
|
},
|
|
|
|
setX : function(el, x) {
|
|
ELEMENT.setXY(el, [x, false]);
|
|
},
|
|
|
|
setY : function(el, y) {
|
|
ELEMENT.setXY(el, [false, y]);
|
|
},
|
|
|
|
|
|
serializeForm: function(form) {
|
|
var fElements = form.elements || (document.forms[form] || Ext.getDom(form)).elements,
|
|
hasSubmit = false,
|
|
encoder = encodeURIComponent,
|
|
name,
|
|
data = '',
|
|
type,
|
|
hasValue;
|
|
|
|
Ext.each(fElements, function(element){
|
|
name = element.name;
|
|
type = element.type;
|
|
|
|
if (!element.disabled && name) {
|
|
if (/select-(one|multiple)/i.test(type)) {
|
|
Ext.each(element.options, function(opt){
|
|
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.Element.addMethods((function(){
|
|
var focusRe = /button|input|textarea|select|object/;
|
|
return {
|
|
|
|
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;
|
|
function fn(e) {
|
|
e.stopPropagation();
|
|
if (preventDefault) {
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
|
|
if (Ext.isArray(eventName)) {
|
|
Ext.each(eventName, function(e) {
|
|
me.on(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,
|
|
n = dom.firstChild,
|
|
nx,
|
|
ni = -1;
|
|
|
|
if (Ext.Element.data(dom, 'isCleaned') && forceReclean !== true) {
|
|
return me;
|
|
}
|
|
|
|
while (n) {
|
|
nx = n.nextSibling;
|
|
if (n.nodeType == 3) {
|
|
|
|
if (!(/\S/.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 {
|
|
|
|
Ext.fly(n).clean();
|
|
n.nodeIndex = ++ni;
|
|
}
|
|
n = nx;
|
|
}
|
|
|
|
Ext.Element.data(dom, 'isCleaned', true);
|
|
return me;
|
|
},
|
|
|
|
|
|
load : function(options) {
|
|
this.getLoader().load(options);
|
|
return this;
|
|
},
|
|
|
|
|
|
getLoader : function() {
|
|
var dom = this.dom,
|
|
data = Ext.Element.data,
|
|
loader = data(dom, 'loader');
|
|
|
|
if (!loader) {
|
|
loader = Ext.create('Ext.ElementLoader', {
|
|
target: this
|
|
});
|
|
data(dom, 'loader', loader);
|
|
}
|
|
return loader;
|
|
},
|
|
|
|
|
|
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 += '<span id="' + id + '"></span>';
|
|
|
|
interval = setInterval(function(){
|
|
if (!document.getElementById(id)) {
|
|
return false;
|
|
}
|
|
clearInterval(interval);
|
|
var DOC = document,
|
|
hd = DOC.getElementsByTagName("head")[0],
|
|
re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig,
|
|
srcRe = /\ssrc=([\'\"])(.*?)\1/i,
|
|
typeRe = /\stype=([\'\"])(.*?)\1/i,
|
|
match,
|
|
attrs,
|
|
srcMatch,
|
|
typeMatch,
|
|
el,
|
|
s;
|
|
|
|
while ((match = re.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]);
|
|
}
|
|
}
|
|
}
|
|
|
|
el = DOC.getElementById(id);
|
|
if (el) {
|
|
Ext.removeNode(el);
|
|
}
|
|
Ext.callback(callback, me);
|
|
}, 20);
|
|
dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, '');
|
|
return me;
|
|
},
|
|
|
|
|
|
removeAllListeners : function() {
|
|
this.removeAnchor();
|
|
Ext.EventManager.removeAll(this.dom);
|
|
return this;
|
|
},
|
|
|
|
|
|
getScopeParent: function(){
|
|
var parent = this.dom.parentNode;
|
|
return Ext.scopeResetCSS ? parent.parentNode : parent;
|
|
},
|
|
|
|
|
|
createProxy : function(config, renderTo, matchBox) {
|
|
config = (typeof config == 'object') ? config : {tag : "div", cls: config};
|
|
|
|
var me = this,
|
|
proxy = renderTo ? Ext.DomHelper.append(renderTo, config, true) :
|
|
Ext.DomHelper.insertBefore(me.dom, config, true);
|
|
|
|
proxy.setVisibilityMode(Ext.Element.DISPLAY);
|
|
proxy.hide();
|
|
if (matchBox && me.setBox && me.getBox) {
|
|
proxy.setBox(me.getBox());
|
|
}
|
|
return proxy;
|
|
},
|
|
|
|
|
|
focusable: function(){
|
|
var dom = this.dom,
|
|
nodeName = dom.nodeName.toLowerCase(),
|
|
canFocus = false,
|
|
hasTabIndex = !isNaN(dom.tabIndex);
|
|
|
|
if (!dom.disabled) {
|
|
if (focusRe.test(nodeName)) {
|
|
canFocus = true;
|
|
} else {
|
|
canFocus = nodeName == 'a' ? dom.href || hasTabIndex : hasTabIndex;
|
|
}
|
|
}
|
|
return canFocus && this.isVisible(true);
|
|
}
|
|
};
|
|
})());
|
|
Ext.Element.prototype.clearListeners = Ext.Element.prototype.removeAllListeners;
|
|
|
|
|
|
Ext.Element.addMethods({
|
|
|
|
getAnchorXY : function(anchor, local, s){
|
|
|
|
|
|
anchor = (anchor || "tl").toLowerCase();
|
|
s = s || {};
|
|
|
|
var me = this,
|
|
vp = me.dom == document.body || me.dom == document,
|
|
w = s.width || vp ? Ext.Element.getViewWidth() : me.getWidth(),
|
|
h = s.height || vp ? Ext.Element.getViewHeight() : me.getHeight(),
|
|
xy,
|
|
r = Math.round,
|
|
o = me.getXY(),
|
|
scroll = me.getScroll(),
|
|
extraX = vp ? scroll.left : !local ? o[0] : 0,
|
|
extraY = vp ? scroll.top : !local ? o[1] : 0,
|
|
hash = {
|
|
c : [r(w * 0.5), r(h * 0.5)],
|
|
t : [r(w * 0.5), 0],
|
|
l : [0, r(h * 0.5)],
|
|
r : [w, r(h * 0.5)],
|
|
b : [r(w * 0.5), h],
|
|
tl : [0, 0],
|
|
bl : [0, h],
|
|
br : [w, h],
|
|
tr : [w, 0]
|
|
};
|
|
|
|
xy = hash[anchor];
|
|
return [xy[0] + extraX, xy[1] + extraY];
|
|
},
|
|
|
|
|
|
anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
|
|
var me = this,
|
|
dom = me.dom,
|
|
scroll = !Ext.isEmpty(monitorScroll),
|
|
action = function(){
|
|
Ext.fly(dom).alignTo(el, alignment, offsets, animate);
|
|
Ext.callback(callback, Ext.fly(dom));
|
|
},
|
|
anchor = this.getAnchor();
|
|
|
|
|
|
this.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.call(me);
|
|
return me;
|
|
},
|
|
|
|
|
|
removeAnchor : function(){
|
|
var me = this,
|
|
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 me;
|
|
},
|
|
|
|
|
|
getAnchor : function(){
|
|
var data = Ext.Element.data,
|
|
dom = this.dom;
|
|
if (!dom) {
|
|
return;
|
|
}
|
|
var anchor = data(dom, '_anchor');
|
|
|
|
if(!anchor){
|
|
anchor = data(dom, '_anchor', {});
|
|
}
|
|
return anchor;
|
|
},
|
|
|
|
getAlignVector: function(el, spec, offset) {
|
|
var me = this,
|
|
side = {t:"top", l:"left", r:"right", b: "bottom"},
|
|
thisRegion = me.getRegion(),
|
|
elRegion;
|
|
|
|
el = Ext.get(el);
|
|
if(!el || !el.dom){
|
|
}
|
|
|
|
elRegion = el.getRegion();
|
|
},
|
|
|
|
|
|
getAlignToXY : function(el, p, o){
|
|
el = Ext.get(el);
|
|
|
|
if(!el || !el.dom){
|
|
}
|
|
|
|
o = o || [0,0];
|
|
p = (!p || p == "?" ? "tl-bl?" : (!(/-/).test(p) && p !== "" ? "tl-" + p : p || "tl-bl")).toLowerCase();
|
|
|
|
var me = this,
|
|
d = me.dom,
|
|
a1,
|
|
a2,
|
|
x,
|
|
y,
|
|
|
|
w,
|
|
h,
|
|
r,
|
|
dw = Ext.Element.getViewWidth() -10,
|
|
dh = Ext.Element.getViewHeight()-10,
|
|
p1y,
|
|
p1x,
|
|
p2y,
|
|
p2x,
|
|
swapY,
|
|
swapX,
|
|
doc = document,
|
|
docElement = doc.documentElement,
|
|
docBody = doc.body,
|
|
scrollX = (docElement.scrollLeft || docBody.scrollLeft || 0)+5,
|
|
scrollY = (docElement.scrollTop || docBody.scrollTop || 0)+5,
|
|
c = false,
|
|
p1 = "",
|
|
p2 = "",
|
|
m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
|
|
|
|
if(!m){
|
|
}
|
|
|
|
p1 = m[1];
|
|
p2 = m[2];
|
|
c = !!m[3];
|
|
|
|
|
|
|
|
a1 = me.getAnchorXY(p1, true);
|
|
a2 = el.getAnchorXY(p2, false);
|
|
|
|
x = a2[0] - a1[0] + o[0];
|
|
y = a2[1] - a1[1] + o[1];
|
|
|
|
if(c){
|
|
w = me.getWidth();
|
|
h = me.getHeight();
|
|
r = el.getRegion();
|
|
|
|
|
|
|
|
p1y = p1.charAt(0);
|
|
p1x = p1.charAt(p1.length-1);
|
|
p2y = p2.charAt(0);
|
|
p2x = p2.charAt(p2.length-1);
|
|
swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
|
|
swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
|
|
|
|
|
|
if (x + w > dw + scrollX) {
|
|
x = swapX ? r.left-w : dw+scrollX-w;
|
|
}
|
|
if (x < scrollX) {
|
|
x = swapX ? r.right : scrollX;
|
|
}
|
|
if (y + h > dh + scrollY) {
|
|
y = swapY ? r.top-h : dh+scrollY-h;
|
|
}
|
|
if (y < scrollY){
|
|
y = swapY ? r.bottom : scrollY;
|
|
}
|
|
}
|
|
return [x,y];
|
|
},
|
|
|
|
|
|
alignTo : function(element, position, offsets, animate){
|
|
var me = this;
|
|
return me.setXY(me.getAlignToXY(element, position, offsets),
|
|
me.anim && !!animate ? me.anim(animate) : false);
|
|
},
|
|
|
|
|
|
adjustForConstraints : function(xy, parent) {
|
|
var vector = this.getConstrainVector(parent, xy);
|
|
if (vector) {
|
|
xy[0] += vector[0];
|
|
xy[1] += vector[1];
|
|
}
|
|
return xy;
|
|
},
|
|
|
|
|
|
getConstrainVector: function(constrainTo, proposedPosition) {
|
|
if (!(constrainTo instanceof Ext.util.Region)) {
|
|
constrainTo = Ext.get(constrainTo).getViewRegion();
|
|
}
|
|
var thisRegion = this.getRegion(),
|
|
vector = [0, 0],
|
|
shadowSize = this.shadow && this.shadow.offset,
|
|
overflowed = false;
|
|
|
|
|
|
if (proposedPosition) {
|
|
thisRegion.translateBy(proposedPosition[0] - thisRegion.x, proposedPosition[1] - thisRegion.y);
|
|
}
|
|
|
|
|
|
|
|
if (shadowSize) {
|
|
constrainTo.adjust(0, -shadowSize, -shadowSize, shadowSize);
|
|
}
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
getCenterXY : function(){
|
|
return this.getAlignToXY(document, 'c-c');
|
|
},
|
|
|
|
|
|
center : function(centerIn){
|
|
return this.alignTo(centerIn || document, 'c-c');
|
|
}
|
|
});
|
|
|
|
|
|
(function(){
|
|
|
|
var ELEMENT = Ext.Element,
|
|
LEFT = "left",
|
|
RIGHT = "right",
|
|
TOP = "top",
|
|
BOTTOM = "bottom",
|
|
POSITION = "position",
|
|
STATIC = "static",
|
|
RELATIVE = "relative",
|
|
AUTO = "auto",
|
|
ZINDEX = "z-index";
|
|
|
|
Ext.override(Ext.Element, {
|
|
|
|
getX : function(){
|
|
return ELEMENT.getX(this.dom);
|
|
},
|
|
|
|
|
|
getY : function(){
|
|
return ELEMENT.getY(this.dom);
|
|
},
|
|
|
|
|
|
getXY : function(){
|
|
return ELEMENT.getXY(this.dom);
|
|
},
|
|
|
|
|
|
getOffsetsTo : function(el){
|
|
var o = this.getXY(),
|
|
e = Ext.fly(el, '_internal').getXY();
|
|
return [o[0]-e[0],o[1]-e[1]];
|
|
},
|
|
|
|
|
|
setX : function(x, animate){
|
|
return this.setXY([x, this.getY()], animate);
|
|
},
|
|
|
|
|
|
setY : function(y, animate){
|
|
return this.setXY([this.getX(), y], animate);
|
|
},
|
|
|
|
|
|
setLeft : function(left){
|
|
this.setStyle(LEFT, this.addUnits(left));
|
|
return this;
|
|
},
|
|
|
|
|
|
setTop : function(top){
|
|
this.setStyle(TOP, this.addUnits(top));
|
|
return this;
|
|
},
|
|
|
|
|
|
setRight : function(right){
|
|
this.setStyle(RIGHT, this.addUnits(right));
|
|
return this;
|
|
},
|
|
|
|
|
|
setBottom : function(bottom){
|
|
this.setStyle(BOTTOM, this.addUnits(bottom));
|
|
return this;
|
|
},
|
|
|
|
|
|
setXY: function(pos, animate) {
|
|
var me = this;
|
|
if (!animate || !me.anim) {
|
|
ELEMENT.setXY(me.dom, pos);
|
|
}
|
|
else {
|
|
if (!Ext.isObject(animate)) {
|
|
animate = {};
|
|
}
|
|
me.animate(Ext.applyIf({ to: { x: pos[0], y: pos[1] } }, animate));
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
setLocation : function(x, y, animate){
|
|
return this.setXY([x, y], animate);
|
|
},
|
|
|
|
|
|
moveTo : function(x, y, animate){
|
|
return this.setXY([x, y], animate);
|
|
},
|
|
|
|
|
|
getLeft : function(local){
|
|
return !local ? this.getX() : parseInt(this.getStyle(LEFT), 10) || 0;
|
|
},
|
|
|
|
|
|
getRight : function(local){
|
|
var me = this;
|
|
return !local ? me.getX() + me.getWidth() : (me.getLeft(true) + me.getWidth()) || 0;
|
|
},
|
|
|
|
|
|
getTop : function(local) {
|
|
return !local ? this.getY() : parseInt(this.getStyle(TOP), 10) || 0;
|
|
},
|
|
|
|
|
|
getBottom : function(local){
|
|
var me = this;
|
|
return !local ? me.getY() + me.getHeight() : (me.getTop(true) + me.getHeight()) || 0;
|
|
},
|
|
|
|
|
|
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]);
|
|
}
|
|
},
|
|
|
|
|
|
clearPositioning : function(value){
|
|
value = value || '';
|
|
this.setStyle({
|
|
left : value,
|
|
right : value,
|
|
top : value,
|
|
bottom : value,
|
|
"z-index" : "",
|
|
position : STATIC
|
|
});
|
|
return this;
|
|
},
|
|
|
|
|
|
getPositioning : function(){
|
|
var l = this.getStyle(LEFT);
|
|
var t = this.getStyle(TOP);
|
|
return {
|
|
"position" : this.getStyle(POSITION),
|
|
"left" : l,
|
|
"right" : l ? "" : this.getStyle(RIGHT),
|
|
"top" : t,
|
|
"bottom" : t ? "" : this.getStyle(BOTTOM),
|
|
"z-index" : this.getStyle(ZINDEX)
|
|
};
|
|
},
|
|
|
|
|
|
setPositioning : function(pc){
|
|
var me = this,
|
|
style = me.dom.style;
|
|
|
|
me.setStyle(pc);
|
|
|
|
if(pc.right == AUTO){
|
|
style.right = "";
|
|
}
|
|
if(pc.bottom == AUTO){
|
|
style.bottom = "";
|
|
}
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
translatePoints: function(x, y) {
|
|
if (Ext.isArray(x)) {
|
|
y = x[1];
|
|
x = x[0];
|
|
}
|
|
var me = this,
|
|
relative = me.isStyle(POSITION, RELATIVE),
|
|
o = me.getXY(),
|
|
left = parseInt(me.getStyle(LEFT), 10),
|
|
top = parseInt(me.getStyle(TOP), 10);
|
|
|
|
if (!Ext.isNumber(left)) {
|
|
left = relative ? 0 : me.dom.offsetLeft;
|
|
}
|
|
if (!Ext.isNumber(top)) {
|
|
top = relative ? 0 : me.dom.offsetTop;
|
|
}
|
|
left = (Ext.isNumber(x)) ? x - o[0] + left : undefined;
|
|
top = (Ext.isNumber(y)) ? y - o[1] + top : undefined;
|
|
return {
|
|
left: left,
|
|
top: top
|
|
};
|
|
},
|
|
|
|
|
|
setBox: function(box, adjust, animate) {
|
|
var me = this,
|
|
w = box.width,
|
|
h = box.height;
|
|
if ((adjust && !me.autoBoxAdjust) && !me.isBorderBox()) {
|
|
w -= (me.getBorderWidth("lr") + me.getPadding("lr"));
|
|
h -= (me.getBorderWidth("tb") + me.getPadding("tb"));
|
|
}
|
|
me.setBounds(box.x, box.y, w, h, animate);
|
|
return me;
|
|
},
|
|
|
|
|
|
getBox: function(contentBox, local) {
|
|
var me = this,
|
|
xy,
|
|
left,
|
|
top,
|
|
getBorderWidth = me.getBorderWidth,
|
|
getPadding = me.getPadding,
|
|
l, r, t, b, w, h, bx;
|
|
if (!local) {
|
|
xy = me.getXY();
|
|
} else {
|
|
left = parseInt(me.getStyle("left"), 10) || 0;
|
|
top = parseInt(me.getStyle("top"), 10) || 0;
|
|
xy = [left, top];
|
|
}
|
|
w = me.getWidth();
|
|
h = me.getHeight();
|
|
if (!contentBox) {
|
|
bx = {
|
|
x: xy[0],
|
|
y: xy[1],
|
|
0: xy[0],
|
|
1: xy[1],
|
|
width: w,
|
|
height: h
|
|
};
|
|
} else {
|
|
l = getBorderWidth.call(me, "l") + getPadding.call(me, "l");
|
|
r = getBorderWidth.call(me, "r") + getPadding.call(me, "r");
|
|
t = getBorderWidth.call(me, "t") + getPadding.call(me, "t");
|
|
b = getBorderWidth.call(me, "b") + getPadding.call(me, "b");
|
|
bx = {
|
|
x: xy[0] + l,
|
|
y: xy[1] + t,
|
|
0: xy[0] + l,
|
|
1: xy[1] + t,
|
|
width: w - (l + r),
|
|
height: h - (t + b)
|
|
};
|
|
}
|
|
bx.right = bx.x + bx.width;
|
|
bx.bottom = bx.y + bx.height;
|
|
return bx;
|
|
},
|
|
|
|
|
|
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.moveTo(hash[direction][0], hash[direction][1], animate);
|
|
},
|
|
|
|
|
|
setLeftTop: function(left, top) {
|
|
var me = this,
|
|
style = me.dom.style;
|
|
style.left = me.addUnits(left);
|
|
style.top = me.addUnits(top);
|
|
return me;
|
|
},
|
|
|
|
|
|
getRegion: function() {
|
|
return this.getPageBox(true);
|
|
},
|
|
|
|
|
|
getViewRegion: function() {
|
|
var me = this,
|
|
isBody = me.dom === document.body,
|
|
scroll, pos, top, left, width, height;
|
|
|
|
|
|
if (isBody) {
|
|
scroll = me.getScroll();
|
|
left = scroll.left;
|
|
top = scroll.top;
|
|
width = Ext.Element.getViewportWidth();
|
|
height = Ext.Element.getViewportHeight();
|
|
}
|
|
else {
|
|
pos = me.getXY();
|
|
left = pos[0] + me.getBorderWidth('l') + me.getPadding('l');
|
|
top = pos[1] + me.getBorderWidth('t') + me.getPadding('t');
|
|
width = me.getWidth(true);
|
|
height = me.getHeight(true);
|
|
}
|
|
|
|
return Ext.create('Ext.util.Region', top, left + width, top + height, left);
|
|
},
|
|
|
|
|
|
getPageBox : function(getRegion) {
|
|
var me = this,
|
|
el = me.dom,
|
|
isDoc = el === document.body,
|
|
w = isDoc ? Ext.Element.getViewWidth() : el.offsetWidth,
|
|
h = isDoc ? Ext.Element.getViewHeight() : el.offsetHeight,
|
|
xy = me.getXY(),
|
|
t = xy[1],
|
|
r = xy[0] + w,
|
|
b = xy[1] + h,
|
|
l = xy[0];
|
|
|
|
if (getRegion) {
|
|
return Ext.create('Ext.util.Region', t, r, b, l);
|
|
}
|
|
else {
|
|
return {
|
|
left: l,
|
|
top: t,
|
|
width: w,
|
|
height: h,
|
|
right: r,
|
|
bottom: b
|
|
};
|
|
}
|
|
},
|
|
|
|
|
|
setBounds: function(x, y, width, height, animate) {
|
|
var me = this;
|
|
if (!animate || !me.anim) {
|
|
me.setSize(width, height);
|
|
me.setLocation(x, y);
|
|
} else {
|
|
if (!Ext.isObject(animate)) {
|
|
animate = {};
|
|
}
|
|
me.animate(Ext.applyIf({
|
|
to: {
|
|
x: x,
|
|
y: y,
|
|
width: me.adjustWidth(width),
|
|
height: me.adjustHeight(height)
|
|
}
|
|
}, animate));
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
setRegion: function(region, animate) {
|
|
return this.setBounds(region.left, region.top, region.right - region.left, region.bottom - region.top, animate);
|
|
}
|
|
});
|
|
})();
|
|
|
|
|
|
Ext.override(Ext.Element, {
|
|
|
|
isScrollable : function(){
|
|
var dom = this.dom;
|
|
return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
|
|
},
|
|
|
|
|
|
getScroll : function() {
|
|
var d = this.dom,
|
|
doc = document,
|
|
body = doc.body,
|
|
docElement = doc.documentElement,
|
|
l,
|
|
t,
|
|
ret;
|
|
|
|
if (d == doc || d == body) {
|
|
if (Ext.isIE && Ext.isStrict) {
|
|
l = docElement.scrollLeft;
|
|
t = docElement.scrollTop;
|
|
} else {
|
|
l = window.pageXOffset;
|
|
t = window.pageYOffset;
|
|
}
|
|
ret = {
|
|
left: l || (body ? body.scrollLeft : 0),
|
|
top : t || (body ? body.scrollTop : 0)
|
|
};
|
|
} else {
|
|
ret = {
|
|
left: d.scrollLeft,
|
|
top : d.scrollTop
|
|
};
|
|
}
|
|
|
|
return ret;
|
|
},
|
|
|
|
|
|
scrollTo : function(side, value, animate) {
|
|
|
|
var top = /top/i.test(side),
|
|
me = this,
|
|
dom = me.dom,
|
|
obj = {},
|
|
prop;
|
|
if (!animate || !me.anim) {
|
|
|
|
prop = 'scroll' + (top ? 'Top' : 'Left');
|
|
dom[prop] = value;
|
|
}
|
|
else {
|
|
if (!Ext.isObject(animate)) {
|
|
animate = {};
|
|
}
|
|
obj['scroll' + (top ? 'Top' : 'Left')] = value;
|
|
me.animate(Ext.applyIf({
|
|
to: obj
|
|
}, animate));
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
scrollIntoView : function(container, hscroll) {
|
|
container = Ext.getDom(container) || Ext.getBody().dom;
|
|
var el = this.dom,
|
|
offsets = this.getOffsetsTo(container),
|
|
|
|
left = offsets[0] + container.scrollLeft,
|
|
top = offsets[1] + container.scrollTop,
|
|
bottom = top + el.offsetHeight,
|
|
right = left + el.offsetWidth,
|
|
|
|
ctClientHeight = container.clientHeight,
|
|
ctScrollTop = parseInt(container.scrollTop, 10),
|
|
ctScrollLeft = parseInt(container.scrollLeft, 10),
|
|
ctBottom = ctScrollTop + ctClientHeight,
|
|
ctRight = ctScrollLeft + container.clientWidth;
|
|
|
|
if (el.offsetHeight > ctClientHeight || top < ctScrollTop) {
|
|
container.scrollTop = top;
|
|
} else if (bottom > ctBottom) {
|
|
container.scrollTop = bottom - ctClientHeight;
|
|
}
|
|
|
|
container.scrollTop = container.scrollTop;
|
|
|
|
if (hscroll !== false) {
|
|
if (el.offsetWidth > container.clientWidth || left < ctScrollLeft) {
|
|
container.scrollLeft = left;
|
|
}
|
|
else if (right > ctRight) {
|
|
container.scrollLeft = right - container.clientWidth;
|
|
}
|
|
container.scrollLeft = container.scrollLeft;
|
|
}
|
|
return this;
|
|
},
|
|
|
|
|
|
scrollChildIntoView : function(child, hscroll) {
|
|
Ext.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
|
|
},
|
|
|
|
|
|
scroll : function(direction, distance, animate) {
|
|
if (!this.isScrollable()) {
|
|
return false;
|
|
}
|
|
var el = this.dom,
|
|
l = el.scrollLeft, t = el.scrollTop,
|
|
w = el.scrollWidth, h = el.scrollHeight,
|
|
cw = el.clientWidth, ch = el.clientHeight,
|
|
scrolled = false, v,
|
|
hash = {
|
|
l: Math.min(l + distance, w-cw),
|
|
r: v = Math.max(l - distance, 0),
|
|
t: Math.max(t - distance, 0),
|
|
b: Math.min(t + distance, h-ch)
|
|
};
|
|
hash.d = hash.b;
|
|
hash.u = hash.t;
|
|
|
|
direction = direction.substr(0, 1);
|
|
if ((v = hash[direction]) > -1) {
|
|
scrolled = true;
|
|
this.scrollTo(direction == 'l' || direction == 'r' ? 'left' : 'top', v, this.anim(animate));
|
|
}
|
|
return scrolled;
|
|
}
|
|
});
|
|
|
|
Ext.Element.addMethods(
|
|
function() {
|
|
var VISIBILITY = "visibility",
|
|
DISPLAY = "display",
|
|
HIDDEN = "hidden",
|
|
NONE = "none",
|
|
XMASKED = Ext.baseCSSPrefix + "masked",
|
|
XMASKEDRELATIVE = Ext.baseCSSPrefix + "masked-relative",
|
|
data = Ext.Element.data;
|
|
|
|
return {
|
|
|
|
isVisible : function(deep) {
|
|
var vis = !this.isStyle(VISIBILITY, HIDDEN) && !this.isStyle(DISPLAY, NONE),
|
|
p = this.dom.parentNode;
|
|
|
|
if (deep !== true || !vis) {
|
|
return vis;
|
|
}
|
|
|
|
while (p && !(/^body/i.test(p.tagName))) {
|
|
if (!Ext.fly(p, '_isVisible').isVisible()) {
|
|
return false;
|
|
}
|
|
p = p.parentNode;
|
|
}
|
|
return true;
|
|
},
|
|
|
|
|
|
isDisplayed : function() {
|
|
return !this.isStyle(DISPLAY, NONE);
|
|
},
|
|
|
|
|
|
enableDisplayMode : function(display) {
|
|
this.setVisibilityMode(Ext.Element.DISPLAY);
|
|
|
|
if (!Ext.isEmpty(display)) {
|
|
data(this.dom, 'originalDisplay', display);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
mask : function(msg, msgCls) {
|
|
var me = this,
|
|
dom = me.dom,
|
|
setExpression = dom.style.setExpression,
|
|
dh = Ext.DomHelper,
|
|
EXTELMASKMSG = Ext.baseCSSPrefix + "mask-msg",
|
|
el,
|
|
mask;
|
|
|
|
if (!(/^body/i.test(dom.tagName) && me.getStyle('position') == 'static')) {
|
|
me.addCls(XMASKEDRELATIVE);
|
|
}
|
|
el = data(dom, 'maskMsg');
|
|
if (el) {
|
|
el.remove();
|
|
}
|
|
el = data(dom, 'mask');
|
|
if (el) {
|
|
el.remove();
|
|
}
|
|
|
|
mask = dh.append(dom, {cls : Ext.baseCSSPrefix + "mask"}, true);
|
|
data(dom, 'mask', mask);
|
|
|
|
me.addCls(XMASKED);
|
|
mask.setDisplayed(true);
|
|
|
|
if (typeof msg == 'string') {
|
|
var mm = dh.append(dom, {cls : EXTELMASKMSG, cn:{tag:'div'}}, true);
|
|
data(dom, 'maskMsg', mm);
|
|
mm.dom.className = msgCls ? EXTELMASKMSG + " " + msgCls : EXTELMASKMSG;
|
|
mm.dom.firstChild.innerHTML = msg;
|
|
mm.setDisplayed(true);
|
|
mm.center(me);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!Ext.supports.IncludePaddingInWidthCalculation && setExpression) {
|
|
mask.dom.style.setExpression('width', 'this.parentNode.offsetWidth + "px"');
|
|
}
|
|
|
|
|
|
|
|
if (!Ext.supports.IncludePaddingInHeightCalculation && setExpression) {
|
|
mask.dom.style.setExpression('height', 'this.parentNode.offsetHeight + "px"');
|
|
}
|
|
|
|
else if (Ext.isIE && !(Ext.isIE7 && Ext.isStrict) && me.getStyle('height') == 'auto') {
|
|
mask.setSize(undefined, me.getHeight());
|
|
}
|
|
return mask;
|
|
},
|
|
|
|
|
|
unmask : function() {
|
|
var me = this,
|
|
dom = me.dom,
|
|
mask = data(dom, 'mask'),
|
|
maskMsg = data(dom, 'maskMsg');
|
|
|
|
if (mask) {
|
|
|
|
if (mask.dom.style.clearExpression) {
|
|
mask.dom.style.clearExpression('width');
|
|
mask.dom.style.clearExpression('height');
|
|
}
|
|
if (maskMsg) {
|
|
maskMsg.remove();
|
|
data(dom, 'maskMsg', undefined);
|
|
}
|
|
|
|
mask.remove();
|
|
data(dom, 'mask', undefined);
|
|
me.removeCls([XMASKED, XMASKEDRELATIVE]);
|
|
}
|
|
},
|
|
|
|
isMasked : function() {
|
|
var me = this,
|
|
mask = data(me.dom, 'mask'),
|
|
maskMsg = data(me.dom, 'maskMsg');
|
|
|
|
if (mask && mask.isVisible()) {
|
|
if (maskMsg) {
|
|
maskMsg.center(me);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
|
|
createShim : function() {
|
|
var el = document.createElement('iframe'),
|
|
shim;
|
|
|
|
el.frameBorder = '0';
|
|
el.className = Ext.baseCSSPrefix + 'shim';
|
|
el.src = Ext.SSL_SECURE_URL;
|
|
shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));
|
|
shim.autoBoxAdjust = false;
|
|
return shim;
|
|
}
|
|
};
|
|
}()
|
|
);
|
|
|
|
Ext.Element.addMethods({
|
|
|
|
addKeyListener : function(key, fn, scope){
|
|
var config;
|
|
if(typeof key != 'object' || Ext.isArray(key)){
|
|
config = {
|
|
key: key,
|
|
fn: fn,
|
|
scope: scope
|
|
};
|
|
}else{
|
|
config = {
|
|
key : key.key,
|
|
shift : key.shift,
|
|
ctrl : key.ctrl,
|
|
alt : key.alt,
|
|
fn: fn,
|
|
scope: scope
|
|
};
|
|
}
|
|
return Ext.create('Ext.util.KeyMap', this, config);
|
|
},
|
|
|
|
|
|
addKeyMap : function(config){
|
|
return Ext.create('Ext.util.KeyMap', this, config);
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.CompositeElementLite.importElementMethods();
|
|
|
|
|
|
Ext.apply(Ext.CompositeElementLite.prototype, {
|
|
addElements : function(els, root){
|
|
if(!els){
|
|
return this;
|
|
}
|
|
if(typeof els == "string"){
|
|
els = Ext.Element.selectorFunction(els, root);
|
|
}
|
|
var yels = this.elements;
|
|
Ext.each(els, function(e) {
|
|
yels.push(Ext.get(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){
|
|
var me = this,
|
|
els = this.elements,
|
|
el;
|
|
Ext.each(keys, function(val){
|
|
if ((el = (els[val] || els[val = me.indexOf(val)]))) {
|
|
if(removeDom){
|
|
if(el.dom){
|
|
el.remove();
|
|
}else{
|
|
Ext.removeNode(el);
|
|
}
|
|
}
|
|
Ext.Array.erase(els, val, 1);
|
|
}
|
|
});
|
|
return this;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.CompositeElement = Ext.extend(Ext.CompositeElementLite, {
|
|
|
|
constructor : function(els, root){
|
|
this.elements = [];
|
|
this.add(els, root);
|
|
},
|
|
|
|
|
|
getElement : function(el){
|
|
|
|
return el;
|
|
},
|
|
|
|
|
|
transformElement : function(el){
|
|
return Ext.get(el);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.Element.select = function(selector, unique, root){
|
|
var els;
|
|
if(typeof selector == "string"){
|
|
els = Ext.Element.selectorFunction(selector, root);
|
|
}else if(selector.length !== undefined){
|
|
els = selector;
|
|
}else{
|
|
}
|
|
return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);
|
|
};
|
|
|
|
|
|
Ext.select = Ext.Element.select;
|
|
|
|
|
|
|
|
|
|
Ext.define('Ext.util.Observable', {
|
|
|
|
|
|
|
|
requires: ['Ext.util.Event'],
|
|
|
|
statics: {
|
|
|
|
releaseCapture: function(o) {
|
|
o.fireEvent = this.prototype.fireEvent;
|
|
},
|
|
|
|
|
|
capture: function(o, fn, scope) {
|
|
o.fireEvent = Ext.Function.createInterceptor(o.fireEvent, fn, scope);
|
|
},
|
|
|
|
|
|
observe: function(cls, listeners) {
|
|
if (cls) {
|
|
if (!cls.isObservable) {
|
|
Ext.applyIf(cls, new this());
|
|
this.capture(cls.prototype, cls.fireEvent, cls);
|
|
}
|
|
if (Ext.isObject(listeners)) {
|
|
cls.on(listeners);
|
|
}
|
|
return cls;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
isObservable: true,
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
Ext.apply(me, config);
|
|
if (me.listeners) {
|
|
me.on(me.listeners);
|
|
delete me.listeners;
|
|
}
|
|
me.events = me.events || {};
|
|
|
|
if (me.bubbleEvents) {
|
|
me.enableBubble(me.bubbleEvents);
|
|
}
|
|
},
|
|
|
|
|
|
eventOptionsRe : /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate|element|vertical|horizontal|freezeEvent)$/,
|
|
|
|
|
|
addManagedListener : function(item, ename, fn, scope, options) {
|
|
var me = this,
|
|
managedListeners = me.managedListeners = me.managedListeners || [],
|
|
config;
|
|
|
|
if (typeof ename !== 'string') {
|
|
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, config.fn ? config : options);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
managedListeners.push({
|
|
item: item,
|
|
ename: ename,
|
|
fn: fn,
|
|
scope: scope,
|
|
options: options
|
|
});
|
|
|
|
item.on(ename, fn, scope, options);
|
|
}
|
|
},
|
|
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
managedListeners = me.managedListeners ? me.managedListeners.slice() : [];
|
|
|
|
for (i = 0, length = managedListeners.length; i < length; i++) {
|
|
me.removeManagedListenerItem(false, managedListeners[i], item, ename, fn, scope);
|
|
}
|
|
},
|
|
|
|
|
|
fireEvent: function(eventName) {
|
|
var name = eventName.toLowerCase(),
|
|
events = this.events,
|
|
event = events && events[name],
|
|
bubbles = event && event.bubble;
|
|
|
|
return this.continueFireEvent(name, Ext.Array.slice(arguments, 1), bubbles);
|
|
},
|
|
|
|
|
|
continueFireEvent: function(eventName, args, bubbles) {
|
|
var target = this,
|
|
queue, event,
|
|
ret = true;
|
|
|
|
do {
|
|
if (target.eventsSuspended === true) {
|
|
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;
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
ename = ename.toLowerCase();
|
|
me.events[ename] = me.events[ename] || true;
|
|
event = me.events[ename] || true;
|
|
if (Ext.isBoolean(event)) {
|
|
me.events[ename] = event = new Ext.util.Event(me, ename);
|
|
}
|
|
event.addListener(fn, scope, Ext.isObject(options) ? 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) {
|
|
event.removeListener(fn, scope);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
clearListeners: function() {
|
|
var events = this.events,
|
|
event,
|
|
key;
|
|
|
|
for (key in events) {
|
|
if (events.hasOwnProperty(key)) {
|
|
event = events[key];
|
|
if (event.isEvent) {
|
|
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,
|
|
args,
|
|
len,
|
|
i;
|
|
|
|
me.events = me.events || {};
|
|
if (Ext.isString(o)) {
|
|
args = arguments;
|
|
i = args.length;
|
|
|
|
while (i--) {
|
|
me.events[args[i]] = me.events[args[i]] || true;
|
|
}
|
|
} else {
|
|
Ext.applyIf(me.events, o);
|
|
}
|
|
},
|
|
|
|
|
|
hasListener: function(ename) {
|
|
var event = this.events[ename.toLowerCase()];
|
|
return event && event.isEvent === true && event.listeners.length > 0;
|
|
},
|
|
|
|
|
|
suspendEvents: function(queueSuspended) {
|
|
this.eventsSuspended = true;
|
|
if (queueSuspended && !this.eventQueue) {
|
|
this.eventQueue = [];
|
|
}
|
|
},
|
|
|
|
|
|
resumeEvents: function() {
|
|
var me = this,
|
|
queued = me.eventQueue;
|
|
|
|
me.eventsSuspended = false;
|
|
delete me.eventQueue;
|
|
|
|
if (queued) {
|
|
Ext.each(queued, function(e) {
|
|
me.continueFireEvent.apply(me, e);
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
relayEvents : function(origin, events, prefix) {
|
|
prefix = prefix || '';
|
|
var me = this,
|
|
len = events.length,
|
|
i = 0,
|
|
oldName,
|
|
newName;
|
|
|
|
for (; i < len; i++) {
|
|
oldName = events[i].substr(prefix.length);
|
|
newName = prefix + oldName;
|
|
me.events[newName] = me.events[newName] || true;
|
|
origin.on(oldName, me.createRelayer(newName));
|
|
}
|
|
},
|
|
|
|
|
|
createRelayer: function(newName){
|
|
var me = this;
|
|
return function(){
|
|
return me.fireEvent.apply(me, [newName].concat(Array.prototype.slice.call(arguments, 0, -1)));
|
|
};
|
|
},
|
|
|
|
|
|
enableBubble: function(events) {
|
|
var me = this;
|
|
if (!Ext.isEmpty(events)) {
|
|
events = Ext.isArray(events) ? events: Ext.Array.toArray(arguments);
|
|
Ext.each(events,
|
|
function(ename) {
|
|
ename = ename.toLowerCase();
|
|
var ce = me.events[ename] || true;
|
|
if (Ext.isBoolean(ce)) {
|
|
ce = new Ext.util.Event(me, ename);
|
|
me.events[ename] = ce;
|
|
}
|
|
ce.bubble = true;
|
|
});
|
|
}
|
|
}
|
|
}, function() {
|
|
|
|
this.createAlias({
|
|
|
|
on: 'addListener',
|
|
|
|
un: 'removeListener',
|
|
|
|
mon: 'addManagedListener',
|
|
|
|
mun: 'removeManagedListener'
|
|
});
|
|
|
|
|
|
this.observeClass = this.observe;
|
|
|
|
Ext.apply(Ext.util.Observable.prototype, function(){
|
|
|
|
|
|
|
|
function getMethodEvent(method){
|
|
var e = (this.methodEvents = this.methodEvents || {})[method],
|
|
returnValue,
|
|
v,
|
|
cancel,
|
|
obj = this;
|
|
|
|
if (!e) {
|
|
this.methodEvents[method] = e = {};
|
|
e.originalFn = this[method];
|
|
e.methodName = method;
|
|
e.before = [];
|
|
e.after = [];
|
|
|
|
var 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;
|
|
}
|
|
|
|
return {
|
|
|
|
|
|
|
|
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.util.Animate', {
|
|
|
|
uses: ['Ext.fx.Manager', 'Ext.fx.Anim'],
|
|
|
|
|
|
animate: function(animObj) {
|
|
var me = this;
|
|
if (Ext.fx.Manager.hasFxBlock(me.id)) {
|
|
return me;
|
|
}
|
|
Ext.fx.Manager.queueFx(Ext.create('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.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,
|
|
value,
|
|
keyValue;
|
|
|
|
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 != ''){
|
|
Ext.each(value.split('^'), function(val){
|
|
all.push(me.decodeValue(val));
|
|
}, me);
|
|
}
|
|
return all;
|
|
case 'o':
|
|
all = {};
|
|
if(value != ''){
|
|
Ext.each(value.split('^'), function(val){
|
|
keyValue = val.split('=');
|
|
all[keyValue[0]] = me.decodeValue(keyValue[1]);
|
|
}, me);
|
|
}
|
|
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.ComponentQuery', {
|
|
singleton: true,
|
|
uses: ['Ext.ComponentManager']
|
|
}, function() {
|
|
|
|
var cq = this,
|
|
|
|
|
|
|
|
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.ownerCt || candidate.floatParent))) {
|
|
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 EA = Ext.Array,
|
|
result = [],
|
|
i = 0,
|
|
length = items.length,
|
|
candidate;
|
|
for (; i < length; i++) {
|
|
candidate = items[i];
|
|
if (candidate.el ? candidate.el.hasCls(className) : EA.contains(candidate.initCls(), className)) {
|
|
result.push(candidate);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
|
|
filterByAttribute = function(items, property, operator, value) {
|
|
var result = [],
|
|
i = 0,
|
|
length = items.length,
|
|
candidate;
|
|
for (; i < length; i++) {
|
|
candidate = items[i];
|
|
if (!value ? !!candidate[property] : (String(candidate[property]) === value)) {
|
|
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.isArray(root)) {
|
|
workingItems = root;
|
|
}
|
|
|
|
|
|
|
|
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,
|
|
components = Ext.isArray(component) ? component : [component],
|
|
originalLength = components.length,
|
|
lastOperation = operations[operations.length-1],
|
|
ln, i;
|
|
|
|
components = filterItems(components, lastOperation);
|
|
if (components.length === originalLength) {
|
|
if (operations.length > 1) {
|
|
for (i = 0, ln = components.length; i < ln; i++) {
|
|
if (Ext.Array.indexOf(this.execute(), components[i]) === -1) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
|
|
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;
|
|
},
|
|
last: function(components) {
|
|
return components[components.length - 1];
|
|
}
|
|
},
|
|
|
|
|
|
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];
|
|
if (!query) {
|
|
this.cache[selector] = query = 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 query = this.cache[selector];
|
|
if (!query) {
|
|
this.cache[selector] = query = this.parse(selector);
|
|
}
|
|
return query.is(component);
|
|
},
|
|
|
|
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 (modeMatch[1]) {
|
|
operations.push({
|
|
mode: modeMatch[2]||modeMatch[1]
|
|
});
|
|
selector = selector.replace(modeMatch[0], '');
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return new cq.Query({
|
|
operations: operations
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
Ext.define('Ext.util.HashMap', {
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
|
|
|
|
|
|
constructor: function(config) {
|
|
config = config || {};
|
|
|
|
var me = this,
|
|
keyFn = config.keyFn;
|
|
|
|
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,
|
|
data;
|
|
|
|
if (arguments.length === 1) {
|
|
value = key;
|
|
key = me.getKey(value);
|
|
}
|
|
|
|
if (me.containsKey(key)) {
|
|
return me.replace(key, value);
|
|
}
|
|
|
|
data = me.getData(key, value);
|
|
key = data[0];
|
|
value = data[1];
|
|
me.map[key] = value;
|
|
++me.length;
|
|
me.fireEvent('add', me, key, value);
|
|
return value;
|
|
},
|
|
|
|
|
|
replace: function(key, value) {
|
|
var me = this,
|
|
map = me.map,
|
|
old;
|
|
|
|
if (!me.containsKey(key)) {
|
|
me.add(key, value);
|
|
}
|
|
old = map[key];
|
|
map[key] = value;
|
|
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.fireEvent('remove', me, key, value);
|
|
return true;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
|
|
get: function(key) {
|
|
return this.map[key];
|
|
},
|
|
|
|
|
|
clear: function( initial) {
|
|
var me = this;
|
|
me.map = {};
|
|
me.length = 0;
|
|
if (initial !== true) {
|
|
me.fireEvent('clear', me);
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
containsKey: function(key) {
|
|
return this.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(),
|
|
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.state.Manager', {
|
|
singleton: true,
|
|
requires: ['Ext.state.Provider'],
|
|
constructor: function() {
|
|
this.provider = Ext.create('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'
|
|
},
|
|
|
|
requires: ['Ext.state.Manager'],
|
|
|
|
|
|
|
|
|
|
stateful: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
saveDelay: 100,
|
|
|
|
autoGenIdRe: /^((\w+-)|(ext-comp-))\d{4,}$/i,
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
config = config || {};
|
|
if (Ext.isDefined(config.stateful)) {
|
|
me.stateful = config.stateful;
|
|
}
|
|
if (Ext.isDefined(config.saveDelay)) {
|
|
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.initStateEvents();
|
|
me.initState();
|
|
}
|
|
},
|
|
|
|
|
|
initStateEvents: function() {
|
|
this.addStateEvents(this.stateEvents);
|
|
},
|
|
|
|
|
|
addStateEvents: function(events){
|
|
if (!Ext.isArray(events)) {
|
|
events = [events];
|
|
}
|
|
|
|
var me = this,
|
|
i = 0,
|
|
len = events.length;
|
|
|
|
for (; i < len; ++i) {
|
|
me.on(events[i], me.onStateChange, me);
|
|
}
|
|
},
|
|
|
|
|
|
onStateChange: function(){
|
|
var me = this,
|
|
delay = me.saveDelay;
|
|
|
|
if (delay > 0) {
|
|
if (!me.stateTask) {
|
|
me.stateTask = Ext.create('Ext.util.DelayedTask', me.saveState, me);
|
|
}
|
|
me.stateTask.delay(me.saveDelay);
|
|
} else {
|
|
me.saveState();
|
|
}
|
|
},
|
|
|
|
|
|
saveState: function() {
|
|
var me = this,
|
|
id,
|
|
state;
|
|
|
|
if (me.stateful !== false) {
|
|
id = me.getStateId();
|
|
if (id) {
|
|
state = me.getState();
|
|
if (me.fireEvent('beforestatesave', me, state) !== false) {
|
|
Ext.state.Manager.set(id, state);
|
|
me.fireEvent('statesave', me, state);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getState: function(){
|
|
return null;
|
|
},
|
|
|
|
|
|
applyState: function(state) {
|
|
if (state) {
|
|
Ext.apply(this, state);
|
|
}
|
|
},
|
|
|
|
|
|
getStateId: function() {
|
|
var me = this,
|
|
id = me.stateId;
|
|
|
|
if (!id) {
|
|
id = me.autoGenIdRe.test(String(me.id)) ? null : me.id;
|
|
}
|
|
return id;
|
|
},
|
|
|
|
|
|
initState: function(){
|
|
var me = this,
|
|
id = me.getStateId(),
|
|
state;
|
|
|
|
if (me.stateful !== false) {
|
|
if (id) {
|
|
state = Ext.state.Manager.get(id);
|
|
if (state) {
|
|
state = Ext.apply({}, state);
|
|
if (me.fireEvent('beforestaterestore', me, state) !== false) {
|
|
me.applyState(state);
|
|
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;
|
|
Ext.each(propNames, function (propName) {
|
|
me.savePropToState(propName, state);
|
|
});
|
|
return state;
|
|
},
|
|
|
|
|
|
destroy: function(){
|
|
var task = this.stateTask;
|
|
if (task) {
|
|
task.cancel();
|
|
}
|
|
this.clearListeners();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.AbstractManager', {
|
|
|
|
|
|
|
|
requires: ['Ext.util.HashMap'],
|
|
|
|
|
|
|
|
typeName: 'type',
|
|
|
|
constructor: function(config) {
|
|
Ext.apply(this, config || {});
|
|
|
|
|
|
this.all = Ext.create('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;
|
|
|
|
if (all.containsKey(id)) {
|
|
item = all.get(id);
|
|
fn.call(scope || item, item);
|
|
} else {
|
|
all.on('add', function(map, key, item){
|
|
if (key == id) {
|
|
fn.call(scope || item, item);
|
|
all.un('add', fn, scope);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
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 (component instanceof Ext.AbstractComponent) {
|
|
return component;
|
|
}
|
|
else if (Ext.isString(component)) {
|
|
return Ext.createByAlias('widget.' + component);
|
|
}
|
|
else {
|
|
var type = component.xtype || defaultType,
|
|
config = component;
|
|
|
|
return Ext.createByAlias('widget.' + type, config);
|
|
}
|
|
},
|
|
|
|
registerType: function(type, cls) {
|
|
this.types[type] = cls;
|
|
cls[this.typeName] = type;
|
|
cls.prototype[this.typeName] = type;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.AbstractComponent', {
|
|
|
|
|
|
requires: [
|
|
'Ext.ComponentQuery',
|
|
'Ext.ComponentManager'
|
|
],
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable',
|
|
animate: 'Ext.util.Animate',
|
|
state: 'Ext.state.Stateful'
|
|
},
|
|
|
|
|
|
|
|
uses: [
|
|
'Ext.PluginManager',
|
|
'Ext.ComponentManager',
|
|
'Ext.Element',
|
|
'Ext.DomHelper',
|
|
'Ext.XTemplate',
|
|
'Ext.ComponentQuery',
|
|
'Ext.ComponentLoader',
|
|
'Ext.EventManager',
|
|
'Ext.layout.Layout',
|
|
'Ext.layout.component.Auto',
|
|
'Ext.LoadMask',
|
|
'Ext.ZIndexManager'
|
|
],
|
|
|
|
statics: {
|
|
AUTO_ID: 1000
|
|
},
|
|
|
|
|
|
|
|
isComponent: true,
|
|
|
|
getAutoId: function() {
|
|
return ++Ext.AbstractComponent.AUTO_ID;
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
renderTpl: 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',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
styleHtmlContent: false,
|
|
|
|
|
|
styleHtmlCls: Ext.baseCSSPrefix + 'html',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
autoShow: false,
|
|
|
|
|
|
autoRender: false,
|
|
|
|
needsLayout: false,
|
|
|
|
|
|
allowDomMove: true,
|
|
|
|
|
|
|
|
|
|
rendered: false,
|
|
|
|
|
|
componentLayoutCounter: 0,
|
|
|
|
weight: 0,
|
|
|
|
trimRe: /^\s+|\s+$/g,
|
|
spacesRe: /\s+/,
|
|
|
|
|
|
|
|
maskOnDisable: true,
|
|
|
|
|
|
constructor : function(config) {
|
|
var me = this,
|
|
i, len;
|
|
|
|
config = config || {};
|
|
me.initialConfig = config;
|
|
Ext.apply(me, config);
|
|
|
|
me.addEvents(
|
|
|
|
'beforeactivate',
|
|
|
|
'activate',
|
|
|
|
'beforedeactivate',
|
|
|
|
'deactivate',
|
|
|
|
'added',
|
|
|
|
'disable',
|
|
|
|
'enable',
|
|
|
|
'beforeshow',
|
|
|
|
'show',
|
|
|
|
'beforehide',
|
|
|
|
'hide',
|
|
|
|
'removed',
|
|
|
|
'beforerender',
|
|
|
|
'render',
|
|
|
|
'afterrender',
|
|
|
|
'beforedestroy',
|
|
|
|
'destroy',
|
|
|
|
'resize',
|
|
|
|
'move'
|
|
);
|
|
|
|
me.getId();
|
|
|
|
me.mons = [];
|
|
me.additionalCls = [];
|
|
me.renderData = me.renderData || {};
|
|
me.renderSelectors = me.renderSelectors || {};
|
|
|
|
if (me.plugins) {
|
|
me.plugins = [].concat(me.plugins);
|
|
me.constructPlugins();
|
|
}
|
|
|
|
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) {
|
|
me.plugins = [].concat(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.show();
|
|
}
|
|
|
|
},
|
|
|
|
initComponent: function () {
|
|
|
|
|
|
this.constructPlugins();
|
|
},
|
|
|
|
|
|
getState: function() {
|
|
var me = this,
|
|
layout = me.ownerCt ? (me.shadowOwnerCt || me.ownerCt).getLayout() : null,
|
|
state = {
|
|
collapsed: me.collapsed
|
|
},
|
|
width = me.width,
|
|
height = me.height,
|
|
cm = me.collapseMemento,
|
|
anchors;
|
|
|
|
|
|
|
|
if (me.collapsed && cm) {
|
|
if (Ext.isDefined(cm.data.width)) {
|
|
width = cm.width;
|
|
}
|
|
if (Ext.isDefined(cm.data.height)) {
|
|
height = cm.height;
|
|
}
|
|
}
|
|
|
|
|
|
if (layout && me.flex) {
|
|
state.flex = me.flex;
|
|
if (layout.perpendicularPrefix) {
|
|
state[layout.perpendicularPrefix] = me['get' + layout.perpendicularPrefixCap]();
|
|
} else {
|
|
}
|
|
}
|
|
|
|
else if (layout && me.anchor) {
|
|
state.anchor = me.anchor;
|
|
anchors = me.anchor.split(' ').concat(null);
|
|
if (!anchors[0]) {
|
|
if (me.width) {
|
|
state.width = width;
|
|
}
|
|
}
|
|
if (!anchors[1]) {
|
|
if (me.height) {
|
|
state.height = height;
|
|
}
|
|
}
|
|
}
|
|
|
|
else {
|
|
if (me.width) {
|
|
state.width = width;
|
|
}
|
|
if (me.height) {
|
|
state.height = height;
|
|
}
|
|
}
|
|
|
|
|
|
if (state.width == me.initialConfig.width) {
|
|
delete state.width;
|
|
}
|
|
if (state.height == me.initialConfig.height) {
|
|
delete state.height;
|
|
}
|
|
|
|
|
|
if (layout && layout.align && (layout.align.indexOf('stretch') !== -1)) {
|
|
delete state[layout.perpendicularPrefix];
|
|
}
|
|
return state;
|
|
},
|
|
|
|
show: Ext.emptyFn,
|
|
|
|
animate: function(animObj) {
|
|
var me = this,
|
|
to;
|
|
|
|
animObj = animObj || {};
|
|
to = animObj.to || {};
|
|
|
|
if (Ext.fx.Manager.hasFxBlock(me.id)) {
|
|
return me;
|
|
}
|
|
|
|
if (!animObj.dynamic && (to.height || to.width)) {
|
|
var curWidth = me.getWidth(),
|
|
w = curWidth,
|
|
curHeight = me.getHeight(),
|
|
h = curHeight,
|
|
needsResize = false;
|
|
|
|
if (to.height && to.height > curHeight) {
|
|
h = to.height;
|
|
needsResize = true;
|
|
}
|
|
if (to.width && to.width > curWidth) {
|
|
w = to.width;
|
|
needsResize = true;
|
|
}
|
|
|
|
|
|
|
|
|
|
if (needsResize) {
|
|
var clearWidth = !Ext.isNumber(me.width),
|
|
clearHeight = !Ext.isNumber(me.height);
|
|
|
|
me.componentLayout.childrenChanged = true;
|
|
me.setSize(w, h, me.ownerCt);
|
|
me.el.setSize(curWidth, curHeight);
|
|
if (clearWidth) {
|
|
delete me.width;
|
|
}
|
|
if (clearHeight) {
|
|
delete me.height;
|
|
}
|
|
}
|
|
}
|
|
return me.mixins.animate.animate.apply(me, arguments);
|
|
},
|
|
|
|
|
|
findLayoutController: function() {
|
|
return this.findParentBy(function(c) {
|
|
|
|
|
|
return !c.ownerCt || (c.layout.layoutBusy && !c.ownerCt.layout.layoutBusy);
|
|
});
|
|
},
|
|
|
|
onShow : function() {
|
|
|
|
var needsLayout = this.needsLayout;
|
|
if (Ext.isObject(needsLayout)) {
|
|
this.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
|
|
}
|
|
},
|
|
|
|
constructPlugin: function(plugin) {
|
|
if (plugin.ptype && typeof plugin.init != 'function') {
|
|
plugin.cmp = this;
|
|
plugin = Ext.PluginManager.create(plugin);
|
|
}
|
|
else if (typeof plugin == 'string') {
|
|
plugin = Ext.PluginManager.create({
|
|
ptype: plugin,
|
|
cmp: this
|
|
});
|
|
}
|
|
return plugin;
|
|
},
|
|
|
|
|
|
constructPlugins: function() {
|
|
var me = this,
|
|
plugins = me.plugins,
|
|
i, len;
|
|
|
|
if (plugins) {
|
|
for (i = 0, len = plugins.length; i < len; i++) {
|
|
|
|
plugins[i] = me.constructPlugin(plugins[i]);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
initPlugin : function(plugin) {
|
|
plugin.init(this);
|
|
|
|
return plugin;
|
|
},
|
|
|
|
|
|
doAutoRender: function() {
|
|
var me = this;
|
|
if (me.floating) {
|
|
me.render(document.body);
|
|
} else {
|
|
me.render(Ext.isBoolean(me.autoRender) ? Ext.getBody() : me.autoRender);
|
|
}
|
|
},
|
|
|
|
|
|
render : function(container, position) {
|
|
var me = this;
|
|
|
|
if (!me.rendered && me.fireEvent('beforerender', me) !== false) {
|
|
|
|
|
|
|
|
me.rendering = true;
|
|
|
|
|
|
|
|
if (me.el) {
|
|
me.el = Ext.get(me.el);
|
|
}
|
|
|
|
|
|
if (me.floating) {
|
|
me.onFloatRender();
|
|
}
|
|
|
|
container = me.initContainer(container);
|
|
|
|
me.onRender(container, position);
|
|
|
|
|
|
|
|
me.el.setVisibilityMode(Ext.Element[me.hideMode.toUpperCase()]);
|
|
|
|
if (me.overCls) {
|
|
me.el.hover(me.addOverCls, me.removeOverCls, me);
|
|
}
|
|
|
|
me.fireEvent('render', me);
|
|
|
|
me.initContent();
|
|
|
|
me.afterRender(container);
|
|
me.fireEvent('afterrender', me);
|
|
|
|
me.initEvents();
|
|
|
|
if (me.hidden) {
|
|
|
|
|
|
|
|
me.el.hide();
|
|
}
|
|
|
|
if (me.disabled) {
|
|
|
|
me.disable(true);
|
|
}
|
|
|
|
|
|
delete me.rendering;
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
onRender : function(container, position) {
|
|
var me = this,
|
|
el = me.el,
|
|
styles = me.initStyles(),
|
|
renderTpl, renderData, i;
|
|
|
|
position = me.getInsertPosition(position);
|
|
|
|
if (!el) {
|
|
if (position) {
|
|
el = Ext.DomHelper.insertBefore(position, me.getElConfig(), true);
|
|
}
|
|
else {
|
|
el = Ext.DomHelper.append(container, me.getElConfig(), true);
|
|
}
|
|
}
|
|
else if (me.allowDomMove !== false) {
|
|
if (position) {
|
|
container.dom.insertBefore(el.dom, position);
|
|
} else {
|
|
container.dom.appendChild(el.dom);
|
|
}
|
|
}
|
|
|
|
if (Ext.scopeResetCSS && !me.ownerCt) {
|
|
|
|
if (el.dom == Ext.getBody().dom) {
|
|
el.parent().addCls(Ext.baseCSSPrefix + 'reset');
|
|
}
|
|
else {
|
|
|
|
me.resetEl = el.wrap({
|
|
cls: Ext.baseCSSPrefix + 'reset'
|
|
});
|
|
}
|
|
}
|
|
|
|
me.setUI(me.ui);
|
|
|
|
el.addCls(me.initCls());
|
|
el.setStyle(styles);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
me.el = el;
|
|
|
|
me.initFrame();
|
|
|
|
renderTpl = me.initRenderTpl();
|
|
if (renderTpl) {
|
|
renderData = me.initRenderData();
|
|
renderTpl.append(me.getTargetEl(), renderData);
|
|
}
|
|
|
|
me.applyRenderSelectors();
|
|
|
|
me.rendered = true;
|
|
},
|
|
|
|
|
|
afterRender : function() {
|
|
var me = this,
|
|
pos,
|
|
xy;
|
|
|
|
me.getComponentLayout();
|
|
|
|
|
|
|
|
|
|
if (me.collapsed || (!me.ownerCt || (me.height || me.width))) {
|
|
me.setSize(me.width, me.height);
|
|
} else {
|
|
|
|
|
|
|
|
|
|
me.renderChildren();
|
|
}
|
|
|
|
|
|
|
|
if (me.floating && (me.x === undefined || me.y === undefined)) {
|
|
if (me.floatParent) {
|
|
xy = me.el.getAlignToXY(me.floatParent.getTargetEl(), 'c-c');
|
|
pos = me.floatParent.getTargetEl().translatePoints(xy[0], xy[1]);
|
|
} else {
|
|
xy = me.el.getAlignToXY(me.container, 'c-c');
|
|
pos = me.container.translatePoints(xy[0], xy[1]);
|
|
}
|
|
me.x = me.x === undefined ? pos.left: me.x;
|
|
me.y = me.y === undefined ? pos.top: me.y;
|
|
}
|
|
|
|
if (Ext.isDefined(me.x) || Ext.isDefined(me.y)) {
|
|
me.setPosition(me.x, me.y);
|
|
}
|
|
|
|
if (me.styleHtmlContent) {
|
|
me.getTargetEl().addCls(me.styleHtmlCls);
|
|
}
|
|
},
|
|
|
|
|
|
registerFloatingItem: function(cmp) {
|
|
var me = this;
|
|
if (!me.floatingItems) {
|
|
me.floatingItems = Ext.create('Ext.ZIndexManager', me);
|
|
}
|
|
me.floatingItems.register(cmp);
|
|
},
|
|
|
|
renderChildren: function () {
|
|
var me = this,
|
|
layout = me.getComponentLayout();
|
|
|
|
me.suspendLayout = true;
|
|
layout.renderChildren();
|
|
delete me.suspendLayout;
|
|
},
|
|
|
|
frameCls: Ext.baseCSSPrefix + 'frame',
|
|
|
|
frameIdRegex: /[-]frame\d+[TMB][LCR]$/,
|
|
|
|
frameElementCls: {
|
|
tl: [],
|
|
tc: [],
|
|
tr: [],
|
|
ml: [],
|
|
mc: [],
|
|
mr: [],
|
|
bl: [],
|
|
bc: [],
|
|
br: []
|
|
},
|
|
|
|
frameTpl: [
|
|
'<tpl if="top">',
|
|
'<tpl if="left"><div id="{fgid}TL" class="{frameCls}-tl {baseCls}-tl {baseCls}-{ui}-tl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tl</tpl></tpl>" style="background-position: {tl}; padding-left: {frameWidth}px" role="presentation"></tpl>',
|
|
'<tpl if="right"><div id="{fgid}TR" class="{frameCls}-tr {baseCls}-tr {baseCls}-{ui}-tr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tr</tpl></tpl>" style="background-position: {tr}; padding-right: {frameWidth}px" role="presentation"></tpl>',
|
|
'<div id="{fgid}TC" class="{frameCls}-tc {baseCls}-tc {baseCls}-{ui}-tc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tc</tpl></tpl>" style="background-position: {tc}; height: {frameWidth}px" role="presentation"></div>',
|
|
'<tpl if="right"></div></tpl>',
|
|
'<tpl if="left"></div></tpl>',
|
|
'</tpl>',
|
|
'<tpl if="left"><div id="{fgid}ML" class="{frameCls}-ml {baseCls}-ml {baseCls}-{ui}-ml<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-ml</tpl></tpl>" style="background-position: {ml}; padding-left: {frameWidth}px" role="presentation"></tpl>',
|
|
'<tpl if="right"><div id="{fgid}MR" class="{frameCls}-mr {baseCls}-mr {baseCls}-{ui}-mr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mr</tpl></tpl>" style="background-position: {mr}; padding-right: {frameWidth}px" role="presentation"></tpl>',
|
|
'<div id="{fgid}MC" class="{frameCls}-mc {baseCls}-mc {baseCls}-{ui}-mc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mc</tpl></tpl>" role="presentation"></div>',
|
|
'<tpl if="right"></div></tpl>',
|
|
'<tpl if="left"></div></tpl>',
|
|
'<tpl if="bottom">',
|
|
'<tpl if="left"><div id="{fgid}BL" class="{frameCls}-bl {baseCls}-bl {baseCls}-{ui}-bl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bl</tpl></tpl>" style="background-position: {bl}; padding-left: {frameWidth}px" role="presentation"></tpl>',
|
|
'<tpl if="right"><div id="{fgid}BR" class="{frameCls}-br {baseCls}-br {baseCls}-{ui}-br<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-br</tpl></tpl>" style="background-position: {br}; padding-right: {frameWidth}px" role="presentation"></tpl>',
|
|
'<div id="{fgid}BC" class="{frameCls}-bc {baseCls}-bc {baseCls}-{ui}-bc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bc</tpl></tpl>" style="background-position: {bc}; height: {frameWidth}px" role="presentation"></div>',
|
|
'<tpl if="right"></div></tpl>',
|
|
'<tpl if="left"></div></tpl>',
|
|
'</tpl>'
|
|
],
|
|
|
|
frameTableTpl: [
|
|
'<table><tbody>',
|
|
'<tpl if="top">',
|
|
'<tr>',
|
|
'<tpl if="left"><td id="{fgid}TL" class="{frameCls}-tl {baseCls}-tl {baseCls}-{ui}-tl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tl</tpl></tpl>" style="background-position: {tl}; padding-left:{frameWidth}px" role="presentation"></td></tpl>',
|
|
'<td id="{fgid}TC" class="{frameCls}-tc {baseCls}-tc {baseCls}-{ui}-tc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tc</tpl></tpl>" style="background-position: {tc}; height: {frameWidth}px" role="presentation"></td>',
|
|
'<tpl if="right"><td id="{fgid}TR" class="{frameCls}-tr {baseCls}-tr {baseCls}-{ui}-tr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-tr</tpl></tpl>" style="background-position: {tr}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
|
|
'</tr>',
|
|
'</tpl>',
|
|
'<tr>',
|
|
'<tpl if="left"><td id="{fgid}ML" class="{frameCls}-ml {baseCls}-ml {baseCls}-{ui}-ml<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-ml</tpl></tpl>" style="background-position: {ml}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
|
|
'<td id="{fgid}MC" class="{frameCls}-mc {baseCls}-mc {baseCls}-{ui}-mc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mc</tpl></tpl>" style="background-position: 0 0;" role="presentation"></td>',
|
|
'<tpl if="right"><td id="{fgid}MR" class="{frameCls}-mr {baseCls}-mr {baseCls}-{ui}-mr<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-mr</tpl></tpl>" style="background-position: {mr}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
|
|
'</tr>',
|
|
'<tpl if="bottom">',
|
|
'<tr>',
|
|
'<tpl if="left"><td id="{fgid}BL" class="{frameCls}-bl {baseCls}-bl {baseCls}-{ui}-bl<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bl</tpl></tpl>" style="background-position: {bl}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
|
|
'<td id="{fgid}BC" class="{frameCls}-bc {baseCls}-bc {baseCls}-{ui}-bc<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-bc</tpl></tpl>" style="background-position: {bc}; height: {frameWidth}px" role="presentation"></td>',
|
|
'<tpl if="right"><td id="{fgid}BR" class="{frameCls}-br {baseCls}-br {baseCls}-{ui}-br<tpl if="uiCls"><tpl for="uiCls"> {parent.baseCls}-{parent.ui}-{.}-br</tpl></tpl>" style="background-position: {br}; padding-left: {frameWidth}px" role="presentation"></td></tpl>',
|
|
'</tr>',
|
|
'</tpl>',
|
|
'</tbody></table>'
|
|
],
|
|
|
|
|
|
initFrame : function() {
|
|
if (Ext.supports.CSS3BorderRadius) {
|
|
return false;
|
|
}
|
|
|
|
var me = this,
|
|
frameInfo = me.getFrameInfo(),
|
|
frameWidth = frameInfo.width,
|
|
frameTpl = me.getFrameTpl(frameInfo.table),
|
|
frameGenId;
|
|
|
|
if (me.frame) {
|
|
|
|
|
|
me.frameGenId = frameGenId = (me.frameGenId || 0) + 1;
|
|
frameGenId = me.id + '-frame' + frameGenId;
|
|
|
|
|
|
frameTpl.insertFirst(me.el, Ext.apply({}, {
|
|
fgid: frameGenId,
|
|
ui: me.ui,
|
|
uiCls: me.uiCls,
|
|
frameCls: me.frameCls,
|
|
baseCls: me.baseCls,
|
|
frameWidth: frameWidth,
|
|
top: !!frameInfo.top,
|
|
left: !!frameInfo.left,
|
|
right: !!frameInfo.right,
|
|
bottom: !!frameInfo.bottom
|
|
}, me.getFramePositions(frameInfo)));
|
|
|
|
|
|
me.frameBody = me.el.down('.' + me.frameCls + '-mc');
|
|
|
|
|
|
me.removeChildEls(function (c) {
|
|
return c.id && me.frameIdRegex.test(c.id);
|
|
});
|
|
|
|
|
|
Ext.each(['TL','TC','TR','ML','MC','MR','BL','BC','BR'], function (suffix) {
|
|
me.childEls.push({ name: 'frame' + suffix, id: frameGenId + suffix });
|
|
});
|
|
}
|
|
},
|
|
|
|
updateFrame: function() {
|
|
if (Ext.supports.CSS3BorderRadius) {
|
|
return false;
|
|
}
|
|
|
|
var me = this,
|
|
wasTable = this.frameSize && this.frameSize.table,
|
|
oldFrameTL = this.frameTL,
|
|
oldFrameBL = this.frameBL,
|
|
oldFrameML = this.frameML,
|
|
oldFrameMC = this.frameMC,
|
|
newMCClassName;
|
|
|
|
this.initFrame();
|
|
|
|
if (oldFrameMC) {
|
|
if (me.frame) {
|
|
|
|
delete me.frameTL;
|
|
delete me.frameTC;
|
|
delete me.frameTR;
|
|
delete me.frameML;
|
|
delete me.frameMC;
|
|
delete me.frameMR;
|
|
delete me.frameBL;
|
|
delete me.frameBC;
|
|
delete me.frameBR;
|
|
this.applyRenderSelectors();
|
|
|
|
|
|
newMCClassName = this.frameMC.dom.className;
|
|
|
|
|
|
oldFrameMC.insertAfter(this.frameMC);
|
|
this.frameMC.remove();
|
|
|
|
|
|
this.frameBody = this.frameMC = oldFrameMC;
|
|
|
|
|
|
oldFrameMC.dom.className = newMCClassName;
|
|
|
|
|
|
if (wasTable) {
|
|
me.el.query('> table')[1].remove();
|
|
}
|
|
else {
|
|
if (oldFrameTL) {
|
|
oldFrameTL.remove();
|
|
}
|
|
if (oldFrameBL) {
|
|
oldFrameBL.remove();
|
|
}
|
|
oldFrameML.remove();
|
|
}
|
|
}
|
|
else {
|
|
|
|
|
|
}
|
|
}
|
|
else if (me.frame) {
|
|
this.applyRenderSelectors();
|
|
}
|
|
},
|
|
|
|
getFrameInfo: function() {
|
|
if (Ext.supports.CSS3BorderRadius) {
|
|
return false;
|
|
}
|
|
|
|
var me = this,
|
|
left = me.el.getStyle('background-position-x'),
|
|
top = me.el.getStyle('background-position-y'),
|
|
info, frameInfo = false, max;
|
|
|
|
|
|
|
|
if (!left && !top) {
|
|
info = me.el.getStyle('background-position').split(' ');
|
|
left = info[0];
|
|
top = info[1];
|
|
}
|
|
|
|
|
|
|
|
|
|
if (parseInt(left, 10) >= 1000000 && parseInt(top, 10) >= 1000000) {
|
|
max = Math.max;
|
|
|
|
frameInfo = {
|
|
|
|
table: left.substr(0, 3) == '110',
|
|
|
|
|
|
vertical: top.substr(0, 3) == '110',
|
|
|
|
|
|
top: max(left.substr(3, 2), left.substr(5, 2)),
|
|
right: max(left.substr(5, 2), top.substr(3, 2)),
|
|
bottom: max(top.substr(3, 2), top.substr(5, 2)),
|
|
left: max(top.substr(5, 2), left.substr(3, 2))
|
|
};
|
|
|
|
frameInfo.width = max(frameInfo.top, frameInfo.right, frameInfo.bottom, frameInfo.left);
|
|
|
|
|
|
me.el.setStyle('background-image', 'none');
|
|
}
|
|
|
|
|
|
|
|
if (me.frame === true && !frameInfo) {
|
|
}
|
|
|
|
me.frame = me.frame || !!frameInfo;
|
|
me.frameSize = frameInfo || false;
|
|
|
|
return frameInfo;
|
|
},
|
|
|
|
getFramePositions: function(frameInfo) {
|
|
var me = this,
|
|
frameWidth = frameInfo.width,
|
|
dock = me.dock,
|
|
positions, tc, bc, ml, mr;
|
|
|
|
if (frameInfo.vertical) {
|
|
tc = '0 -' + (frameWidth * 0) + 'px';
|
|
bc = '0 -' + (frameWidth * 1) + 'px';
|
|
|
|
if (dock && dock == "right") {
|
|
tc = 'right -' + (frameWidth * 0) + 'px';
|
|
bc = 'right -' + (frameWidth * 1) + 'px';
|
|
}
|
|
|
|
positions = {
|
|
tl: '0 -' + (frameWidth * 0) + 'px',
|
|
tr: '0 -' + (frameWidth * 1) + 'px',
|
|
bl: '0 -' + (frameWidth * 2) + 'px',
|
|
br: '0 -' + (frameWidth * 3) + 'px',
|
|
|
|
ml: '-' + (frameWidth * 1) + 'px 0',
|
|
mr: 'right 0',
|
|
|
|
tc: tc,
|
|
bc: bc
|
|
};
|
|
} else {
|
|
ml = '-' + (frameWidth * 0) + 'px 0';
|
|
mr = 'right 0';
|
|
|
|
if (dock && dock == "bottom") {
|
|
ml = 'left bottom';
|
|
mr = 'right bottom';
|
|
}
|
|
|
|
positions = {
|
|
tl: '0 -' + (frameWidth * 2) + 'px',
|
|
tr: 'right -' + (frameWidth * 3) + 'px',
|
|
bl: '0 -' + (frameWidth * 4) + 'px',
|
|
br: 'right -' + (frameWidth * 5) + 'px',
|
|
|
|
ml: ml,
|
|
mr: mr,
|
|
|
|
tc: '0 -' + (frameWidth * 0) + 'px',
|
|
bc: '0 -' + (frameWidth * 1) + 'px'
|
|
};
|
|
}
|
|
|
|
return positions;
|
|
},
|
|
|
|
|
|
getFrameTpl : function(table) {
|
|
return table ? this.getTpl('frameTableTpl') : this.getTpl('frameTpl');
|
|
},
|
|
|
|
|
|
initCls: function() {
|
|
var me = this,
|
|
cls = [];
|
|
|
|
cls.push(me.baseCls);
|
|
|
|
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;
|
|
}
|
|
if (me.cls) {
|
|
cls.push(me.cls);
|
|
delete me.cls;
|
|
}
|
|
|
|
return cls.concat(me.additionalCls);
|
|
},
|
|
|
|
|
|
setUI: function(ui) {
|
|
var me = this,
|
|
oldUICls = Ext.Array.clone(me.uiCls),
|
|
newUICls = [],
|
|
classes = [],
|
|
cls,
|
|
i;
|
|
|
|
|
|
for (i = 0; i < oldUICls.length; i++) {
|
|
cls = oldUICls[i];
|
|
|
|
classes = classes.concat(me.removeClsWithUI(cls, true));
|
|
newUICls.push(cls);
|
|
}
|
|
|
|
if (classes.length) {
|
|
me.removeCls(classes);
|
|
}
|
|
|
|
|
|
me.removeUIFromElement();
|
|
|
|
|
|
me.ui = ui;
|
|
|
|
|
|
me.addUIToElement();
|
|
|
|
|
|
classes = [];
|
|
for (i = 0; i < newUICls.length; i++) {
|
|
cls = newUICls[i];
|
|
classes = classes.concat(me.addClsWithUI(cls, true));
|
|
}
|
|
|
|
if (classes.length) {
|
|
me.addCls(classes);
|
|
}
|
|
},
|
|
|
|
|
|
addClsWithUI: function(cls, skip) {
|
|
var me = this,
|
|
classes = [],
|
|
i;
|
|
|
|
if (!Ext.isArray(cls)) {
|
|
cls = [cls];
|
|
}
|
|
|
|
for (i = 0; i < cls.length; i++) {
|
|
if (cls[i] && !me.hasUICls(cls[i])) {
|
|
me.uiCls = Ext.Array.clone(me.uiCls);
|
|
me.uiCls.push(cls[i]);
|
|
|
|
classes = classes.concat(me.addUIClsToElement(cls[i]));
|
|
}
|
|
}
|
|
|
|
if (skip !== true) {
|
|
me.addCls(classes);
|
|
}
|
|
|
|
return classes;
|
|
},
|
|
|
|
|
|
removeClsWithUI: function(cls, skip) {
|
|
var me = this,
|
|
classes = [],
|
|
i;
|
|
|
|
if (!Ext.isArray(cls)) {
|
|
cls = [cls];
|
|
}
|
|
|
|
for (i = 0; i < cls.length; i++) {
|
|
if (cls[i] && me.hasUICls(cls[i])) {
|
|
me.uiCls = Ext.Array.remove(me.uiCls, cls[i]);
|
|
|
|
classes = classes.concat(me.removeUIClsFromElement(cls[i]));
|
|
}
|
|
}
|
|
|
|
if (skip !== true) {
|
|
me.removeCls(classes);
|
|
}
|
|
|
|
return classes;
|
|
},
|
|
|
|
|
|
hasUICls: function(cls) {
|
|
var me = this,
|
|
uiCls = me.uiCls || [];
|
|
|
|
return Ext.Array.contains(uiCls, cls);
|
|
},
|
|
|
|
|
|
addUIClsToElement: function(cls, force) {
|
|
var me = this,
|
|
result = [],
|
|
frameElementCls = me.frameElementCls;
|
|
|
|
result.push(Ext.baseCSSPrefix + cls);
|
|
result.push(me.baseCls + '-' + cls);
|
|
result.push(me.baseCls + '-' + me.ui + '-' + cls);
|
|
|
|
if (!force && me.frame && !Ext.supports.CSS3BorderRadius) {
|
|
|
|
var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
|
|
classes, i, j, el;
|
|
|
|
|
|
for (i = 0; i < els.length; i++) {
|
|
el = me['frame' + els[i].toUpperCase()];
|
|
classes = [me.baseCls + '-' + me.ui + '-' + els[i], me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i]];
|
|
if (el && el.dom) {
|
|
el.addCls(classes);
|
|
} else {
|
|
for (j = 0; j < classes.length; j++) {
|
|
if (Ext.Array.indexOf(frameElementCls[els[i]], classes[j]) == -1) {
|
|
frameElementCls[els[i]].push(classes[j]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
me.frameElementCls = frameElementCls;
|
|
|
|
return result;
|
|
},
|
|
|
|
|
|
removeUIClsFromElement: function(cls, force) {
|
|
var me = this,
|
|
result = [],
|
|
frameElementCls = me.frameElementCls;
|
|
|
|
result.push(Ext.baseCSSPrefix + cls);
|
|
result.push(me.baseCls + '-' + cls);
|
|
result.push(me.baseCls + '-' + me.ui + '-' + cls);
|
|
|
|
if (!force && me.frame && !Ext.supports.CSS3BorderRadius) {
|
|
|
|
var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
|
|
i, el;
|
|
cls = me.baseCls + '-' + me.ui + '-' + cls + '-' + els[i];
|
|
|
|
for (i = 0; i < els.length; i++) {
|
|
el = me['frame' + els[i].toUpperCase()];
|
|
if (el && el.dom) {
|
|
el.removeCls(cls);
|
|
} else {
|
|
Ext.Array.remove(frameElementCls[els[i]], cls);
|
|
}
|
|
}
|
|
}
|
|
|
|
me.frameElementCls = frameElementCls;
|
|
|
|
return result;
|
|
},
|
|
|
|
|
|
addUIToElement: function(force) {
|
|
var me = this,
|
|
frameElementCls = me.frameElementCls;
|
|
|
|
me.addCls(me.baseCls + '-' + me.ui);
|
|
|
|
if (me.frame && !Ext.supports.CSS3BorderRadius) {
|
|
|
|
var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
|
|
i, el, cls;
|
|
|
|
|
|
for (i = 0; i < els.length; i++) {
|
|
el = me['frame' + els[i].toUpperCase()];
|
|
cls = me.baseCls + '-' + me.ui + '-' + els[i];
|
|
if (el) {
|
|
el.addCls(cls);
|
|
} else {
|
|
if (!Ext.Array.contains(frameElementCls[els[i]], cls)) {
|
|
frameElementCls[els[i]].push(cls);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
removeUIFromElement: function() {
|
|
var me = this,
|
|
frameElementCls = me.frameElementCls;
|
|
|
|
me.removeCls(me.baseCls + '-' + me.ui);
|
|
|
|
if (me.frame && !Ext.supports.CSS3BorderRadius) {
|
|
|
|
var els = ['tl', 'tc', 'tr', 'ml', 'mc', 'mr', 'bl', 'bc', 'br'],
|
|
i, j, el, cls;
|
|
|
|
|
|
for (i = 0; i < els.length; i++) {
|
|
el = me['frame' + els[i].toUpperCase()];
|
|
cls = me.baseCls + '-' + me.ui + '-' + els[i];
|
|
|
|
if (el) {
|
|
el.removeCls(cls);
|
|
} else {
|
|
Ext.Array.remove(frameElementCls[els[i]], cls);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
getElConfig : function() {
|
|
if (Ext.isString(this.autoEl)) {
|
|
this.autoEl = {
|
|
tag: this.autoEl
|
|
};
|
|
}
|
|
|
|
var result = this.autoEl || {tag: 'div'};
|
|
result.id = this.id;
|
|
return result;
|
|
},
|
|
|
|
|
|
getInsertPosition: function(position) {
|
|
|
|
if (position !== undefined) {
|
|
if (Ext.isNumber(position)) {
|
|
position = this.container.dom.childNodes[position];
|
|
}
|
|
else {
|
|
position = Ext.getDom(position);
|
|
}
|
|
}
|
|
|
|
return position;
|
|
},
|
|
|
|
|
|
initContainer: function(container) {
|
|
var me = this;
|
|
|
|
|
|
|
|
|
|
if (!container && me.el) {
|
|
container = me.el.dom.parentNode;
|
|
me.allowDomMove = false;
|
|
}
|
|
|
|
me.container = Ext.get(container);
|
|
|
|
if (me.ctCls) {
|
|
me.container.addCls(me.ctCls);
|
|
}
|
|
|
|
return me.container;
|
|
},
|
|
|
|
|
|
initRenderData: function() {
|
|
var me = this;
|
|
|
|
return Ext.applyIf(me.renderData, {
|
|
id: me.id,
|
|
ui: me.ui,
|
|
uiCls: me.uiCls,
|
|
baseCls: me.baseCls,
|
|
componentCls: me.componentCls,
|
|
frame: me.frame
|
|
});
|
|
},
|
|
|
|
|
|
getTpl: function(name) {
|
|
var me = this,
|
|
prototype = me.self.prototype,
|
|
ownerPrototype,
|
|
tpl;
|
|
|
|
if (me.hasOwnProperty(name)) {
|
|
tpl = me[name];
|
|
if (tpl && !(tpl instanceof Ext.XTemplate)) {
|
|
me[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
|
|
}
|
|
|
|
return me[name];
|
|
}
|
|
|
|
if (!(prototype[name] instanceof Ext.XTemplate)) {
|
|
ownerPrototype = prototype;
|
|
|
|
do {
|
|
if (ownerPrototype.hasOwnProperty(name)) {
|
|
tpl = ownerPrototype[name];
|
|
if (tpl && !(tpl instanceof Ext.XTemplate)) {
|
|
ownerPrototype[name] = Ext.ClassManager.dynInstantiate('Ext.XTemplate', tpl);
|
|
break;
|
|
}
|
|
}
|
|
|
|
ownerPrototype = ownerPrototype.superclass;
|
|
} while (ownerPrototype);
|
|
}
|
|
|
|
return prototype[name];
|
|
},
|
|
|
|
|
|
initRenderTpl: function() {
|
|
return this.getTpl('renderTpl');
|
|
},
|
|
|
|
|
|
initStyles: function() {
|
|
var style = {},
|
|
me = this,
|
|
Element = Ext.Element;
|
|
|
|
if (Ext.isString(me.style)) {
|
|
style = Element.parseStyles(me.style);
|
|
} else {
|
|
style = Ext.apply({}, me.style);
|
|
}
|
|
|
|
|
|
|
|
if (me.padding !== undefined) {
|
|
style.padding = Element.unitizeBox((me.padding === true) ? 5 : me.padding);
|
|
}
|
|
|
|
if (me.margin !== undefined) {
|
|
style.margin = Element.unitizeBox((me.margin === true) ? 5 : me.margin);
|
|
}
|
|
|
|
delete me.style;
|
|
return style;
|
|
},
|
|
|
|
|
|
initContent: function() {
|
|
var me = this,
|
|
target = me.getTargetEl(),
|
|
contentEl,
|
|
pre;
|
|
|
|
if (me.html) {
|
|
target.update(Ext.DomHelper.markup(me.html));
|
|
delete me.html;
|
|
}
|
|
|
|
if (me.contentEl) {
|
|
contentEl = Ext.get(me.contentEl);
|
|
pre = Ext.baseCSSPrefix;
|
|
contentEl.removeCls([pre + 'hidden', pre + 'hide-display', pre + 'hide-offsets', pre + 'hide-nosize']);
|
|
target.appendChild(contentEl.dom);
|
|
}
|
|
|
|
if (me.tpl) {
|
|
|
|
if (!me.tpl.isTemplate) {
|
|
me.tpl = Ext.create('Ext.XTemplate', me.tpl);
|
|
}
|
|
|
|
if (me.data) {
|
|
me.tpl[me.tplWriteMode](target, me.data);
|
|
delete me.data;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
initEvents : function() {
|
|
var me = this,
|
|
afterRenderEvents = me.afterRenderEvents,
|
|
el,
|
|
property,
|
|
fn = function(listeners){
|
|
me.mon(el, listeners);
|
|
};
|
|
if (afterRenderEvents) {
|
|
for (property in afterRenderEvents) {
|
|
if (afterRenderEvents.hasOwnProperty(property)) {
|
|
el = me[property];
|
|
if (el && el.on) {
|
|
Ext.each(afterRenderEvents[property], fn);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
addChildEls: function () {
|
|
var me = this,
|
|
childEls = me.childEls || (me.childEls = []);
|
|
|
|
childEls.push.apply(childEls, arguments);
|
|
},
|
|
|
|
|
|
removeChildEls: function (testFn) {
|
|
var me = this,
|
|
old = me.childEls,
|
|
keepers = (me.childEls = []),
|
|
n, i, cel;
|
|
|
|
for (i = 0, n = old.length; i < n; ++i) {
|
|
cel = old[i];
|
|
if (!testFn(cel)) {
|
|
keepers.push(cel);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
applyRenderSelectors: function() {
|
|
var me = this,
|
|
childEls = me.childEls,
|
|
selectors = me.renderSelectors,
|
|
el = me.el,
|
|
dom = el.dom,
|
|
baseId, childName, childId, i, selector;
|
|
|
|
if (childEls) {
|
|
baseId = me.id + '-';
|
|
for (i = childEls.length; i--; ) {
|
|
childName = childId = childEls[i];
|
|
if (typeof(childName) != 'string') {
|
|
childId = childName.id || (baseId + childName.itemId);
|
|
childName = childName.name;
|
|
} else {
|
|
childId = baseId + childId;
|
|
}
|
|
|
|
|
|
|
|
me[childName] = el.getById(childId);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
if (selectors) {
|
|
for (selector in selectors) {
|
|
if (selectors.hasOwnProperty(selector) && selectors[selector]) {
|
|
me[selector] = Ext.get(Ext.DomQuery.selectNode(selectors[selector], dom));
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
is: function(selector) {
|
|
return Ext.ComponentQuery.is(this, selector);
|
|
},
|
|
|
|
|
|
up: function(selector) {
|
|
var result = this.ownerCt;
|
|
if (selector) {
|
|
for (; result; result = result.ownerCt) {
|
|
if (Ext.ComponentQuery.is(result, selector)) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
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,
|
|
result,
|
|
it, len, i;
|
|
|
|
|
|
if (includeSelf && node.is(selector)) {
|
|
return node;
|
|
}
|
|
|
|
result = this.prev(selector);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (node.ownerCt) {
|
|
for (it = node.ownerCt.items.items, i = Ext.Array.indexOf(it, node) - 1; i > -1; i--) {
|
|
if (it[i].query) {
|
|
result = it[i].query(selector);
|
|
result = result[result.length - 1];
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
return node.ownerCt.previousNode(selector, true);
|
|
}
|
|
},
|
|
|
|
|
|
nextNode: function(selector, includeSelf) {
|
|
var node = this,
|
|
result,
|
|
it, len, i;
|
|
|
|
|
|
if (includeSelf && node.is(selector)) {
|
|
return node;
|
|
}
|
|
|
|
result = this.next(selector);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
|
|
if (node.ownerCt) {
|
|
for (it = node.ownerCt.items, i = it.indexOf(node) + 1, it = it.items, len = it.length; i < len; i++) {
|
|
if (it[i].down) {
|
|
result = it[i].down(selector);
|
|
if (result) {
|
|
return result;
|
|
}
|
|
}
|
|
}
|
|
return node.ownerCt.nextNode(selector);
|
|
}
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
isXType: function(xtype, shallow) {
|
|
|
|
if (Ext.isFunction(xtype)) {
|
|
xtype = xtype.xtype;
|
|
|
|
} else if (Ext.isObject(xtype)) {
|
|
xtype = xtype.statics().xtype;
|
|
|
|
}
|
|
|
|
return !shallow ? ('/' + this.getXTypes() + '/').indexOf('/' + xtype + '/') != -1: this.self.xtype == 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;
|
|
|
|
if (me.tpl && !Ext.isString(htmlOrData)) {
|
|
me.data = htmlOrData;
|
|
if (me.rendered) {
|
|
me.tpl[me.tplWriteMode](me.getTargetEl(), htmlOrData || {});
|
|
}
|
|
} else {
|
|
me.html = Ext.isObject(htmlOrData) ? Ext.DomHelper.markup(htmlOrData) : htmlOrData;
|
|
if (me.rendered) {
|
|
me.getTargetEl().update(me.html, loadScripts, cb);
|
|
}
|
|
}
|
|
|
|
if (me.rendered) {
|
|
me.doComponentLayout();
|
|
}
|
|
},
|
|
|
|
|
|
setVisible : function(visible) {
|
|
return this[visible ? 'show': 'hide']();
|
|
},
|
|
|
|
|
|
isVisible: function(deep) {
|
|
var me = this,
|
|
child = me,
|
|
visible = !me.hidden,
|
|
ancestor = me.ownerCt;
|
|
|
|
|
|
me.hiddenAncestor = false;
|
|
if (me.destroyed) {
|
|
return false;
|
|
}
|
|
|
|
if (deep && visible && me.rendered && ancestor) {
|
|
while (ancestor) {
|
|
|
|
|
|
|
|
|
|
if (ancestor.hidden || (ancestor.collapsed &&
|
|
!(ancestor.getDockedItems && Ext.Array.contains(ancestor.getDockedItems(), child)))) {
|
|
|
|
me.hiddenAncestor = ancestor;
|
|
visible = false;
|
|
break;
|
|
}
|
|
child = ancestor;
|
|
ancestor = ancestor.ownerCt;
|
|
}
|
|
}
|
|
return visible;
|
|
},
|
|
|
|
|
|
enable: function(silent) {
|
|
var me = this;
|
|
|
|
if (me.rendered) {
|
|
me.el.removeCls(me.disabledCls);
|
|
me.el.dom.disabled = false;
|
|
me.onEnable();
|
|
}
|
|
|
|
me.disabled = false;
|
|
|
|
if (silent !== true) {
|
|
me.fireEvent('enable', me);
|
|
}
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
disable: function(silent) {
|
|
var me = this;
|
|
|
|
if (me.rendered) {
|
|
me.el.addCls(me.disabledCls);
|
|
me.el.dom.disabled = true;
|
|
me.onDisable();
|
|
}
|
|
|
|
me.disabled = true;
|
|
|
|
if (silent !== true) {
|
|
me.fireEvent('disable', me);
|
|
}
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
onEnable: function() {
|
|
if (this.maskOnDisable) {
|
|
this.el.unmask();
|
|
}
|
|
},
|
|
|
|
|
|
onDisable : function() {
|
|
if (this.maskOnDisable) {
|
|
this.el.mask();
|
|
}
|
|
},
|
|
|
|
|
|
isDisabled : function() {
|
|
return this.disabled;
|
|
},
|
|
|
|
|
|
setDisabled : function(disabled) {
|
|
return this[disabled ? 'disable': 'enable']();
|
|
},
|
|
|
|
|
|
isHidden : function() {
|
|
return this.hidden;
|
|
},
|
|
|
|
|
|
addCls : function(className) {
|
|
var me = this;
|
|
if (!className) {
|
|
return me;
|
|
}
|
|
if (!Ext.isArray(className)){
|
|
className = className.replace(me.trimRe, '').split(me.spacesRe);
|
|
}
|
|
if (me.rendered) {
|
|
me.el.addCls(className);
|
|
}
|
|
else {
|
|
me.additionalCls = Ext.Array.unique(me.additionalCls.concat(className));
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
addClass : function() {
|
|
return this.addCls.apply(this, arguments);
|
|
},
|
|
|
|
|
|
removeCls : function(className) {
|
|
var me = this;
|
|
|
|
if (!className) {
|
|
return me;
|
|
}
|
|
if (!Ext.isArray(className)){
|
|
className = className.replace(me.trimRe, '').split(me.spacesRe);
|
|
}
|
|
if (me.rendered) {
|
|
me.el.removeCls(className);
|
|
}
|
|
else if (me.additionalCls.length) {
|
|
Ext.each(className, function(cls) {
|
|
Ext.Array.remove(me.additionalCls, cls);
|
|
});
|
|
}
|
|
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 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) {
|
|
this.ownerCt = container;
|
|
this.fireEvent('added', this, container, pos);
|
|
},
|
|
|
|
|
|
onRemoved : function() {
|
|
var me = this;
|
|
|
|
me.fireEvent('removed', me, me.ownerCt);
|
|
delete me.ownerCt;
|
|
},
|
|
|
|
|
|
beforeDestroy : Ext.emptyFn,
|
|
|
|
|
|
onResize : Ext.emptyFn,
|
|
|
|
|
|
setSize : function(width, height) {
|
|
var me = this,
|
|
layoutCollection;
|
|
|
|
|
|
if (Ext.isObject(width)) {
|
|
height = width.height;
|
|
width = width.width;
|
|
}
|
|
|
|
|
|
if (Ext.isNumber(width)) {
|
|
width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
|
|
}
|
|
if (Ext.isNumber(height)) {
|
|
height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
|
|
}
|
|
|
|
if (!me.rendered || !me.isVisible()) {
|
|
|
|
if (me.hiddenAncestor) {
|
|
layoutCollection = me.hiddenAncestor.layoutOnShow;
|
|
layoutCollection.remove(me);
|
|
layoutCollection.add(me);
|
|
}
|
|
me.needsLayout = {
|
|
width: width,
|
|
height: height,
|
|
isSetSize: true
|
|
};
|
|
if (!me.rendered) {
|
|
me.width = (width !== undefined) ? width : me.width;
|
|
me.height = (height !== undefined) ? height : me.height;
|
|
}
|
|
return me;
|
|
}
|
|
me.doComponentLayout(width, height, true);
|
|
|
|
return me;
|
|
},
|
|
|
|
isFixedWidth: function() {
|
|
var me = this,
|
|
layoutManagedWidth = me.layoutManagedWidth;
|
|
|
|
if (Ext.isDefined(me.width) || layoutManagedWidth == 1) {
|
|
return true;
|
|
}
|
|
if (layoutManagedWidth == 2) {
|
|
return false;
|
|
}
|
|
return (me.ownerCt && me.ownerCt.isFixedWidth());
|
|
},
|
|
|
|
isFixedHeight: function() {
|
|
var me = this,
|
|
layoutManagedHeight = me.layoutManagedHeight;
|
|
|
|
if (Ext.isDefined(me.height) || layoutManagedHeight == 1) {
|
|
return true;
|
|
}
|
|
if (layoutManagedHeight == 2) {
|
|
return false;
|
|
}
|
|
return (me.ownerCt && me.ownerCt.isFixedHeight());
|
|
},
|
|
|
|
setCalculatedSize : function(width, height, callingContainer) {
|
|
var me = this,
|
|
layoutCollection;
|
|
|
|
|
|
if (Ext.isObject(width)) {
|
|
callingContainer = width.ownerCt;
|
|
height = width.height;
|
|
width = width.width;
|
|
}
|
|
|
|
|
|
if (Ext.isNumber(width)) {
|
|
width = Ext.Number.constrain(width, me.minWidth, me.maxWidth);
|
|
}
|
|
if (Ext.isNumber(height)) {
|
|
height = Ext.Number.constrain(height, me.minHeight, me.maxHeight);
|
|
}
|
|
|
|
if (!me.rendered || !me.isVisible()) {
|
|
|
|
if (me.hiddenAncestor) {
|
|
layoutCollection = me.hiddenAncestor.layoutOnShow;
|
|
layoutCollection.remove(me);
|
|
layoutCollection.add(me);
|
|
}
|
|
me.needsLayout = {
|
|
width: width,
|
|
height: height,
|
|
isSetSize: false,
|
|
ownerCt: callingContainer
|
|
};
|
|
return me;
|
|
}
|
|
me.doComponentLayout(width, height, false, callingContainer);
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
doComponentLayout : function(width, height, isSetSize, callingContainer) {
|
|
var me = this,
|
|
componentLayout = me.getComponentLayout(),
|
|
lastComponentSize = componentLayout.lastComponentSize || {
|
|
width: undefined,
|
|
height: undefined
|
|
};
|
|
|
|
|
|
|
|
|
|
if (me.rendered && componentLayout) {
|
|
|
|
if (!Ext.isDefined(width)) {
|
|
if (me.isFixedWidth()) {
|
|
width = Ext.isDefined(me.width) ? me.width : lastComponentSize.width;
|
|
}
|
|
}
|
|
|
|
if (!Ext.isDefined(height)) {
|
|
if (me.isFixedHeight()) {
|
|
height = Ext.isDefined(me.height) ? me.height : lastComponentSize.height;
|
|
}
|
|
}
|
|
|
|
if (isSetSize) {
|
|
me.width = width;
|
|
me.height = height;
|
|
}
|
|
|
|
componentLayout.layout(width, height, isSetSize, callingContainer);
|
|
}
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
forceComponentLayout: function () {
|
|
this.doComponentLayout();
|
|
},
|
|
|
|
|
|
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, isSetSize, callingContainer) {
|
|
var me = this,
|
|
layout = me.componentLayout,
|
|
oldSize = me.preLayoutSize;
|
|
|
|
++me.componentLayoutCounter;
|
|
if (!oldSize || ((width !== oldSize.width) || (height !== oldSize.height))) {
|
|
me.fireEvent('resize', me, width, height);
|
|
}
|
|
},
|
|
|
|
|
|
beforeComponentLayout: function(width, height, isSetSize, callingContainer) {
|
|
this.preLayoutSize = this.componentLayout.lastComponentSize;
|
|
return true;
|
|
},
|
|
|
|
|
|
setPosition : function(x, y) {
|
|
var me = this;
|
|
|
|
if (Ext.isObject(x)) {
|
|
y = x.y;
|
|
x = x.x;
|
|
}
|
|
|
|
if (!me.rendered) {
|
|
return me;
|
|
}
|
|
|
|
if (x !== undefined || y !== undefined) {
|
|
me.el.setBox(x, y);
|
|
me.onPosition(x, y);
|
|
me.fireEvent('move', me, x, y);
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
onPosition: Ext.emptyFn,
|
|
|
|
|
|
setWidth : function(width) {
|
|
return this.setSize(width);
|
|
},
|
|
|
|
|
|
setHeight : function(height) {
|
|
return this.setSize(undefined, height);
|
|
},
|
|
|
|
|
|
getSize : function() {
|
|
return this.el.getSize();
|
|
},
|
|
|
|
|
|
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 = Ext.create('Ext.ComponentLoader', Ext.apply({
|
|
target: me,
|
|
autoLoad: autoLoad
|
|
}, loader));
|
|
} else {
|
|
loader.setTarget(me);
|
|
}
|
|
return me.loader;
|
|
|
|
}
|
|
return null;
|
|
},
|
|
|
|
|
|
setLoading : function(load, targetEl) {
|
|
var me = this,
|
|
config;
|
|
|
|
if (me.rendered) {
|
|
if (load !== false && !me.collapsed) {
|
|
if (Ext.isObject(load)) {
|
|
config = load;
|
|
}
|
|
else if (Ext.isString(load)) {
|
|
config = {msg: load};
|
|
}
|
|
else {
|
|
config = {};
|
|
}
|
|
me.loadMask = me.loadMask || Ext.create('Ext.LoadMask', targetEl ? me.getTargetEl() : me.el, config);
|
|
me.loadMask.show();
|
|
} else if (me.loadMask) {
|
|
Ext.destroy(me.loadMask);
|
|
me.loadMask = null;
|
|
}
|
|
}
|
|
|
|
return me.loadMask;
|
|
},
|
|
|
|
|
|
setDocked : function(dock, layoutParent) {
|
|
var me = this;
|
|
|
|
me.dock = dock;
|
|
if (layoutParent && me.ownerCt && me.rendered) {
|
|
me.ownerCt.doComponentLayout();
|
|
}
|
|
return me;
|
|
},
|
|
|
|
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.floatingItems
|
|
);
|
|
},
|
|
|
|
|
|
cleanElementRefs: function(){
|
|
var me = this,
|
|
i = 0,
|
|
childEls = me.childEls,
|
|
selectors = me.renderSelectors,
|
|
selector,
|
|
name,
|
|
len;
|
|
|
|
if (me.rendered) {
|
|
if (childEls) {
|
|
for (len = childEls.length; i < len; ++i) {
|
|
name = childEls[i];
|
|
if (typeof(name) != 'string') {
|
|
name = name.name;
|
|
}
|
|
delete me[name];
|
|
}
|
|
}
|
|
|
|
if (selectors) {
|
|
for (selector in selectors) {
|
|
if (selectors.hasOwnProperty(selector)) {
|
|
delete me[selector];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
delete me.rendered;
|
|
delete me.el;
|
|
delete me.frameBody;
|
|
},
|
|
|
|
|
|
destroy : function() {
|
|
var me = this;
|
|
|
|
if (!me.isDestroyed) {
|
|
if (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.onDestroy();
|
|
|
|
|
|
Ext.destroy(me.plugins);
|
|
|
|
if (me.rendered) {
|
|
me.el.remove();
|
|
}
|
|
|
|
me.fireEvent('destroy', me);
|
|
Ext.ComponentManager.unregister(me);
|
|
|
|
me.mixins.state.destroy.call(me);
|
|
|
|
me.clearListeners();
|
|
|
|
me.cleanElementRefs();
|
|
me.destroying = false;
|
|
me.isDestroyed = true;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getPlugin: function(pluginId) {
|
|
var i = 0,
|
|
plugins = this.plugins,
|
|
ln = plugins.length;
|
|
for (; i < ln; i++) {
|
|
if (plugins[i].pluginId === pluginId) {
|
|
return plugins[i];
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
isDescendantOf: function(container) {
|
|
return !!this.findParentBy(function(p){
|
|
return p === container;
|
|
});
|
|
}
|
|
}, function() {
|
|
this.createAlias({
|
|
on: 'addListener',
|
|
prev: 'previousSibling',
|
|
next: 'nextSibling'
|
|
});
|
|
});
|
|
|
|
|
|
Ext.define('Ext.AbstractPlugin', {
|
|
disabled: false,
|
|
|
|
constructor: function(config) {
|
|
Ext.apply(this, config);
|
|
},
|
|
|
|
getCmp: function() {
|
|
return this.cmp;
|
|
},
|
|
|
|
|
|
init: Ext.emptyFn,
|
|
|
|
|
|
destroy: Ext.emptyFn,
|
|
|
|
|
|
enable: function() {
|
|
this.disabled = false;
|
|
},
|
|
|
|
|
|
disable: function() {
|
|
this.disabled = true;
|
|
}
|
|
});
|
|
|
|
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,
|
|
|
|
|
|
cors: false,
|
|
|
|
|
|
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.addEvents(
|
|
|
|
'beforerequest',
|
|
|
|
'requestcomplete',
|
|
|
|
'requestexception'
|
|
);
|
|
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 (this.isFormUpload(options) === true) {
|
|
this.upload(options.form, requestOptions.url, requestOptions.data, options);
|
|
return null;
|
|
}
|
|
|
|
|
|
if (options.autoAbort === true || me.autoAbort) {
|
|
me.abort();
|
|
}
|
|
|
|
|
|
|
|
if ((options.cors === true || me.cors === true) && Ext.isIe && Ext.ieVersion >= 8) {
|
|
xhr = new XDomainRequest();
|
|
} else {
|
|
xhr = this.getXhrInstance();
|
|
}
|
|
|
|
async = options.async !== false ? (options.async || me.async) : false;
|
|
|
|
|
|
if (username) {
|
|
xhr.open(requestOptions.method, requestOptions.url, async, username, password);
|
|
} else {
|
|
xhr.open(requestOptions.method, requestOptions.url, async);
|
|
}
|
|
|
|
if (options.withCredentials === true || me.withCredentials === true) {
|
|
xhr.withCredentials = true;
|
|
}
|
|
|
|
headers = me.setupHeaders(xhr, options, requestOptions.data, requestOptions.params);
|
|
|
|
|
|
request = {
|
|
id: ++Ext.data.Connection.requestId,
|
|
xhr: xhr,
|
|
headers: headers,
|
|
options: options,
|
|
async: async,
|
|
timeout: setTimeout(function() {
|
|
request.timedout = true;
|
|
me.abort(request);
|
|
}, options.timeout || me.timeout)
|
|
};
|
|
me.requests[request.id] = request;
|
|
me.latestId = request.id;
|
|
|
|
if (async) {
|
|
xhr.onreadystatechange = Ext.Function.bind(me.onStateChange, me, [request]);
|
|
}
|
|
|
|
|
|
xhr.send(requestOptions.data);
|
|
if (!async) {
|
|
return this.onComplete(request);
|
|
}
|
|
return request;
|
|
} else {
|
|
Ext.callback(options.callback, options.scope, [options, undefined, undefined]);
|
|
return null;
|
|
}
|
|
},
|
|
|
|
|
|
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
|
|
}, hiddenItem;
|
|
|
|
|
|
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) {
|
|
Ext.iterate(Ext.Object.fromQueryString(params), function(name, value){
|
|
hiddenItem = document.createElement('input');
|
|
Ext.fly(hiddenItem).set({
|
|
type: 'hidden',
|
|
value: value,
|
|
name: name
|
|
});
|
|
form.appendChild(hiddenItem);
|
|
hiddens.push(hiddenItem);
|
|
});
|
|
}
|
|
|
|
Ext.fly(frame).on('load', Ext.Function.bind(this.onUploadComplete, this, [frame, options]), null, {single: true});
|
|
form.submit();
|
|
|
|
Ext.fly(form).set(buf);
|
|
Ext.each(hiddens, function(h) {
|
|
Ext.removeNode(h);
|
|
});
|
|
},
|
|
|
|
|
|
onUploadComplete: function(frame, options) {
|
|
var me = this,
|
|
|
|
response = {
|
|
responseText: '',
|
|
responseXML: null
|
|
}, doc, firstChild;
|
|
|
|
try {
|
|
doc = frame.contentWindow.document || frame.contentDocument || window.frames[frame.id].document;
|
|
if (doc) {
|
|
if (doc.body) {
|
|
if (/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)) {
|
|
response.responseText = firstChild.value;
|
|
} else {
|
|
response.responseText = doc.body.innerHTML;
|
|
}
|
|
}
|
|
|
|
response.responseXML = doc.XMLDocument || doc;
|
|
}
|
|
} catch (e) {
|
|
}
|
|
|
|
me.fireEvent('requestcomplete', me, response, options);
|
|
|
|
Ext.callback(options.success, options.scope, [response, options]);
|
|
Ext.callback(options.callback, options.scope, [options, true, 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.xmlData || jsonData || null;
|
|
if (jsonData && !Ext.isPrimitive(jsonData)) {
|
|
data = Ext.encode(data);
|
|
}
|
|
|
|
|
|
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,
|
|
key,
|
|
header;
|
|
|
|
if (!headers['Content-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['Content-Type'] = contentType;
|
|
}
|
|
|
|
if (me.useDefaultXhrHeader && !headers['X-Requested-With']) {
|
|
headers['X-Requested-With'] = me.defaultXhrHeader;
|
|
}
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
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 !(state === 0 || state == 4);
|
|
},
|
|
|
|
|
|
abort : function(request) {
|
|
var me = this;
|
|
|
|
if (!request) {
|
|
request = me.getLatest();
|
|
}
|
|
|
|
if (request && me.isLoading(request)) {
|
|
|
|
request.xhr.onreadystatechange = null;
|
|
request.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) {
|
|
if (request.xhr.readyState == 4) {
|
|
this.clearTimeout(request);
|
|
this.onComplete(request);
|
|
this.cleanup(request);
|
|
}
|
|
},
|
|
|
|
|
|
clearTimeout: function(request){
|
|
clearTimeout(request.timeout);
|
|
delete request.timeout;
|
|
},
|
|
|
|
|
|
cleanup: function(request){
|
|
request.xhr = null;
|
|
delete request.xhr;
|
|
},
|
|
|
|
|
|
onComplete : function(request) {
|
|
var me = this,
|
|
options = request.options,
|
|
result,
|
|
success,
|
|
response;
|
|
|
|
try {
|
|
result = me.parseStatus(request.xhr.status);
|
|
} catch (e) {
|
|
|
|
result = {
|
|
success : false,
|
|
isException : false
|
|
};
|
|
}
|
|
success = 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 xhr = request.xhr,
|
|
headers = {},
|
|
lines = xhr.getAllResponseHeaders().replace(/\r\n/g, '\n').split('\n'),
|
|
count = lines.length,
|
|
line, index, key, value, response;
|
|
|
|
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; },
|
|
responseText : xhr.responseText,
|
|
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
|
|
};
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.Ajax', {
|
|
extend: 'Ext.data.Connection',
|
|
singleton: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
autoAbort : false
|
|
});
|
|
|
|
Ext.define('Ext.ElementLoader', {
|
|
|
|
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
uses: [
|
|
'Ext.data.Connection',
|
|
'Ext.Ajax'
|
|
],
|
|
|
|
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,
|
|
target = me.target,
|
|
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,
|
|
request;
|
|
|
|
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);
|
|
}
|
|
|
|
request = Ext.Ajax.request(options);
|
|
me.active = {
|
|
request: request,
|
|
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.setOptions(me.active, options);
|
|
},
|
|
|
|
|
|
setOptions: Ext.emptyFn,
|
|
|
|
|
|
onComplete: function(options, success, response) {
|
|
var me = this,
|
|
active = me.active,
|
|
scope = active.scope,
|
|
renderer = me.getRenderer(active.renderer);
|
|
|
|
|
|
if (success) {
|
|
success = renderer.call(me, me, response, active);
|
|
}
|
|
|
|
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) {
|
|
if (active.removeAll) {
|
|
target.removeAll();
|
|
}
|
|
target.add(items);
|
|
}
|
|
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.data.Association', {
|
|
|
|
|
|
|
|
|
|
|
|
primaryKey: 'id',
|
|
|
|
|
|
|
|
|
|
|
|
defaultReaderType: 'json',
|
|
|
|
statics: {
|
|
create: function(association){
|
|
if (!association.isAssociation) {
|
|
if (Ext.isString(association)) {
|
|
association = {
|
|
type: association
|
|
};
|
|
}
|
|
|
|
switch (association.type) {
|
|
case 'belongsTo':
|
|
return Ext.create('Ext.data.BelongsToAssociation', association);
|
|
case 'hasMany':
|
|
return Ext.create('Ext.data.HasManyAssociation', association);
|
|
|
|
|
|
|
|
default:
|
|
}
|
|
}
|
|
return association;
|
|
}
|
|
},
|
|
|
|
|
|
constructor: function(config) {
|
|
Ext.apply(this, config);
|
|
|
|
var types = Ext.ModelManager.types,
|
|
ownerName = config.ownerModel,
|
|
associatedName = config.associatedModel,
|
|
ownerModel = types[ownerName],
|
|
associatedModel = types[associatedName],
|
|
ownerProto;
|
|
|
|
|
|
this.ownerModel = ownerModel;
|
|
this.associatedModel = associatedModel;
|
|
|
|
|
|
|
|
|
|
|
|
Ext.applyIf(this, {
|
|
ownerName : ownerName,
|
|
associatedName: associatedName
|
|
});
|
|
},
|
|
|
|
|
|
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',
|
|
requires: ['Ext.data.Association'],
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
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.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.PluginManager', {
|
|
extend: 'Ext.AbstractManager',
|
|
alternateClassName: 'Ext.PluginMgr',
|
|
singleton: true,
|
|
typeName: 'ptype',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
create : function(config, defaultType){
|
|
if (config.init) {
|
|
return config;
|
|
} else {
|
|
return Ext.createByAlias('plugin.' + (config.ptype || defaultType), config);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
findByType: function(type, defaultsOnly) {
|
|
var matches = [],
|
|
types = this.types;
|
|
|
|
for (var name in types) {
|
|
if (!types.hasOwnProperty(name)) {
|
|
continue;
|
|
}
|
|
var 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.Template', {
|
|
|
|
|
|
|
|
requires: ['Ext.DomHelper', 'Ext.util.Format'],
|
|
|
|
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) {
|
|
for (; i < length; i++) {
|
|
value = args[i];
|
|
if (typeof value == 'object') {
|
|
Ext.apply(me.initialConfig, value);
|
|
Ext.apply(me, value);
|
|
} else {
|
|
buffer.push(value);
|
|
}
|
|
}
|
|
html = buffer.join('');
|
|
} else {
|
|
if (Ext.isArray(html)) {
|
|
buffer.push(html.join(''));
|
|
} else {
|
|
buffer.push(html);
|
|
}
|
|
}
|
|
|
|
|
|
me.html = buffer.join('');
|
|
|
|
if (me.compiled) {
|
|
me.compile();
|
|
}
|
|
},
|
|
|
|
isTemplate: true,
|
|
|
|
|
|
|
|
|
|
disableFormats: false,
|
|
|
|
re: /\{([\w\-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
|
|
|
|
|
|
applyTemplate: function(values) {
|
|
var me = this,
|
|
useFormat = me.disableFormats !== true,
|
|
fm = Ext.util.Format,
|
|
tpl = me;
|
|
|
|
if (me.compiled) {
|
|
return me.compiled(values);
|
|
}
|
|
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] : "";
|
|
}
|
|
}
|
|
return me.html.replace(me.re, fn);
|
|
},
|
|
|
|
|
|
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 + "'].join('');};";
|
|
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, returnEl) {
|
|
el = Ext.getDom(el);
|
|
var newNode = Ext.DomHelper.insertHtml(where, el, this.applyTemplate(values));
|
|
return returnEl ? Ext.get(newNode, true) : 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) {
|
|
el = Ext.getDom(el);
|
|
el.innerHTML = this.applyTemplate(values);
|
|
return returnElement ? Ext.get(el.firstChild, true) : el.firstChild;
|
|
}
|
|
}, function() {
|
|
|
|
/**
|
|
* @method apply
|
|
* @member Ext.Template
|
|
* Alias for {@link #applyTemplate}.
|
|
* @alias Ext.Template#applyTemplate
|
|
*/
|
|
this.createAlias('apply', 'applyTemplate');
|
|
});
|
|
|
|
/**
|
|
* 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: 'Tommy Maintz',
|
|
* title: 'Lead Developer',
|
|
* company: 'Sencha Inc.',
|
|
* email: 'tommy@sencha.com',
|
|
* address: '5 Cups Drive',
|
|
* city: 'Palo Alto',
|
|
* state: 'CA',
|
|
* zip: '44102',
|
|
* drinks: ['Coffee', 'Soda', 'Water'],
|
|
* kids: [
|
|
* {
|
|
* name: 'Joshua',
|
|
* age:3
|
|
* },
|
|
* {
|
|
* name: 'Matthew',
|
|
* age:2
|
|
* },
|
|
* {
|
|
* 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.
|
|
* - While processing an array, the special variable {#} will provide the current array index + 1 (starts at 1, not 0).
|
|
*
|
|
* Examples:
|
|
*
|
|
* <tpl for=".">...</tpl> // loop through array at root node
|
|
* <tpl for="foo">...</tpl> // loop through array at foo node
|
|
* <tpl for="foo.bar">...</tpl> // loop through array at foo.bar node
|
|
*
|
|
* Using the sample data above:
|
|
*
|
|
* var tpl = new Ext.XTemplate(
|
|
* '<p>Kids: ',
|
|
* '<tpl for=".">', // process the data.kids node
|
|
* '<p>{#}. {name}</p>', // use current array index to autonumber
|
|
* '</tpl></p>'
|
|
* );
|
|
* tpl.overwrite(panel.body, data.kids); // pass the kids property of the data object
|
|
*
|
|
* 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(
|
|
* '<p>Name: {name}</p>',
|
|
* '<p>Title: {title}</p>',
|
|
* '<p>Company: {company}</p>',
|
|
* '<p>Kids: ',
|
|
* '<tpl for="kids">', // interrogate the kids property within the data
|
|
* '<p>{name}</p>',
|
|
* '</tpl></p>'
|
|
* );
|
|
* tpl.overwrite(panel.body, data); // pass the root node of the data object
|
|
*
|
|
* 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(
|
|
* '<p>{name}\'s favorite beverages:</p>',
|
|
* '<tpl for="drinks">',
|
|
* '<div> - {.}</div>',
|
|
* '</tpl>'
|
|
* );
|
|
* 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(
|
|
* '<p>Name: {name}</p>',
|
|
* '<p>Kids: ',
|
|
* '<tpl for="kids">',
|
|
* '<tpl if="age > 1">',
|
|
* '<p>{name}</p>',
|
|
* '<p>Dad: {parent.name}</p>',
|
|
* '</tpl>',
|
|
* '</tpl></p>'
|
|
* );
|
|
* 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. Notes:
|
|
*
|
|
* - Double quotes must be encoded if used within the conditional
|
|
* - There is no else operator -- if needed, two opposite if statements should be used.
|
|
*
|
|
* Examples:
|
|
*
|
|
* <tpl if="age > 1 && age < 10">Child</tpl>
|
|
* <tpl if="age >= 10 && age < 18">Teenager</tpl>
|
|
* <tpl if="this.isGirl(name)">...</tpl>
|
|
* <tpl if="id==\'download\'">...</tpl>
|
|
* <tpl if="needsIcon"><img src="{icon}" class="{iconCls}"/></tpl>
|
|
* // no good:
|
|
* <tpl if="name == "Tommy"">Hello</tpl>
|
|
* // encode " if it is part of the condition, e.g.
|
|
* <tpl if="name == "Tommy"">Hello</tpl>
|
|
*
|
|
* Using the sample data above:
|
|
*
|
|
* var tpl = new Ext.XTemplate(
|
|
* '<p>Name: {name}</p>',
|
|
* '<p>Kids: ',
|
|
* '<tpl for="kids">',
|
|
* '<tpl if="age > 1">',
|
|
* '<p>{name}</p>',
|
|
* '</tpl>',
|
|
* '</tpl></p>'
|
|
* );
|
|
* tpl.overwrite(panel.body, data);
|
|
*
|
|
* # Basic math support
|
|
*
|
|
* The following basic math operators may be applied directly on numeric data values:
|
|
*
|
|
* + - * /
|
|
*
|
|
* For example:
|
|
*
|
|
* var tpl = new Ext.XTemplate(
|
|
* '<p>Name: {name}</p>',
|
|
* '<p>Kids: ',
|
|
* '<tpl for="kids">',
|
|
* '<tpl if="age > 1">', // <-- Note that the > is encoded
|
|
* '<p>{#}: {name}</p>', // <-- Auto-number each item
|
|
* '<p>In 5 Years: {age+5}</p>', // <-- Basic math
|
|
* '<p>Dad: {parent.name}</p>',
|
|
* '</tpl>',
|
|
* '</tpl></p>'
|
|
* );
|
|
* 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. There are some special
|
|
* variables available in that code:
|
|
*
|
|
* - **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 looping template, the index of the loop you are in (1-based).
|
|
* - **xcount**: If you are in a looping template, the total length of the array you are looping.
|
|
*
|
|
* This example demonstrates basic row striping using an inline code block and the xindex variable:
|
|
*
|
|
* var tpl = new Ext.XTemplate(
|
|
* '<p>Name: {name}</p>',
|
|
* '<p>Company: {[values.company.toUpperCase() + ", " + values.title]}</p>',
|
|
* '<p>Kids: ',
|
|
* '<tpl for="kids">',
|
|
* '<div class="{[xindex % 2 === 0 ? "even" : "odd"]}">',
|
|
* '{name}',
|
|
* '</div>',
|
|
* '</tpl></p>'
|
|
* );
|
|
* tpl.overwrite(panel.body, data);
|
|
*
|
|
* # 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(
|
|
* '<p>Name: {name}</p>',
|
|
* '<p>Kids: ',
|
|
* '<tpl for="kids">',
|
|
* '<tpl if="this.isGirl(name)">',
|
|
* '<p>Girl: {name} - {age}</p>',
|
|
* '</tpl>',
|
|
* // use opposite if statement to simulate 'else' processing:
|
|
* '<tpl if="this.isGirl(name) == false">',
|
|
* '<p>Boy: {name} - {age}</p>',
|
|
* '</tpl>',
|
|
* '<tpl if="this.isBaby(age)">',
|
|
* '<p>{name} is a baby!</p>',
|
|
* '</tpl>',
|
|
* '</tpl></p>',
|
|
* {
|
|
* // XTemplate configuration:
|
|
* disableFormats: true,
|
|
* // member functions:
|
|
* isGirl: function(name){
|
|
* return name == 'Sara Grace';
|
|
* },
|
|
* isBaby: function(age){
|
|
* return age < 1;
|
|
* }
|
|
* }
|
|
* );
|
|
* tpl.overwrite(panel.body, data);
|
|
*/
|
|
Ext.define('Ext.XTemplate', {
|
|
|
|
/* Begin Definitions */
|
|
|
|
extend: 'Ext.Template',
|
|
|
|
/* End Definitions */
|
|
|
|
argsRe: /<tpl\b[^>]*>((?:(?=([^<]+))\2|<(?!tpl\b[^>]*>))*?)<\/tpl>/,
|
|
nameRe: /^<tpl\b[^>]*?for="(.*?)"/,
|
|
ifRe: /^<tpl\b[^>]*?if="(.*?)"/,
|
|
execRe: /^<tpl\b[^>]*?exec="(.*?)"/,
|
|
constructor: function() {
|
|
this.callParent(arguments);
|
|
|
|
var me = this,
|
|
html = me.html,
|
|
argsRe = me.argsRe,
|
|
nameRe = me.nameRe,
|
|
ifRe = me.ifRe,
|
|
execRe = me.execRe,
|
|
id = 0,
|
|
tpls = [],
|
|
VALUES = 'values',
|
|
PARENT = 'parent',
|
|
XINDEX = 'xindex',
|
|
XCOUNT = 'xcount',
|
|
RETURN = 'return ',
|
|
WITHVALUES = 'with(values){ ',
|
|
m, matchName, matchIf, matchExec, exp, fn, exec, name, i;
|
|
|
|
html = ['<tpl>', html, '</tpl>'].join('');
|
|
|
|
while ((m = html.match(argsRe))) {
|
|
exp = null;
|
|
fn = null;
|
|
exec = null;
|
|
matchName = m[0].match(nameRe);
|
|
matchIf = m[0].match(ifRe);
|
|
matchExec = m[0].match(execRe);
|
|
|
|
exp = matchIf ? matchIf[1] : null;
|
|
if (exp) {
|
|
fn = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + 'try{' + RETURN + Ext.String.htmlDecode(exp) + ';}catch(e){return;}}');
|
|
}
|
|
|
|
exp = matchExec ? matchExec[1] : null;
|
|
if (exp) {
|
|
exec = Ext.functionFactory(VALUES, PARENT, XINDEX, XCOUNT, WITHVALUES + Ext.String.htmlDecode(exp) + ';}');
|
|
}
|
|
|
|
name = matchName ? matchName[1] : null;
|
|
if (name) {
|
|
if (name === '.') {
|
|
name = VALUES;
|
|
} else if (name === '..') {
|
|
name = PARENT;
|
|
}
|
|
name = Ext.functionFactory(VALUES, PARENT, 'try{' + WITHVALUES + RETURN + name + ';}}catch(e){return;}');
|
|
}
|
|
|
|
tpls.push({
|
|
id: id,
|
|
target: name,
|
|
exec: exec,
|
|
test: fn,
|
|
body: m[1] || ''
|
|
});
|
|
|
|
html = html.replace(m[0], '{xtpl' + id + '}');
|
|
id = id + 1;
|
|
}
|
|
|
|
for (i = tpls.length - 1; i >= 0; --i) {
|
|
me.compileTpl(tpls[i]);
|
|
}
|
|
me.master = tpls[tpls.length - 1];
|
|
me.tpls = tpls;
|
|
},
|
|
|
|
// @private
|
|
applySubTemplate: function(id, values, parent, xindex, xcount) {
|
|
var me = this, t = me.tpls[id];
|
|
return t.compiled.call(me, values, parent, xindex, xcount);
|
|
},
|
|
|
|
/**
|
|
* @cfg {RegExp} codeRe
|
|
* The regular expression used to match code variables. Default: matches {[expression]}.
|
|
*/
|
|
codeRe: /\{\[((?:\\\]|.|\n)*?)\]\}/g,
|
|
|
|
/**
|
|
* @cfg {Boolean} compiled
|
|
* Only applies to {@link Ext.Template}, XTemplates are compiled automatically.
|
|
*/
|
|
|
|
re: /\{([\w-\.\#]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?(\s?[\+\-\*\/]\s?[\d\.\+\-\*\/\(\)]+)?\}/g,
|
|
|
|
// @private
|
|
compileTpl: function(tpl) {
|
|
var fm = Ext.util.Format,
|
|
me = this,
|
|
useFormat = me.disableFormats !== true,
|
|
body, bodyReturn, evaluatedFn;
|
|
|
|
function fn(m, name, format, args, math) {
|
|
var v;
|
|
// name is what is inside the {}
|
|
// Name begins with xtpl, use a Sub Template
|
|
if (name.substr(0, 4) == 'xtpl') {
|
|
return "',this.applySubTemplate(" + name.substr(4) + ", values, parent, xindex, xcount),'";
|
|
}
|
|
// name = "." - Just use the values object.
|
|
if (name == '.') {
|
|
// filter to not include arrays/objects/nulls
|
|
v = 'Ext.Array.indexOf(["string", "number", "boolean"], typeof values) > -1 || Ext.isDate(values) ? values : ""';
|
|
}
|
|
|
|
// name = "#" - Use the xindex
|
|
else if (name == '#') {
|
|
v = 'xindex';
|
|
}
|
|
else if (name.substr(0, 7) == "parent.") {
|
|
v = name;
|
|
}
|
|
// name has a . in it - Use object literal notation, starting from values
|
|
else if (name.indexOf('.') != -1) {
|
|
v = "values." + name;
|
|
}
|
|
|
|
// name is a property of values
|
|
else {
|
|
v = "values['" + name + "']";
|
|
}
|
|
if (math) {
|
|
v = '(' + v + math + ')';
|
|
}
|
|
if (format && useFormat) {
|
|
args = args ? ',' + args : "";
|
|
if (format.substr(0, 5) != "this.") {
|
|
format = "fm." + format + '(';
|
|
}
|
|
else {
|
|
format = 'this.' + format.substr(5) + '(';
|
|
}
|
|
}
|
|
else {
|
|
args = '';
|
|
format = "(" + v + " === undefined ? '' : ";
|
|
}
|
|
return "'," + format + v + args + "),'";
|
|
}
|
|
|
|
function codeFn(m, code) {
|
|
// Single quotes get escaped when the template is compiled, however we want to undo this when running code.
|
|
return "',(" + code.replace(me.compileARe, "'") + "),'";
|
|
}
|
|
|
|
bodyReturn = tpl.body.replace(me.compileBRe, '\\n').replace(me.compileCRe, "\\'").replace(me.re, fn).replace(me.codeRe, codeFn);
|
|
body = "evaluatedFn = function(values, parent, xindex, xcount){return ['" + bodyReturn + "'].join('');};";
|
|
eval(body);
|
|
|
|
tpl.compiled = function(values, parent, xindex, xcount) {
|
|
var vs,
|
|
length,
|
|
buffer,
|
|
i;
|
|
|
|
if (tpl.test && !tpl.test.call(me, values, parent, xindex, xcount)) {
|
|
return '';
|
|
}
|
|
|
|
vs = tpl.target ? tpl.target.call(me, values, parent) : values;
|
|
if (!vs) {
|
|
return '';
|
|
}
|
|
|
|
parent = tpl.target ? values : parent;
|
|
if (tpl.target && Ext.isArray(vs)) {
|
|
buffer = [];
|
|
length = vs.length;
|
|
if (tpl.exec) {
|
|
for (i = 0; i < length; i++) {
|
|
buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
|
|
tpl.exec.call(me, vs[i], parent, i + 1, length);
|
|
}
|
|
} else {
|
|
for (i = 0; i < length; i++) {
|
|
buffer[buffer.length] = evaluatedFn.call(me, vs[i], parent, i + 1, length);
|
|
}
|
|
}
|
|
return buffer.join('');
|
|
}
|
|
|
|
if (tpl.exec) {
|
|
tpl.exec.call(me, vs, parent, xindex, xcount);
|
|
}
|
|
return evaluatedFn.call(me, vs, parent, xindex, xcount);
|
|
};
|
|
|
|
return this;
|
|
},
|
|
|
|
// inherit docs from Ext.Template
|
|
applyTemplate: function(values) {
|
|
return this.master.compiled.call(this, values, {}, 1, 1);
|
|
},
|
|
|
|
/**
|
|
* Does nothing. XTemplates are compiled automatically, so this function simply returns this.
|
|
* @return {Ext.XTemplate} this
|
|
*/
|
|
compile: function() {
|
|
return this;
|
|
}
|
|
}, function() {
|
|
// re-create the alias, inheriting it from Ext.Template doesn't work as intended.
|
|
this.createAlias('apply', 'applyTemplate');
|
|
});
|
|
|
|
|
|
Ext.define('Ext.app.Controller', {
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onClassExtended: function(cls, data) {
|
|
var className = Ext.getClassName(cls),
|
|
match = className.match(/^(.*)\.controller\./);
|
|
|
|
if (match !== null) {
|
|
var namespace = Ext.Loader.getPrefix(className) || match[1],
|
|
onBeforeClassCreated = data.onBeforeClassCreated,
|
|
requires = [],
|
|
modules = ['model', 'view', 'store'],
|
|
prefix;
|
|
|
|
data.onBeforeClassCreated = function(cls, data) {
|
|
var i, ln, module,
|
|
items, j, subLn, item;
|
|
|
|
for (i = 0,ln = modules.length; i < ln; i++) {
|
|
module = modules[i];
|
|
|
|
items = Ext.Array.from(data[module + 's']);
|
|
|
|
for (j = 0,subLn = items.length; j < subLn; j++) {
|
|
item = items[j];
|
|
|
|
prefix = Ext.Loader.getPrefix(item);
|
|
|
|
if (prefix === '' || prefix === item) {
|
|
requires.push(namespace + '.' + module + '.' + item);
|
|
}
|
|
else {
|
|
requires.push(item);
|
|
}
|
|
}
|
|
}
|
|
|
|
Ext.require(requires, Ext.Function.pass(onBeforeClassCreated, arguments, this));
|
|
};
|
|
}
|
|
},
|
|
|
|
|
|
constructor: function(config) {
|
|
this.mixins.observable.constructor.call(this, config);
|
|
|
|
Ext.apply(this, config || {});
|
|
|
|
this.createGetters('model', this.models);
|
|
this.createGetters('store', this.stores);
|
|
this.createGetters('view', this.views);
|
|
|
|
if (this.refs) {
|
|
this.ref(this.refs);
|
|
}
|
|
},
|
|
|
|
|
|
init: function(application) {},
|
|
|
|
|
|
onLaunch: function(application) {},
|
|
|
|
createGetters: function(type, refs) {
|
|
type = Ext.String.capitalize(type);
|
|
Ext.Array.each(refs, function(ref) {
|
|
var fn = 'get',
|
|
parts = ref.split('.');
|
|
|
|
|
|
Ext.Array.each(parts, function(part) {
|
|
fn += Ext.String.capitalize(part);
|
|
});
|
|
fn += type;
|
|
|
|
if (!this[fn]) {
|
|
this[fn] = Ext.Function.pass(this['get' + type], [ref], this);
|
|
}
|
|
|
|
this[fn](ref);
|
|
},
|
|
this);
|
|
},
|
|
|
|
ref: function(refs) {
|
|
var me = this;
|
|
refs = Ext.Array.from(refs);
|
|
Ext.Array.each(refs, function(info) {
|
|
var ref = info.ref,
|
|
fn = 'get' + Ext.String.capitalize(ref);
|
|
if (!me[fn]) {
|
|
me[fn] = Ext.Function.pass(me.getRef, [ref, info], me);
|
|
}
|
|
});
|
|
},
|
|
|
|
getRef: function(ref, info, config) {
|
|
this.refCache = this.refCache || {};
|
|
info = info || {};
|
|
config = config || {};
|
|
|
|
Ext.apply(info, config);
|
|
|
|
if (info.forceCreate) {
|
|
return Ext.ComponentManager.create(info, 'component');
|
|
}
|
|
|
|
var me = this,
|
|
selector = info.selector,
|
|
cached = me.refCache[ref];
|
|
|
|
if (!cached) {
|
|
me.refCache[ref] = cached = Ext.ComponentQuery.query(info.selector)[0];
|
|
if (!cached && info.autoCreate) {
|
|
me.refCache[ref] = cached = Ext.ComponentManager.create(info, 'component');
|
|
}
|
|
if (cached) {
|
|
cached.on('beforedestroy', function() {
|
|
me.refCache[ref] = null;
|
|
});
|
|
}
|
|
}
|
|
|
|
return cached;
|
|
},
|
|
|
|
|
|
control: function(selectors, listeners) {
|
|
this.application.control(selectors, listeners, this);
|
|
},
|
|
|
|
|
|
getController: function(name) {
|
|
return this.application.getController(name);
|
|
},
|
|
|
|
|
|
getStore: function(name) {
|
|
return this.application.getStore(name);
|
|
},
|
|
|
|
|
|
getModel: function(model) {
|
|
return this.application.getModel(model);
|
|
},
|
|
|
|
|
|
getView: function(view) {
|
|
return this.application.getView(view);
|
|
}
|
|
});
|
|
|
|
|
|
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 : function(s) {
|
|
return s;
|
|
},
|
|
|
|
|
|
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.util.Filter', {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
anyMatch: false,
|
|
|
|
|
|
exactMatch: false,
|
|
|
|
|
|
caseSensitive: false,
|
|
|
|
|
|
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
Ext.apply(me, config);
|
|
|
|
|
|
|
|
me.filter = me.filter || me.filterFn;
|
|
|
|
if (me.filter === undefined) {
|
|
if (me.property === undefined || me.value === undefined) {
|
|
|
|
|
|
|
|
|
|
} else {
|
|
me.filter = me.createFilterFn();
|
|
}
|
|
|
|
me.filterFn = me.filter;
|
|
}
|
|
},
|
|
|
|
|
|
createFilterFn: function() {
|
|
var me = this,
|
|
matcher = me.createValueMatcher(),
|
|
property = me.property;
|
|
|
|
return function(item) {
|
|
var value = me.getRoot.call(me, 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;
|
|
}
|
|
});
|
|
|
|
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,
|
|
property = me.property,
|
|
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;
|
|
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);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.data.Operation', {
|
|
|
|
synchronous: true,
|
|
|
|
|
|
action: undefined,
|
|
|
|
|
|
filters: undefined,
|
|
|
|
|
|
sorters: undefined,
|
|
|
|
|
|
group: 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,
|
|
mc, index, clientRecords, serverRec, clientRec;
|
|
|
|
if (!me.actionSkipSyncRe.test(me.action)) {
|
|
clientRecords = me.records;
|
|
|
|
if (clientRecords && clientRecords.length) {
|
|
mc = Ext.create('Ext.util.MixedCollection', true, function(r) {return r.getId();});
|
|
mc.addAll(clientRecords);
|
|
|
|
for (index = serverRecords ? serverRecords.length : 0; index--; ) {
|
|
serverRec = serverRecords[index];
|
|
clientRec = mc.get(serverRec.getId());
|
|
|
|
if (clientRec) {
|
|
clientRec.beginEdit();
|
|
clientRec.set(serverRec.data);
|
|
clientRec.endEdit(true);
|
|
}
|
|
}
|
|
|
|
if (me.actionCommitRecordsRe.test(me.action)) {
|
|
for (index = clientRecords.length; index--; ) {
|
|
clientRecords[index].commit();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
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 (resultSet === undefined ? this.records : resultSet.records);
|
|
},
|
|
|
|
|
|
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.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 (value === undefined) {
|
|
value = config;
|
|
}
|
|
|
|
|
|
return !!value || value === 0;
|
|
},
|
|
|
|
|
|
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.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.writer.Writer', {
|
|
alias: 'writer.base',
|
|
alternateClassName: ['Ext.data.DataWriter', 'Ext.data.Writer'],
|
|
|
|
|
|
writeAllFields: true,
|
|
|
|
|
|
nameProperty: 'name',
|
|
|
|
|
|
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]));
|
|
}
|
|
return this.writeRecords(request, data);
|
|
},
|
|
|
|
|
|
getRecordData: function(record) {
|
|
var isPhantom = record.phantom === true,
|
|
writeAll = this.writeAllFields || isPhantom,
|
|
nameProperty = this.nameProperty,
|
|
fields = record.fields,
|
|
data = {},
|
|
changes,
|
|
name,
|
|
field,
|
|
key;
|
|
|
|
if (writeAll) {
|
|
fields.each(function(field){
|
|
if (field.persist) {
|
|
name = field[nameProperty] || field.name;
|
|
data[name] = record.get(field.name);
|
|
}
|
|
});
|
|
} else {
|
|
|
|
changes = record.getChanges();
|
|
for (key in changes) {
|
|
if (changes.hasOwnProperty(key)) {
|
|
field = fields.get(key);
|
|
name = field[nameProperty] || field.name;
|
|
data[name] = changes[key];
|
|
}
|
|
}
|
|
if (!isPhantom) {
|
|
|
|
data[record.idProperty] = record.getId();
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.util.Floating', {
|
|
|
|
uses: ['Ext.Layer', 'Ext.window.Window'],
|
|
|
|
|
|
focusOnToFront: true,
|
|
|
|
|
|
shadow: 'sides',
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
me.floating = true;
|
|
me.el = Ext.create('Ext.Layer', Ext.apply({}, config, {
|
|
hideMode: me.hideMode,
|
|
hidden: me.hidden,
|
|
shadow: Ext.isDefined(me.shadow) ? me.shadow : 'sides',
|
|
shadowOffset: me.shadowOffset,
|
|
constrain: false,
|
|
shim: me.shim === false ? false : undefined
|
|
}), me.el);
|
|
},
|
|
|
|
onFloatRender: function() {
|
|
var me = this;
|
|
me.zIndexParent = me.getZIndexParent();
|
|
me.setFloatParent(me.ownerCt);
|
|
delete me.ownerCt;
|
|
|
|
if (me.zIndexParent) {
|
|
me.zIndexParent.registerFloatingItem(me);
|
|
} else {
|
|
Ext.WindowManager.register(me);
|
|
}
|
|
},
|
|
|
|
setFloatParent: function(floatParent) {
|
|
var me = this;
|
|
|
|
|
|
if (me.floatParent) {
|
|
me.mun(me.floatParent, {
|
|
hide: me.onFloatParentHide,
|
|
show: me.onFloatParentShow,
|
|
scope: me
|
|
});
|
|
}
|
|
|
|
me.floatParent = floatParent;
|
|
|
|
|
|
if (floatParent) {
|
|
me.mon(me.floatParent, {
|
|
hide: me.onFloatParentHide,
|
|
show: me.onFloatParentShow,
|
|
scope: me
|
|
});
|
|
}
|
|
|
|
|
|
|
|
if ((me.constrain || me.constrainHeader) && !me.constrainTo) {
|
|
me.constrainTo = floatParent ? floatParent.getTargetEl() : me.container;
|
|
}
|
|
},
|
|
|
|
onFloatParentHide: function() {
|
|
var me = this;
|
|
|
|
if (me.hideOnParentHide !== false) {
|
|
me.showOnParentShow = me.isVisible();
|
|
me.hide();
|
|
}
|
|
},
|
|
|
|
onFloatParentShow: function() {
|
|
if (this.showOnParentShow) {
|
|
delete this.showOnParentShow;
|
|
this.show();
|
|
}
|
|
},
|
|
|
|
|
|
getZIndexParent: function() {
|
|
var p = this.ownerCt,
|
|
c;
|
|
|
|
if (p) {
|
|
while (p) {
|
|
c = p;
|
|
p = p.ownerCt;
|
|
}
|
|
if (c.floating) {
|
|
return c;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
setZIndex: function(index) {
|
|
var me = this;
|
|
me.el.setZIndex(index);
|
|
|
|
|
|
index += 10;
|
|
|
|
|
|
|
|
if (me.floatingItems) {
|
|
index = Math.floor(me.floatingItems.setBase(index) / 100) * 100 + 10000;
|
|
}
|
|
return index;
|
|
},
|
|
|
|
|
|
doConstrain: function(constrainTo) {
|
|
var me = this,
|
|
vector = me.getConstrainVector(constrainTo || me.el.getScopeParent()),
|
|
xy;
|
|
|
|
if (vector) {
|
|
xy = me.getPosition();
|
|
xy[0] += vector[0];
|
|
xy[1] += vector[1];
|
|
me.setPosition(xy);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
getConstrainVector: function(constrainTo){
|
|
var me = this,
|
|
el;
|
|
|
|
if (me.constrain || me.constrainHeader) {
|
|
el = me.constrainHeader ? me.header.el : me.el;
|
|
constrainTo = constrainTo || (me.floatParent && me.floatParent.getTargetEl()) || me.container;
|
|
return el.getConstrainVector(constrainTo);
|
|
}
|
|
},
|
|
|
|
|
|
alignTo: function(element, position, offsets) {
|
|
if (element.isComponent) {
|
|
element = element.getEl();
|
|
}
|
|
var xy = this.el.getAlignToXY(element, position, offsets);
|
|
this.setPagePosition(xy);
|
|
return this;
|
|
},
|
|
|
|
|
|
toFront: function(preventFocus) {
|
|
var me = this;
|
|
|
|
|
|
|
|
if (me.zIndexParent) {
|
|
me.zIndexParent.toFront(true);
|
|
}
|
|
if (me.zIndexManager.bringToFront(me)) {
|
|
if (!Ext.isDefined(preventFocus)) {
|
|
preventFocus = !me.focusOnToFront;
|
|
}
|
|
if (!preventFocus) {
|
|
|
|
|
|
|
|
me.focus(false, true);
|
|
}
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
setActive: function(active, newActive) {
|
|
var me = this;
|
|
|
|
if (active) {
|
|
if (me.el.shadow && !me.maximized) {
|
|
me.el.enableShadow(true);
|
|
}
|
|
me.fireEvent('activate', me);
|
|
} else {
|
|
|
|
|
|
if ((me instanceof Ext.window.Window) && (newActive instanceof Ext.window.Window)) {
|
|
me.el.disableShadow();
|
|
}
|
|
me.fireEvent('deactivate', me);
|
|
}
|
|
},
|
|
|
|
|
|
toBack: function() {
|
|
this.zIndexManager.sendToBack(this);
|
|
return this;
|
|
},
|
|
|
|
|
|
center: function() {
|
|
var me = this,
|
|
xy = me.el.getAlignToXY(me.container, 'c-c');
|
|
me.setPagePosition(xy);
|
|
return me;
|
|
},
|
|
|
|
|
|
syncShadow : function(){
|
|
if (this.floating) {
|
|
this.el.sync(true);
|
|
}
|
|
},
|
|
|
|
|
|
fitContainer: function() {
|
|
var parent = this.floatParent,
|
|
container = parent ? parent.getTargetEl() : this.container,
|
|
size = container.getViewSize(false);
|
|
|
|
this.setSize(size);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.layout.Layout', {
|
|
|
|
|
|
|
|
|
|
|
|
isLayout: true,
|
|
initialized: false,
|
|
|
|
statics: {
|
|
create: function(layout, defaultType) {
|
|
var type;
|
|
if (layout instanceof Ext.layout.Layout) {
|
|
return Ext.createByAlias('layout.' + layout);
|
|
} else {
|
|
if (!layout || typeof layout === 'string') {
|
|
type = layout || defaultType;
|
|
layout = {};
|
|
}
|
|
else {
|
|
type = layout.type || defaultType;
|
|
}
|
|
return Ext.createByAlias('layout.' + type, layout || {});
|
|
}
|
|
}
|
|
},
|
|
|
|
constructor : function(config) {
|
|
this.id = Ext.id(null, this.type + '-');
|
|
Ext.apply(this, config);
|
|
},
|
|
|
|
|
|
layout : function() {
|
|
var me = this;
|
|
me.layoutBusy = true;
|
|
me.initLayout();
|
|
|
|
if (me.beforeLayout.apply(me, arguments) !== false) {
|
|
me.layoutCancelled = false;
|
|
me.onLayout.apply(me, arguments);
|
|
me.childrenChanged = false;
|
|
me.owner.needsLayout = false;
|
|
me.layoutBusy = false;
|
|
me.afterLayout.apply(me, arguments);
|
|
}
|
|
else {
|
|
me.layoutCancelled = true;
|
|
}
|
|
me.layoutBusy = false;
|
|
me.doOwnerCtLayouts();
|
|
},
|
|
|
|
beforeLayout : function() {
|
|
this.renderChildren();
|
|
return true;
|
|
},
|
|
|
|
renderChildren: function () {
|
|
this.renderItems(this.getLayoutItems(), this.getRenderTarget());
|
|
},
|
|
|
|
|
|
renderItems : function(items, target) {
|
|
var me = this,
|
|
ln = items.length,
|
|
i = 0,
|
|
item;
|
|
|
|
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);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
isValidParent : function(item, target, position) {
|
|
var dom = item.el ? item.el.dom : Ext.getDom(item);
|
|
if (dom && target && target.dom) {
|
|
if (Ext.isNumber(position) && dom !== target.dom.childNodes[position]) {
|
|
return false;
|
|
}
|
|
return (dom.parentNode == (target.dom || target));
|
|
}
|
|
return false;
|
|
},
|
|
|
|
|
|
renderItem : function(item, target, position) {
|
|
var me = this;
|
|
if (!item.rendered) {
|
|
if (me.itemCls) {
|
|
item.addCls(me.itemCls);
|
|
}
|
|
if (me.owner.itemCls) {
|
|
item.addCls(me.owner.itemCls);
|
|
}
|
|
item.render(target, position);
|
|
me.configureItem(item);
|
|
me.childrenChanged = true;
|
|
}
|
|
},
|
|
|
|
|
|
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);
|
|
this.childrenChanged = true;
|
|
},
|
|
|
|
|
|
initLayout : function() {
|
|
var me = this,
|
|
targetCls = me.targetCls;
|
|
|
|
if (!me.initialized && !Ext.isEmpty(targetCls)) {
|
|
me.getTarget().addCls(targetCls);
|
|
}
|
|
me.initialized = true;
|
|
},
|
|
|
|
|
|
setOwner : function(owner) {
|
|
this.owner = owner;
|
|
},
|
|
|
|
|
|
getLayoutItems : function() {
|
|
return [];
|
|
},
|
|
|
|
|
|
configureItem: Ext.emptyFn,
|
|
|
|
|
|
onLayout : Ext.emptyFn,
|
|
afterLayout : Ext.emptyFn,
|
|
onRemove : Ext.emptyFn,
|
|
onDestroy : Ext.emptyFn,
|
|
doOwnerCtLayouts : Ext.emptyFn,
|
|
|
|
|
|
afterRemove : function(item) {
|
|
var el = item.el,
|
|
owner = this.owner,
|
|
itemCls = this.itemCls,
|
|
ownerCls = owner.itemCls;
|
|
|
|
|
|
if (item.rendered && !item.isDestroyed) {
|
|
if (itemCls) {
|
|
el.removeCls(itemCls);
|
|
}
|
|
if (ownerCls) {
|
|
el.removeCls(ownerCls);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
delete item.layoutManagedWidth;
|
|
delete item.layoutManagedHeight;
|
|
},
|
|
|
|
|
|
destroy : function() {
|
|
var targetCls = this.targetCls,
|
|
target;
|
|
|
|
if (!Ext.isEmpty(targetCls)) {
|
|
target = this.getTarget();
|
|
if (target) {
|
|
target.removeCls(targetCls);
|
|
}
|
|
}
|
|
this.onDestroy();
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.ZIndexManager', {
|
|
|
|
alternateClassName: 'Ext.WindowGroup',
|
|
|
|
statics: {
|
|
zBase : 9000
|
|
},
|
|
|
|
constructor: function(container) {
|
|
var me = this;
|
|
|
|
me.list = {};
|
|
me.zIndexStack = [];
|
|
me.front = null;
|
|
|
|
if (container) {
|
|
|
|
|
|
if (container.isContainer) {
|
|
container.on('resize', me._onContainerResize, me);
|
|
me.zseed = Ext.Number.from(container.getEl().getStyle('zIndex'), 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;
|
|
return this.assignZIndices();
|
|
},
|
|
|
|
|
|
assignZIndices: function() {
|
|
var a = this.zIndexStack,
|
|
len = a.length,
|
|
i = 0,
|
|
zIndex = this.zseed,
|
|
comp;
|
|
|
|
for (; i < len; i++) {
|
|
comp = a[i];
|
|
if (comp && !comp.hidden) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
zIndex = comp.setZIndex(zIndex);
|
|
}
|
|
}
|
|
this._activateLast();
|
|
return zIndex;
|
|
},
|
|
|
|
|
|
_setActiveChild: function(comp) {
|
|
if (comp !== this.front) {
|
|
|
|
if (this.front) {
|
|
this.front.setActive(false, comp);
|
|
}
|
|
this.front = comp;
|
|
if (comp) {
|
|
comp.setActive(true);
|
|
if (comp.modal) {
|
|
this._showModalMask(comp);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
_activateLast: function(justHidden) {
|
|
var comp,
|
|
lastActivated = false,
|
|
i;
|
|
|
|
|
|
|
|
|
|
for (i = this.zIndexStack.length-1; i >= 0; --i) {
|
|
comp = this.zIndexStack[i];
|
|
if (!comp.hidden) {
|
|
if (!lastActivated) {
|
|
this._setActiveChild(comp);
|
|
lastActivated = true;
|
|
}
|
|
|
|
|
|
if (comp.modal) {
|
|
this._showModalMask(comp);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
this._hideModalMask();
|
|
if (!lastActivated) {
|
|
this._setActiveChild(null);
|
|
}
|
|
},
|
|
|
|
_showModalMask: function(comp) {
|
|
var zIndex = comp.el.getStyle('zIndex') - 4,
|
|
maskTarget = comp.floatParent ? comp.floatParent.getTargetEl() : Ext.get(comp.getEl().dom.parentNode),
|
|
parentBox;
|
|
|
|
if (!maskTarget) {
|
|
return;
|
|
}
|
|
|
|
parentBox = maskTarget.getBox();
|
|
|
|
if (!this.mask) {
|
|
this.mask = Ext.getBody().createChild({
|
|
cls: Ext.baseCSSPrefix + 'mask'
|
|
});
|
|
this.mask.setVisibilityMode(Ext.Element.DISPLAY);
|
|
this.mask.on('click', this._onMaskClick, this);
|
|
}
|
|
if (maskTarget.dom === document.body) {
|
|
parentBox.height = Ext.Element.getViewHeight();
|
|
}
|
|
maskTarget.addCls(Ext.baseCSSPrefix + 'body-masked');
|
|
this.mask.setBox(parentBox);
|
|
this.mask.setStyle('zIndex', zIndex);
|
|
this.mask.show();
|
|
},
|
|
|
|
_hideModalMask: function() {
|
|
if (this.mask && this.mask.dom.parentNode) {
|
|
Ext.get(this.mask.dom.parentNode).removeCls(Ext.baseCSSPrefix + 'body-masked');
|
|
this.mask.hide();
|
|
}
|
|
},
|
|
|
|
_onMaskClick: function() {
|
|
if (this.front) {
|
|
this.front.focus();
|
|
}
|
|
},
|
|
|
|
_onContainerResize: function() {
|
|
if (this.mask && this.mask.isVisible()) {
|
|
this.mask.setSize(Ext.get(this.mask.dom.parentNode).getViewSize(true));
|
|
}
|
|
},
|
|
|
|
|
|
register : function(comp) {
|
|
if (comp.zIndexManager) {
|
|
comp.zIndexManager.unregister(comp);
|
|
}
|
|
comp.zIndexManager = this;
|
|
|
|
this.list[comp.id] = comp;
|
|
this.zIndexStack.push(comp);
|
|
comp.on('hide', this._activateLast, this);
|
|
},
|
|
|
|
|
|
unregister : function(comp) {
|
|
delete comp.zIndexManager;
|
|
if (this.list && this.list[comp.id]) {
|
|
delete this.list[comp.id];
|
|
comp.un('hide', this._activateLast);
|
|
Ext.Array.remove(this.zIndexStack, comp);
|
|
|
|
|
|
this._activateLast(comp);
|
|
}
|
|
},
|
|
|
|
|
|
get : function(id) {
|
|
return typeof id == "object" ? id : this.list[id];
|
|
},
|
|
|
|
|
|
bringToFront : function(comp) {
|
|
comp = this.get(comp);
|
|
if (comp !== this.front) {
|
|
Ext.Array.remove(this.zIndexStack, comp);
|
|
this.zIndexStack.push(comp);
|
|
this.assignZIndices();
|
|
return true;
|
|
}
|
|
if (comp.modal) {
|
|
this._showModalMask(comp);
|
|
}
|
|
return false;
|
|
},
|
|
|
|
|
|
sendToBack : function(comp) {
|
|
comp = this.get(comp);
|
|
Ext.Array.remove(this.zIndexStack, comp);
|
|
this.zIndexStack.unshift(comp);
|
|
this.assignZIndices();
|
|
return comp;
|
|
},
|
|
|
|
|
|
hideAll : function() {
|
|
for (var id in this.list) {
|
|
if (this.list[id].isComponent && this.list[id].isVisible()) {
|
|
this.list[id].hide();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
hide: function() {
|
|
var i = 0,
|
|
ln = this.zIndexStack.length,
|
|
comp;
|
|
|
|
this.tempHidden = [];
|
|
for (; i < ln; i++) {
|
|
comp = this.zIndexStack[i];
|
|
if (comp.isVisible()) {
|
|
this.tempHidden.push(comp);
|
|
comp.hide();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
show: function() {
|
|
var i = 0,
|
|
ln = this.tempHidden.length,
|
|
comp,
|
|
x,
|
|
y;
|
|
|
|
for (; i < ln; i++) {
|
|
comp = this.tempHidden[i];
|
|
x = comp.x;
|
|
y = comp.y;
|
|
comp.show();
|
|
comp.setPosition(x, y);
|
|
}
|
|
delete this.tempHidden;
|
|
},
|
|
|
|
|
|
getActive : function() {
|
|
return this.front;
|
|
},
|
|
|
|
|
|
getBy : function(fn, scope) {
|
|
var r = [],
|
|
i = 0,
|
|
len = this.zIndexStack.length,
|
|
comp;
|
|
|
|
for (; i < len; i++) {
|
|
comp = this.zIndexStack[i];
|
|
if (fn.call(scope||comp, comp) !== false) {
|
|
r.push(comp);
|
|
}
|
|
}
|
|
return r;
|
|
},
|
|
|
|
|
|
each : function(fn, scope) {
|
|
var comp;
|
|
for (var id in this.list) {
|
|
comp = this.list[id];
|
|
if (comp.isComponent && fn.call(scope || comp, comp) === false) {
|
|
return;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
eachBottomUp: function (fn, scope) {
|
|
var comp,
|
|
stack = this.zIndexStack,
|
|
i, n;
|
|
|
|
for (i = 0, n = stack.length ; i < n; i++) {
|
|
comp = stack[i];
|
|
if (comp.isComponent && fn.call(scope || comp, comp) === false) {
|
|
return;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
eachTopDown: function (fn, scope) {
|
|
var comp,
|
|
stack = this.zIndexStack,
|
|
i;
|
|
|
|
for (i = stack.length ; i-- > 0; ) {
|
|
comp = stack[i];
|
|
if (comp.isComponent && fn.call(scope || comp, comp) === false) {
|
|
return;
|
|
}
|
|
}
|
|
},
|
|
|
|
destroy: function() {
|
|
this.each(function(c) {
|
|
c.destroy();
|
|
});
|
|
delete this.zIndexStack;
|
|
delete this.list;
|
|
delete this.container;
|
|
delete this.targetEl;
|
|
}
|
|
}, function() {
|
|
|
|
Ext.WindowManager = Ext.WindowMgr = new this();
|
|
});
|
|
|
|
|
|
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,
|
|
|
|
onRemove: Ext.emptyFn,
|
|
|
|
|
|
getItem: function(item) {
|
|
return this.layout.owner.getComponent(item);
|
|
},
|
|
|
|
onRemove: Ext.emptyFn
|
|
});
|
|
|
|
Ext.define('Ext.util.KeyMap', {
|
|
alternateClassName: 'Ext.KeyMap',
|
|
|
|
|
|
constructor: function(el, binding, eventName){
|
|
var me = this;
|
|
|
|
Ext.apply(me, {
|
|
el: Ext.get(el),
|
|
eventName: eventName || me.eventName,
|
|
bindings: []
|
|
});
|
|
if (binding) {
|
|
me.addBinding(binding);
|
|
}
|
|
me.enable();
|
|
},
|
|
|
|
eventName: 'keydown',
|
|
|
|
|
|
addBinding : function(binding){
|
|
if (Ext.isArray(binding)) {
|
|
Ext.each(binding, this.addBinding, this);
|
|
return;
|
|
}
|
|
|
|
var keyCode = binding.key,
|
|
processed = false,
|
|
key,
|
|
keys,
|
|
keyString,
|
|
i,
|
|
len;
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.bindings.push(Ext.apply({
|
|
keyCode: keyCode
|
|
}, binding));
|
|
},
|
|
|
|
|
|
handleKeyDown: function(event) {
|
|
if (this.enabled) {
|
|
var bindings = this.bindings,
|
|
i = 0,
|
|
len = bindings.length;
|
|
|
|
event = this.processEvent(event);
|
|
for(; i < len; ++i){
|
|
this.processBinding(bindings[i], event);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
processEvent: function(event){
|
|
return event;
|
|
},
|
|
|
|
|
|
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
|
|
});
|
|
},
|
|
|
|
|
|
isEnabled : function(){
|
|
return this.enabled;
|
|
},
|
|
|
|
|
|
enable: function(){
|
|
var me = this;
|
|
|
|
if (!me.enabled) {
|
|
me.el.on(me.eventName, me.handleKeyDown, me);
|
|
me.enabled = true;
|
|
}
|
|
},
|
|
|
|
|
|
disable: function(){
|
|
var me = this;
|
|
|
|
if (me.enabled) {
|
|
me.el.removeListener(me.eventName, me.handleKeyDown, me);
|
|
me.enabled = false;
|
|
}
|
|
},
|
|
|
|
|
|
setDisabled : function(disabled){
|
|
if (disabled) {
|
|
this.disable();
|
|
} else {
|
|
this.enable();
|
|
}
|
|
},
|
|
|
|
|
|
destroy: function(removeEl){
|
|
var me = this;
|
|
|
|
me.bindings = [];
|
|
me.disable();
|
|
if (removeEl === true) {
|
|
me.el.remove();
|
|
}
|
|
delete me.el;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.util.ClickRepeater', {
|
|
extend: 'Ext.util.Observable',
|
|
|
|
|
|
constructor : function(el, config){
|
|
this.el = Ext.get(el);
|
|
this.el.unselectable();
|
|
|
|
Ext.apply(this, config);
|
|
|
|
this.addEvents(
|
|
|
|
"mousedown",
|
|
|
|
"click",
|
|
|
|
"mouseup"
|
|
);
|
|
|
|
if(!this.disabled){
|
|
this.disabled = true;
|
|
this.enable();
|
|
}
|
|
|
|
|
|
if(this.handler){
|
|
this.on("click", this.handler, this.scope || this);
|
|
}
|
|
|
|
this.callParent();
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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){
|
|
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.Component', {
|
|
|
|
|
|
|
|
extend: 'Ext.layout.Layout',
|
|
|
|
|
|
|
|
type: 'component',
|
|
|
|
monitorChildren: true,
|
|
|
|
initLayout : function() {
|
|
var me = this,
|
|
owner = me.owner,
|
|
ownerEl = owner.el;
|
|
|
|
if (!me.initialized) {
|
|
if (owner.frameSize) {
|
|
me.frameSize = owner.frameSize;
|
|
}
|
|
else {
|
|
owner.frameSize = me.frameSize = {
|
|
top: 0,
|
|
left: 0,
|
|
bottom: 0,
|
|
right: 0
|
|
};
|
|
}
|
|
}
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
beforeLayout : function(width, height, isSetSize, callingContainer) {
|
|
this.callParent(arguments);
|
|
|
|
var me = this,
|
|
owner = me.owner,
|
|
ownerCt = owner.ownerCt,
|
|
layout = owner.layout,
|
|
isVisible = owner.isVisible(true),
|
|
ownerElChild = owner.el.child,
|
|
layoutCollection;
|
|
|
|
|
|
me.previousComponentSize = me.lastComponentSize;
|
|
|
|
|
|
if (!isSetSize
|
|
&& ((!Ext.isNumber(width) && owner.isFixedWidth()) ||
|
|
(!Ext.isNumber(height) && owner.isFixedHeight()))
|
|
|
|
&& callingContainer && callingContainer !== ownerCt) {
|
|
|
|
me.doContainerLayout();
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
if (!isVisible && (owner.hiddenAncestor || owner.floating)) {
|
|
if (owner.hiddenAncestor) {
|
|
layoutCollection = owner.hiddenAncestor.layoutOnShow;
|
|
layoutCollection.remove(owner);
|
|
layoutCollection.add(owner);
|
|
}
|
|
owner.needsLayout = {
|
|
width: width,
|
|
height: height,
|
|
isSetSize: false
|
|
};
|
|
}
|
|
|
|
if (isVisible && this.needsLayout(width, height)) {
|
|
return owner.beforeComponentLayout(width, height, isSetSize, callingContainer);
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
|
|
needsLayout : function(width, height) {
|
|
var me = this,
|
|
widthBeingChanged,
|
|
heightBeingChanged;
|
|
me.lastComponentSize = me.lastComponentSize || {
|
|
width: -Infinity,
|
|
height: -Infinity
|
|
};
|
|
|
|
|
|
widthBeingChanged = !Ext.isDefined(width) || me.lastComponentSize.width !== width;
|
|
|
|
|
|
heightBeingChanged = !Ext.isDefined(height) || me.lastComponentSize.height !== height;
|
|
|
|
|
|
|
|
return !me.isSizing && (me.childrenChanged || widthBeingChanged || heightBeingChanged);
|
|
},
|
|
|
|
|
|
setElementSize: function(el, width, height) {
|
|
if (width !== undefined && height !== undefined) {
|
|
el.setSize(width, height);
|
|
}
|
|
else if (height !== undefined) {
|
|
el.setHeight(height);
|
|
}
|
|
else if (width !== undefined) {
|
|
el.setWidth(width);
|
|
}
|
|
},
|
|
|
|
|
|
getTarget : function() {
|
|
return this.owner.el;
|
|
},
|
|
|
|
|
|
getRenderTarget : function() {
|
|
return this.owner.el;
|
|
},
|
|
|
|
|
|
setTargetSize : function(width, height) {
|
|
var me = this;
|
|
me.setElementSize(me.owner.el, width, height);
|
|
|
|
if (me.owner.frameBody) {
|
|
var targetInfo = me.getTargetInfo(),
|
|
padding = targetInfo.padding,
|
|
border = targetInfo.border,
|
|
frameSize = me.frameSize;
|
|
|
|
me.setElementSize(me.owner.frameBody,
|
|
Ext.isNumber(width) ? (width - frameSize.left - frameSize.right - padding.left - padding.right - border.left - border.right) : width,
|
|
Ext.isNumber(height) ? (height - frameSize.top - frameSize.bottom - padding.top - padding.bottom - border.top - border.bottom) : height
|
|
);
|
|
}
|
|
|
|
me.autoSized = {
|
|
width: !Ext.isNumber(width),
|
|
height: !Ext.isNumber(height)
|
|
};
|
|
|
|
me.lastComponentSize = {
|
|
width: width,
|
|
height: height
|
|
};
|
|
},
|
|
|
|
getTargetInfo : function() {
|
|
if (!this.targetInfo) {
|
|
var target = this.getTarget(),
|
|
body = this.owner.getTargetEl();
|
|
|
|
this.targetInfo = {
|
|
padding: {
|
|
top: target.getPadding('t'),
|
|
right: target.getPadding('r'),
|
|
bottom: target.getPadding('b'),
|
|
left: target.getPadding('l')
|
|
},
|
|
border: {
|
|
top: target.getBorderWidth('t'),
|
|
right: target.getBorderWidth('r'),
|
|
bottom: target.getBorderWidth('b'),
|
|
left: target.getBorderWidth('l')
|
|
},
|
|
bodyMargin: {
|
|
top: body.getMargin('t'),
|
|
right: body.getMargin('r'),
|
|
bottom: body.getMargin('b'),
|
|
left: body.getMargin('l')
|
|
}
|
|
};
|
|
}
|
|
return this.targetInfo;
|
|
},
|
|
|
|
|
|
doOwnerCtLayouts: function() {
|
|
var owner = this.owner,
|
|
ownerCt = owner.ownerCt,
|
|
ownerCtComponentLayout, ownerCtContainerLayout,
|
|
curSize = this.lastComponentSize,
|
|
prevSize = this.previousComponentSize,
|
|
widthChange = (prevSize && curSize && Ext.isNumber(curSize.width )) ? curSize.width !== prevSize.width : true,
|
|
heightChange = (prevSize && curSize && Ext.isNumber(curSize.height)) ? curSize.height !== prevSize.height : true;
|
|
|
|
|
|
if (!ownerCt || (!widthChange && !heightChange)) {
|
|
return;
|
|
}
|
|
|
|
ownerCtComponentLayout = ownerCt.componentLayout;
|
|
ownerCtContainerLayout = ownerCt.layout;
|
|
|
|
if (!owner.floating && ownerCtComponentLayout && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
|
|
if (!ownerCt.suspendLayout && ownerCtContainerLayout && !ownerCtContainerLayout.layoutBusy) {
|
|
|
|
|
|
if (((widthChange && !ownerCt.isFixedWidth()) || (heightChange && !ownerCt.isFixedHeight()))) {
|
|
|
|
this.isSizing = true;
|
|
ownerCt.doComponentLayout();
|
|
this.isSizing = false;
|
|
}
|
|
|
|
else if (ownerCtContainerLayout.bindToOwnerCtContainer === true) {
|
|
ownerCtContainerLayout.layout();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
doContainerLayout: function() {
|
|
var me = this,
|
|
owner = me.owner,
|
|
ownerCt = owner.ownerCt,
|
|
layout = owner.layout,
|
|
ownerCtComponentLayout;
|
|
|
|
|
|
|
|
if (!owner.suspendLayout && layout && layout.isLayout && !layout.layoutBusy && !layout.isAutoDock) {
|
|
layout.layout();
|
|
}
|
|
|
|
|
|
if (ownerCt && ownerCt.componentLayout) {
|
|
ownerCtComponentLayout = ownerCt.componentLayout;
|
|
if (!owner.floating && ownerCtComponentLayout.monitorChildren && !ownerCtComponentLayout.layoutBusy) {
|
|
ownerCtComponentLayout.childrenChanged = true;
|
|
}
|
|
}
|
|
},
|
|
|
|
afterLayout : function(width, height, isSetSize, layoutOwner) {
|
|
this.doContainerLayout();
|
|
this.owner.afterComponentLayout(width, height, isSetSize, layoutOwner);
|
|
}
|
|
});
|
|
|
|
|
|
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 measure = this.measure = Ext.getBody().createChild({
|
|
cls: 'x-textmetrics'
|
|
});
|
|
this.el = Ext.get(bindTo);
|
|
|
|
measure.position('absolute');
|
|
measure.setLeftTop(-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.layout.container.boxOverflow.Scroller', {
|
|
|
|
|
|
|
|
extend: 'Ext.layout.container.boxOverflow.None',
|
|
requires: ['Ext.util.ClickRepeater', 'Ext.Element'],
|
|
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) {
|
|
this.layout = layout;
|
|
Ext.apply(this, config || {});
|
|
|
|
this.addEvents(
|
|
|
|
'scroll'
|
|
);
|
|
},
|
|
|
|
initCSSClasses: function() {
|
|
var me = this,
|
|
layout = me.layout;
|
|
|
|
if (!me.CSSinitialized) {
|
|
me.beforeCtCls = me.beforeCtCls || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelBefore;
|
|
me.afterCtCls = me.afterCtCls || Ext.baseCSSPrefix + 'box-scroller-' + layout.parallelAfter;
|
|
me.beforeScrollerCls = me.beforeScrollerCls || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelBefore;
|
|
me.afterScrollerCls = me.afterScrollerCls || Ext.baseCSSPrefix + layout.owner.getXType() + '-scroll-' + layout.parallelAfter;
|
|
me.CSSinitializes = true;
|
|
}
|
|
},
|
|
|
|
handleOverflow: function(calculations, targetSize) {
|
|
var me = this,
|
|
layout = me.layout,
|
|
methodName = 'get' + layout.parallelPrefixCap,
|
|
newSize = {};
|
|
|
|
me.initCSSClasses();
|
|
me.callParent(arguments);
|
|
this.createInnerElements();
|
|
this.showScrollers();
|
|
newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
|
|
newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - (me.beforeCt[methodName]() + me.afterCt[methodName]());
|
|
return { targetSize: newSize };
|
|
},
|
|
|
|
|
|
createInnerElements: function() {
|
|
var me = this,
|
|
target = me.layout.getRenderTarget();
|
|
|
|
|
|
|
|
if (!me.beforeCt) {
|
|
target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
|
|
me.beforeCt = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.beforeCtCls}, 'before');
|
|
me.afterCt = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + me.afterCtCls}, 'after');
|
|
me.createWheelListener();
|
|
}
|
|
},
|
|
|
|
|
|
createWheelListener: function() {
|
|
this.layout.innerCt.on({
|
|
scope : this,
|
|
mousewheel: function(e) {
|
|
e.stopEvent();
|
|
|
|
this.scrollBy(e.getWheelDelta() * this.wheelIncrement * -1, false);
|
|
}
|
|
});
|
|
},
|
|
|
|
|
|
clearOverflow: function() {
|
|
this.hideScrollers();
|
|
},
|
|
|
|
|
|
showScrollers: function() {
|
|
this.createScrollers();
|
|
this.beforeScroller.show();
|
|
this.afterScroller.show();
|
|
this.updateScrollButtons();
|
|
|
|
this.layout.owner.addClsWithUI('scroller');
|
|
},
|
|
|
|
|
|
hideScrollers: function() {
|
|
if (this.beforeScroller != undefined) {
|
|
this.beforeScroller.hide();
|
|
this.afterScroller.hide();
|
|
|
|
this.layout.owner.removeClsWithUI('scroller');
|
|
}
|
|
},
|
|
|
|
|
|
createScrollers: function() {
|
|
if (!this.beforeScroller && !this.afterScroller) {
|
|
var before = this.beforeCt.createChild({
|
|
cls: Ext.String.format("{0} {1} ", this.scrollerCls, this.beforeScrollerCls)
|
|
});
|
|
|
|
var after = this.afterCt.createChild({
|
|
cls: Ext.String.format("{0} {1}", this.scrollerCls, this.afterScrollerCls)
|
|
});
|
|
|
|
before.addClsOnOver(this.beforeScrollerCls + '-hover');
|
|
after.addClsOnOver(this.afterScrollerCls + '-hover');
|
|
|
|
before.setVisibilityMode(Ext.Element.DISPLAY);
|
|
after.setVisibilityMode(Ext.Element.DISPLAY);
|
|
|
|
this.beforeRepeater = Ext.create('Ext.util.ClickRepeater', before, {
|
|
interval: this.scrollRepeatInterval,
|
|
handler : this.scrollLeft,
|
|
scope : this
|
|
});
|
|
|
|
this.afterRepeater = Ext.create('Ext.util.ClickRepeater', after, {
|
|
interval: this.scrollRepeatInterval,
|
|
handler : this.scrollRight,
|
|
scope : this
|
|
});
|
|
|
|
|
|
this.beforeScroller = before;
|
|
|
|
|
|
this.afterScroller = after;
|
|
}
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
Ext.destroy(this.beforeRepeater, this.afterRepeater, this.beforeScroller, this.afterScroller, this.beforeCt, this.afterCt);
|
|
},
|
|
|
|
|
|
scrollBy: function(delta, animate) {
|
|
this.scrollTo(this.getScrollPosition() + delta, animate);
|
|
},
|
|
|
|
|
|
getScrollAnim: function() {
|
|
return {
|
|
duration: this.scrollDuration,
|
|
callback: this.updateScrollButtons,
|
|
scope : this
|
|
};
|
|
},
|
|
|
|
|
|
updateScrollButtons: function() {
|
|
if (this.beforeScroller == undefined || this.afterScroller == undefined) {
|
|
return;
|
|
}
|
|
|
|
var beforeMeth = this.atExtremeBefore() ? 'addCls' : 'removeCls',
|
|
afterMeth = this.atExtremeAfter() ? 'addCls' : 'removeCls',
|
|
beforeCls = this.beforeScrollerCls + '-disabled',
|
|
afterCls = this.afterScrollerCls + '-disabled';
|
|
|
|
this.beforeScroller[beforeMeth](beforeCls);
|
|
this.afterScroller[afterMeth](afterCls);
|
|
this.scrolling = false;
|
|
},
|
|
|
|
|
|
atExtremeBefore: function() {
|
|
return this.getScrollPosition() === 0;
|
|
},
|
|
|
|
|
|
scrollLeft: function() {
|
|
this.scrollBy(-this.scrollIncrement, false);
|
|
},
|
|
|
|
|
|
scrollRight: function() {
|
|
this.scrollBy(this.scrollIncrement, false);
|
|
},
|
|
|
|
|
|
getScrollPosition: function(){
|
|
var layout = this.layout;
|
|
return parseInt(layout.innerCt.dom['scroll' + layout.parallelBeforeCap], 10) || 0;
|
|
},
|
|
|
|
|
|
getMaxScrollPosition: function() {
|
|
var layout = this.layout;
|
|
return layout.innerCt.dom['scroll' + layout.parallelPrefixCap] - this.layout.innerCt['get' + layout.parallelPrefixCap]();
|
|
},
|
|
|
|
|
|
atExtremeAfter: function() {
|
|
return this.getScrollPosition() >= this.getMaxScrollPosition();
|
|
},
|
|
|
|
|
|
scrollTo: function(position, animate) {
|
|
var me = this,
|
|
layout = me.layout,
|
|
oldPosition = me.getScrollPosition(),
|
|
newPosition = Ext.Number.constrain(position, 0, me.getMaxScrollPosition());
|
|
|
|
if (newPosition != oldPosition && !me.scrolling) {
|
|
if (animate == undefined) {
|
|
animate = me.animateScroll;
|
|
}
|
|
|
|
layout.innerCt.scrollTo(layout.parallelBefore, newPosition, animate ? me.getScrollAnim() : false);
|
|
if (animate) {
|
|
me.scrolling = true;
|
|
} else {
|
|
me.scrolling = false;
|
|
me.updateScrollButtons();
|
|
}
|
|
|
|
me.fireEvent('scroll', me, newPosition, animate ? me.getScrollAnim() : false);
|
|
}
|
|
},
|
|
|
|
|
|
scrollToItem: function(item, animate) {
|
|
var me = this,
|
|
layout = me.layout,
|
|
visibility,
|
|
box,
|
|
newPos;
|
|
|
|
item = me.getItem(item);
|
|
if (item != undefined) {
|
|
visibility = this.getItemVisibility(item);
|
|
if (!visibility.fullyVisible) {
|
|
box = item.getBox(true, true);
|
|
newPos = box[layout.parallelPosition];
|
|
if (visibility.hiddenEnd) {
|
|
newPos -= (this.layout.innerCt['get' + layout.parallelPrefixCap]() - box[layout.parallelPrefix]);
|
|
}
|
|
this.scrollTo(newPos, animate);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getItemVisibility: function(item) {
|
|
var me = this,
|
|
box = me.getItem(item).getBox(true, true),
|
|
layout = me.layout,
|
|
itemStart = box[layout.parallelPosition],
|
|
itemEnd = itemStart + box[layout.parallelPrefix],
|
|
scrollStart = me.getScrollPosition(),
|
|
scrollEnd = scrollStart + layout.innerCt['get' + layout.parallelPrefixCap]();
|
|
|
|
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.KeyNav', {
|
|
|
|
alternateClassName: 'Ext.KeyNav',
|
|
|
|
requires: ['Ext.util.KeyMap'],
|
|
|
|
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(el, config){
|
|
this.setConfig(el, config || {});
|
|
},
|
|
|
|
|
|
setConfig: function(el, config) {
|
|
if (this.map) {
|
|
this.map.destroy();
|
|
}
|
|
|
|
var map = Ext.create('Ext.util.KeyMap', el, null, this.getKeyEvent('forceKeyDown' in config ? config.forceKeyDown : this.forceKeyDown)),
|
|
keys = Ext.util.KeyNav.keyOptions,
|
|
scope = config.scope || this,
|
|
key;
|
|
|
|
this.map = map;
|
|
for (key in keys) {
|
|
if (keys.hasOwnProperty(key)) {
|
|
if (config[key]) {
|
|
map.addBinding({
|
|
scope: scope,
|
|
key: keys[key],
|
|
handler: Ext.Function.bind(this.handleEvent, scope, [config[key]], true),
|
|
defaultEventAction: config.defaultEventAction || this.defaultEventAction
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
map.disable();
|
|
if (!config.disabled) {
|
|
map.enable();
|
|
}
|
|
},
|
|
|
|
|
|
handleEvent: function(map, event, handler){
|
|
return handler.call(this, event);
|
|
},
|
|
|
|
|
|
disabled: false,
|
|
|
|
|
|
defaultEventAction: "stopEvent",
|
|
|
|
|
|
forceKeyDown: false,
|
|
|
|
|
|
destroy: function(removeEl){
|
|
this.map.destroy(removeEl);
|
|
delete this.map;
|
|
},
|
|
|
|
|
|
enable: function() {
|
|
this.map.enable();
|
|
this.disabled = false;
|
|
},
|
|
|
|
|
|
disable: function() {
|
|
this.map.disable();
|
|
this.disabled = true;
|
|
},
|
|
|
|
|
|
setDisabled : function(disabled){
|
|
this.map.setDisabled(disabled);
|
|
this.disabled = disabled;
|
|
},
|
|
|
|
|
|
getKeyEvent: function(forceKeyDown){
|
|
return (forceKeyDown || Ext.EventManager.useKeyDown) ? 'keydown' : 'keypress';
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.fx.Queue', {
|
|
|
|
requires: ['Ext.util.HashMap'],
|
|
|
|
constructor: function() {
|
|
this.targets = Ext.create('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 (anim.remove) {
|
|
if (target.type == 'element') {
|
|
var el = Ext.get(target.id);
|
|
if (el) {
|
|
el.remove();
|
|
}
|
|
}
|
|
}
|
|
}, this);
|
|
queue.push(anim);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.fx.target.Target', {
|
|
|
|
isAnimTarget: true,
|
|
|
|
|
|
constructor: function(target) {
|
|
this.target = target;
|
|
this.id = this.getId();
|
|
},
|
|
|
|
getId: function() {
|
|
return this.target.id;
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.fx.target.Sprite', {
|
|
|
|
|
|
|
|
extend: 'Ext.fx.target.Target',
|
|
|
|
|
|
|
|
type: 'draw',
|
|
|
|
getFromPrim: function(sprite, attr) {
|
|
var o;
|
|
if (attr == 'translate') {
|
|
o = {
|
|
x: sprite.attr.translation.x || 0,
|
|
y: sprite.attr.translation.y || 0
|
|
};
|
|
}
|
|
else if (attr == 'rotate') {
|
|
o = {
|
|
degrees: sprite.attr.rotation.degrees || 0,
|
|
x: sprite.attr.rotation.x,
|
|
y: sprite.attr.rotation.y
|
|
};
|
|
}
|
|
else {
|
|
o = sprite.attr[attr];
|
|
}
|
|
return o;
|
|
},
|
|
|
|
getAttr: function(attr, val) {
|
|
return [[this.target, val != undefined ? val : this.getFromPrim(this.target, attr)]];
|
|
},
|
|
|
|
setAttr: function(targetData) {
|
|
var ln = targetData.length,
|
|
spriteArr = [],
|
|
attrs, attr, attrArr, attPtr, spritePtr, idx, value, i, j, x, y, ln2;
|
|
for (i = 0; i < ln; i++) {
|
|
attrs = targetData[i].attrs;
|
|
for (attr in attrs) {
|
|
attrArr = attrs[attr];
|
|
ln2 = attrArr.length;
|
|
for (j = 0; j < ln2; j++) {
|
|
spritePtr = attrArr[j][0];
|
|
attPtr = attrArr[j][1];
|
|
if (attr === 'translate') {
|
|
value = {
|
|
x: attPtr.x,
|
|
y: attPtr.y
|
|
};
|
|
}
|
|
else if (attr === 'rotate') {
|
|
x = attPtr.x;
|
|
if (isNaN(x)) {
|
|
x = null;
|
|
}
|
|
y = attPtr.y;
|
|
if (isNaN(y)) {
|
|
y = null;
|
|
}
|
|
value = {
|
|
degrees: attPtr.degrees,
|
|
x: x,
|
|
y: y
|
|
};
|
|
}
|
|
else if (attr === 'width' || attr === 'height' || attr === 'x' || attr === 'y') {
|
|
value = parseFloat(attPtr);
|
|
}
|
|
else {
|
|
value = attPtr;
|
|
}
|
|
idx = Ext.Array.indexOf(spriteArr, spritePtr);
|
|
if (idx == -1) {
|
|
spriteArr.push([spritePtr, {}]);
|
|
idx = spriteArr.length - 1;
|
|
}
|
|
spriteArr[idx][1][attr] = value;
|
|
}
|
|
}
|
|
}
|
|
ln = spriteArr.length;
|
|
for (i = 0; i < ln; i++) {
|
|
spritePtr = spriteArr[i];
|
|
spritePtr[0].setAttributes(spritePtr[1]);
|
|
}
|
|
this.target.redraw();
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.fx.target.CompositeSprite', {
|
|
|
|
|
|
|
|
extend: 'Ext.fx.target.Sprite',
|
|
|
|
|
|
|
|
getAttr: function(attr, val) {
|
|
var out = [],
|
|
target = this.target;
|
|
target.each(function(sprite) {
|
|
out.push([sprite, val != undefined ? val : this.getFromPrim(sprite, attr)]);
|
|
}, this);
|
|
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');
|
|
}
|
|
},
|
|
|
|
compMethod: {
|
|
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,
|
|
target = me.target,
|
|
ln = targetData.length,
|
|
attrs, attr, o, i, j, meth, targets, left, top, w, h;
|
|
for (i = 0; i < ln; i++) {
|
|
attrs = targetData[i].attrs;
|
|
for (attr in attrs) {
|
|
targets = attrs[attr].length;
|
|
meth = {
|
|
setPosition: {},
|
|
setPagePosition: {},
|
|
setSize: {},
|
|
setOpacity: {}
|
|
};
|
|
for (j = 0; j < targets; j++) {
|
|
o = attrs[attr][j];
|
|
|
|
|
|
|
|
|
|
meth[me.compMethod[attr]].target = o[0];
|
|
meth[me.compMethod[attr]][attr] = o[1];
|
|
}
|
|
if (meth.setPosition.target) {
|
|
o = meth.setPosition;
|
|
left = (o.left === undefined) ? undefined : parseInt(o.left, 10);
|
|
top = (o.top === undefined) ? undefined : parseInt(o.top, 10);
|
|
o.target.setPosition(left, top);
|
|
}
|
|
if (meth.setPagePosition.target) {
|
|
o = meth.setPagePosition;
|
|
o.target.setPagePosition(o.x, o.y);
|
|
}
|
|
if (meth.setSize.target && meth.setSize.target.el) {
|
|
o = meth.setSize;
|
|
|
|
w = (o.width === undefined) ? o.target.getWidth() : parseInt(o.width, 10);
|
|
h = (o.height === undefined) ? o.target.getHeight() : parseInt(o.height, 10);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (isLastFrame || me.dynamic) {
|
|
o.target.componentLayout.childrenChanged = true;
|
|
|
|
|
|
if (me.layoutAnimation) {
|
|
o.target.setCalculatedSize(w, h);
|
|
} else {
|
|
o.target.setSize(w, h);
|
|
}
|
|
}
|
|
else {
|
|
o.target.el.setSize(w, h);
|
|
}
|
|
}
|
|
if (meth.setOpacity.target) {
|
|
o = meth.setOpacity;
|
|
o.target.el.setStyle('opacity', o.opacity);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
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.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);
|
|
|
|
if (Ext.isArray(digits)) {
|
|
var 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 '';
|
|
}
|
|
},
|
|
|
|
|
|
fromString: function(str) {
|
|
var values, r, g, b,
|
|
parse = parseInt;
|
|
|
|
if ((str.length == 4 || str.length == 7) && str.substr(0, 1) === '#') {
|
|
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 : Ext.create('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 Ext.create('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);
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
Ext.define('Ext.dd.StatusProxy', {
|
|
animRepair: false,
|
|
|
|
|
|
constructor: function(config){
|
|
Ext.apply(this, config);
|
|
this.id = this.id || Ext.id();
|
|
this.proxy = Ext.createWidget('component', {
|
|
floating: true,
|
|
stateful: false,
|
|
id: this.id,
|
|
html: '<div class="' + Ext.baseCSSPrefix + 'dd-drop-icon"></div>' +
|
|
'<div class="' + Ext.baseCSSPrefix + 'dd-drag-ghost"></div>',
|
|
cls: Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed,
|
|
shadow: !config || config.shadow !== false,
|
|
renderTo: document.body
|
|
});
|
|
|
|
this.el = this.proxy.el;
|
|
this.el.show();
|
|
this.el.setVisibilityMode(Ext.Element.VISIBILITY);
|
|
this.el.hide();
|
|
|
|
this.ghost = Ext.get(this.el.dom.childNodes[1]);
|
|
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){
|
|
this.el.dom.className = Ext.baseCSSPrefix + 'dd-drag-proxy ' + this.dropNotAllowed;
|
|
this.dropStatus = this.dropNotAllowed;
|
|
if(clearGhost){
|
|
this.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');
|
|
}
|
|
},
|
|
|
|
|
|
getEl : function(){
|
|
return this.el;
|
|
},
|
|
|
|
|
|
getGhost : function(){
|
|
return this.ghost;
|
|
},
|
|
|
|
|
|
hide : function(clear) {
|
|
this.proxy.hide();
|
|
if (clear) {
|
|
this.reset(true);
|
|
}
|
|
},
|
|
|
|
|
|
stop : function(){
|
|
if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
|
|
this.anim.stop();
|
|
}
|
|
},
|
|
|
|
|
|
show : function() {
|
|
this.proxy.show();
|
|
this.proxy.toFront();
|
|
},
|
|
|
|
|
|
sync : function(){
|
|
this.proxy.el.sync();
|
|
},
|
|
|
|
|
|
repair : function(xy, callback, scope){
|
|
this.callback = callback;
|
|
this.scope = scope;
|
|
if (xy && this.animRepair !== false) {
|
|
this.el.addCls(Ext.baseCSSPrefix + 'dd-drag-repair');
|
|
this.el.hideUnders(true);
|
|
this.anim = this.el.animate({
|
|
duration: this.repairDuration || 500,
|
|
easing: 'ease-out',
|
|
to: {
|
|
x: xy[0],
|
|
y: xy[1]
|
|
},
|
|
stopAnimation: true,
|
|
callback: this.afterRepair,
|
|
scope: this
|
|
});
|
|
} else {
|
|
this.afterRepair();
|
|
}
|
|
},
|
|
|
|
|
|
afterRepair : function(){
|
|
this.hide(true);
|
|
if(typeof this.callback == "function"){
|
|
this.callback.call(this.scope || this);
|
|
}
|
|
this.callback = null;
|
|
this.scope = null;
|
|
},
|
|
|
|
destroy: function(){
|
|
Ext.destroy(this.ghost, this.proxy, this.el);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.panel.Proxy', {
|
|
|
|
alternateClassName: 'Ext.dd.PanelProxy',
|
|
|
|
|
|
constructor: function(panel, config){
|
|
|
|
this.panel = panel;
|
|
this.id = this.panel.id +'-ddproxy';
|
|
Ext.apply(this, 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(){
|
|
if (this.ghost) {
|
|
if (this.proxy) {
|
|
this.proxy.remove();
|
|
delete this.proxy;
|
|
}
|
|
|
|
|
|
this.panel.unghost(null, false);
|
|
delete this.ghost;
|
|
}
|
|
},
|
|
|
|
|
|
show: function(){
|
|
if (!this.ghost) {
|
|
var panelSize = this.panel.getSize();
|
|
this.panel.el.setVisibilityMode(Ext.Element.DISPLAY);
|
|
this.ghost = this.panel.ghost();
|
|
if (this.insertProxy) {
|
|
|
|
|
|
this.proxy = this.panel.el.insertSibling({cls: Ext.baseCSSPrefix + 'panel-dd-spacer'});
|
|
this.proxy.setSize(panelSize);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
repair: function(xy, callback, scope) {
|
|
this.hide();
|
|
if (typeof callback == "function") {
|
|
callback.call(scope || this);
|
|
}
|
|
},
|
|
|
|
|
|
moveProxy : function(parentNode, before){
|
|
if (this.proxy) {
|
|
parentNode.insertBefore(this.proxy.dom, before);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.component.AbstractDock', {
|
|
|
|
|
|
|
|
extend: 'Ext.layout.component.Component',
|
|
|
|
|
|
|
|
type: 'dock',
|
|
|
|
|
|
autoSizing: true,
|
|
|
|
beforeLayout: function() {
|
|
var returnValue = this.callParent(arguments);
|
|
if (returnValue !== false && (!this.initializedBorders || this.childrenChanged) && (!this.owner.border || this.owner.manageBodyBorders)) {
|
|
this.handleItemBorders();
|
|
this.initializedBorders = true;
|
|
}
|
|
return returnValue;
|
|
},
|
|
|
|
handleItemBorders: function() {
|
|
var owner = this.owner,
|
|
body = owner.body,
|
|
docked = this.getLayoutItems(),
|
|
borders = {
|
|
top: [],
|
|
right: [],
|
|
bottom: [],
|
|
left: []
|
|
},
|
|
oldBorders = this.borders,
|
|
opposites = {
|
|
top: 'bottom',
|
|
right: 'left',
|
|
bottom: 'top',
|
|
left: 'right'
|
|
},
|
|
i, ln, item, dock, side;
|
|
|
|
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 && opposites[dock] !== 'top') {
|
|
borders.top.push(item);
|
|
}
|
|
if (!borders.right.satisfied && opposites[dock] !== 'right') {
|
|
borders.right.push(item);
|
|
}
|
|
if (!borders.bottom.satisfied && opposites[dock] !== 'bottom') {
|
|
borders.bottom.push(item);
|
|
}
|
|
if (!borders.left.satisfied && opposites[dock] !== 'left') {
|
|
borders.left.push(item);
|
|
}
|
|
}
|
|
|
|
if (oldBorders) {
|
|
for (side in oldBorders) {
|
|
if (oldBorders.hasOwnProperty(side)) {
|
|
ln = oldBorders[side].length;
|
|
if (!owner.manageBodyBorders) {
|
|
for (i = 0; i < ln; i++) {
|
|
oldBorders[side][i].removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
|
|
}
|
|
if (!oldBorders[side].satisfied && !owner.bodyBorder) {
|
|
body.removeCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
|
|
}
|
|
}
|
|
else if (oldBorders[side].satisfied) {
|
|
body.setStyle('border-' + side + '-width', '');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (side in borders) {
|
|
if (borders.hasOwnProperty(side)) {
|
|
ln = borders[side].length;
|
|
if (!owner.manageBodyBorders) {
|
|
for (i = 0; i < ln; i++) {
|
|
borders[side][i].addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
|
|
}
|
|
if ((!borders[side].satisfied && !owner.bodyBorder) || owner.bodyBorder === false) {
|
|
body.addCls(Ext.baseCSSPrefix + 'docked-noborder-' + side);
|
|
}
|
|
}
|
|
else if (borders[side].satisfied) {
|
|
body.setStyle('border-' + side + '-width', '1px');
|
|
}
|
|
}
|
|
}
|
|
|
|
this.borders = borders;
|
|
},
|
|
|
|
|
|
onLayout: function(width, height) {
|
|
if (this.onLayout_running) {
|
|
return;
|
|
}
|
|
this.onLayout_running = true;
|
|
var me = this,
|
|
owner = me.owner,
|
|
body = owner.body,
|
|
layout = owner.layout,
|
|
target = me.getTarget(),
|
|
autoWidth = false,
|
|
autoHeight = false,
|
|
padding, border, frameSize;
|
|
|
|
|
|
var info = me.info = {
|
|
boxes: [],
|
|
size: {
|
|
width: width,
|
|
height: height
|
|
},
|
|
bodyBox: {}
|
|
};
|
|
|
|
delete layout.isAutoDock;
|
|
|
|
Ext.applyIf(info, me.getTargetInfo());
|
|
|
|
|
|
if (owner && owner.ownerCt && owner.ownerCt.layout && owner.ownerCt.layout.isLayout) {
|
|
if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
|
|
owner.ownerCt.layout.bindToOwnerCtComponent = true;
|
|
}
|
|
else {
|
|
owner.ownerCt.layout.bindToOwnerCtComponent = false;
|
|
}
|
|
}
|
|
|
|
|
|
if (height == null || width == null) {
|
|
padding = info.padding;
|
|
border = info.border;
|
|
frameSize = me.frameSize;
|
|
|
|
|
|
if ((height == null) && (width == null)) {
|
|
autoHeight = true;
|
|
autoWidth = true;
|
|
me.setTargetSize(null);
|
|
me.setBodyBox({width: null, height: null});
|
|
}
|
|
|
|
else if (height == null) {
|
|
autoHeight = true;
|
|
|
|
me.setTargetSize(width);
|
|
me.setBodyBox({width: width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right, height: null});
|
|
|
|
}
|
|
else {
|
|
autoWidth = true;
|
|
|
|
me.setTargetSize(null, height);
|
|
me.setBodyBox({width: null, height: height - padding.top - padding.bottom - border.top - border.bottom - frameSize.top - frameSize.bottom});
|
|
}
|
|
|
|
|
|
if (layout && layout.isLayout) {
|
|
|
|
layout.bindToOwnerCtComponent = true;
|
|
|
|
layout.isAutoDock = layout.autoSize !== true;
|
|
layout.layout();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
info.autoSizedCtLayout = layout.autoSize === true;
|
|
info.autoHeight = autoHeight;
|
|
info.autoWidth = autoWidth;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
me.dockItems();
|
|
me.setTargetSize(info.size.width, info.size.height);
|
|
}
|
|
else {
|
|
me.setTargetSize(width, height);
|
|
me.dockItems();
|
|
}
|
|
me.callParent(arguments);
|
|
this.onLayout_running = false;
|
|
},
|
|
|
|
|
|
dockItems : function() {
|
|
this.calculateDockBoxes();
|
|
|
|
|
|
|
|
|
|
var info = this.info,
|
|
autoWidth = info.autoWidth,
|
|
autoHeight = info.autoHeight,
|
|
boxes = info.boxes,
|
|
ln = boxes.length,
|
|
dock, i, item;
|
|
|
|
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
dock = boxes[i];
|
|
item = dock.item;
|
|
item.setPosition(dock.x, dock.y);
|
|
if ((autoWidth || autoHeight) && item.layout && item.layout.isLayout) {
|
|
|
|
item.layout.bindToOwnerCtComponent = true;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!info.autoSizedCtLayout) {
|
|
if (autoWidth) {
|
|
info.bodyBox.width = null;
|
|
}
|
|
if (autoHeight) {
|
|
info.bodyBox.height = null;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
this.setBodyBox(info.bodyBox);
|
|
},
|
|
|
|
|
|
calculateDockBoxes : function() {
|
|
if (this.calculateDockBoxes_running) {
|
|
|
|
return;
|
|
}
|
|
this.calculateDockBoxes_running = true;
|
|
|
|
|
|
|
|
var me = this,
|
|
target = me.getTarget(),
|
|
items = me.getLayoutItems(),
|
|
owner = me.owner,
|
|
bodyEl = owner.body,
|
|
info = me.info,
|
|
autoWidth = info.autoWidth,
|
|
autoHeight = info.autoHeight,
|
|
size = info.size,
|
|
ln = items.length,
|
|
padding = info.padding,
|
|
border = info.border,
|
|
frameSize = me.frameSize,
|
|
item, i, box, rect;
|
|
|
|
|
|
|
|
if (autoHeight) {
|
|
size.height = bodyEl.getHeight() + padding.top + border.top + padding.bottom + border.bottom + frameSize.top + frameSize.bottom;
|
|
}
|
|
else {
|
|
size.height = target.getHeight();
|
|
}
|
|
if (autoWidth) {
|
|
size.width = bodyEl.getWidth() + padding.left + border.left + padding.right + border.right + frameSize.left + frameSize.right;
|
|
}
|
|
else {
|
|
size.width = target.getWidth();
|
|
}
|
|
|
|
info.bodyBox = {
|
|
x: padding.left + frameSize.left,
|
|
y: padding.top + frameSize.top,
|
|
width: size.width - padding.left - border.left - padding.right - border.right - frameSize.left - frameSize.right,
|
|
height: size.height - border.top - padding.top - border.bottom - padding.bottom - frameSize.top - frameSize.bottom
|
|
};
|
|
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
item = items[i];
|
|
|
|
|
|
|
|
box = me.initBox(item);
|
|
|
|
if (autoHeight === true) {
|
|
box = me.adjustAutoBox(box, i);
|
|
}
|
|
else {
|
|
box = me.adjustSizedBox(box, i);
|
|
}
|
|
|
|
|
|
|
|
|
|
info.boxes.push(box);
|
|
}
|
|
this.calculateDockBoxes_running = false;
|
|
},
|
|
|
|
|
|
adjustSizedBox : function(box, index) {
|
|
var bodyBox = this.info.bodyBox,
|
|
frameSize = this.frameSize,
|
|
info = this.info,
|
|
padding = info.padding,
|
|
pos = box.type,
|
|
border = info.border;
|
|
|
|
switch (pos) {
|
|
case 'top':
|
|
box.y = bodyBox.y;
|
|
break;
|
|
|
|
case 'left':
|
|
box.x = bodyBox.x;
|
|
break;
|
|
|
|
case 'bottom':
|
|
box.y = (bodyBox.y + bodyBox.height) - box.height;
|
|
break;
|
|
|
|
case 'right':
|
|
box.x = (bodyBox.x + bodyBox.width) - box.width;
|
|
break;
|
|
}
|
|
|
|
if (box.ignoreFrame) {
|
|
if (pos == 'bottom') {
|
|
box.y += (frameSize.bottom + padding.bottom + border.bottom);
|
|
}
|
|
else {
|
|
box.y -= (frameSize.top + padding.top + border.top);
|
|
}
|
|
if (pos == 'right') {
|
|
box.x += (frameSize.right + padding.right + border.right);
|
|
}
|
|
else {
|
|
box.x -= (frameSize.left + padding.left + border.left);
|
|
}
|
|
}
|
|
|
|
|
|
if (!box.overlay) {
|
|
switch (pos) {
|
|
case 'top':
|
|
bodyBox.y += box.height;
|
|
bodyBox.height -= box.height;
|
|
break;
|
|
|
|
case 'left':
|
|
bodyBox.x += box.width;
|
|
bodyBox.width -= box.width;
|
|
break;
|
|
|
|
case 'bottom':
|
|
bodyBox.height -= box.height;
|
|
break;
|
|
|
|
case 'right':
|
|
bodyBox.width -= box.width;
|
|
break;
|
|
}
|
|
}
|
|
return box;
|
|
},
|
|
|
|
|
|
adjustAutoBox : function (box, index) {
|
|
var info = this.info,
|
|
owner = this.owner,
|
|
bodyBox = info.bodyBox,
|
|
size = info.size,
|
|
boxes = info.boxes,
|
|
boxesLn = boxes.length,
|
|
pos = box.type,
|
|
frameSize = this.frameSize,
|
|
padding = info.padding,
|
|
border = info.border,
|
|
autoSizedCtLayout = info.autoSizedCtLayout,
|
|
ln = (boxesLn < index) ? boxesLn : index,
|
|
i, adjustBox;
|
|
|
|
if (pos == 'top' || pos == 'bottom') {
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
adjustBox = boxes[i];
|
|
if (adjustBox.stretched && adjustBox.type == 'left' || adjustBox.type == 'right') {
|
|
adjustBox.height += box.height;
|
|
}
|
|
else if (adjustBox.type == 'bottom') {
|
|
adjustBox.y += box.height;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (pos) {
|
|
case 'top':
|
|
box.y = bodyBox.y;
|
|
if (!box.overlay) {
|
|
bodyBox.y += box.height;
|
|
if (info.autoHeight) {
|
|
size.height += box.height;
|
|
} else {
|
|
bodyBox.height -= box.height;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'bottom':
|
|
if (!box.overlay) {
|
|
if (info.autoHeight) {
|
|
size.height += box.height;
|
|
} else {
|
|
bodyBox.height -= box.height;
|
|
}
|
|
}
|
|
box.y = (bodyBox.y + bodyBox.height);
|
|
break;
|
|
|
|
case 'left':
|
|
box.x = bodyBox.x;
|
|
if (!box.overlay) {
|
|
bodyBox.x += box.width;
|
|
if (info.autoWidth) {
|
|
size.width += box.width;
|
|
} else {
|
|
bodyBox.width -= box.width;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'right':
|
|
if (!box.overlay) {
|
|
if (info.autoWidth) {
|
|
size.width += box.width;
|
|
} else {
|
|
bodyBox.width -= box.width;
|
|
}
|
|
}
|
|
box.x = (bodyBox.x + bodyBox.width);
|
|
break;
|
|
}
|
|
|
|
if (box.ignoreFrame) {
|
|
if (pos == 'bottom') {
|
|
box.y += (frameSize.bottom + padding.bottom + border.bottom);
|
|
}
|
|
else {
|
|
box.y -= (frameSize.top + padding.top + border.top);
|
|
}
|
|
if (pos == 'right') {
|
|
box.x += (frameSize.right + padding.right + border.right);
|
|
}
|
|
else {
|
|
box.x -= (frameSize.left + padding.left + border.left);
|
|
}
|
|
}
|
|
return box;
|
|
},
|
|
|
|
|
|
initBox : function(item) {
|
|
var me = this,
|
|
bodyBox = me.info.bodyBox,
|
|
horizontal = (item.dock == 'top' || item.dock == 'bottom'),
|
|
owner = me.owner,
|
|
frameSize = me.frameSize,
|
|
info = me.info,
|
|
padding = info.padding,
|
|
border = info.border,
|
|
box = {
|
|
item: item,
|
|
overlay: item.overlay,
|
|
type: item.dock,
|
|
offsets: Ext.Element.parseBox(item.offsets || {}),
|
|
ignoreFrame: item.ignoreParentFrame
|
|
};
|
|
|
|
if (item.stretch !== false) {
|
|
box.stretched = true;
|
|
if (horizontal) {
|
|
box.x = bodyBox.x + box.offsets.left;
|
|
box.width = bodyBox.width - (box.offsets.left + box.offsets.right);
|
|
if (box.ignoreFrame) {
|
|
box.width += (frameSize.left + frameSize.right + border.left + border.right + padding.left + padding.right);
|
|
}
|
|
item.setCalculatedSize(box.width - item.el.getMargin('lr'), undefined, owner);
|
|
}
|
|
else {
|
|
box.y = bodyBox.y + box.offsets.top;
|
|
box.height = bodyBox.height - (box.offsets.bottom + box.offsets.top);
|
|
if (box.ignoreFrame) {
|
|
box.height += (frameSize.top + frameSize.bottom + border.top + border.bottom + padding.top + padding.bottom);
|
|
}
|
|
item.setCalculatedSize(undefined, box.height - item.el.getMargin('tb'), owner);
|
|
|
|
|
|
|
|
if (!Ext.supports.ComputedStyle) {
|
|
item.el.repaint();
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
item.doComponentLayout();
|
|
box.width = item.getWidth() - (box.offsets.left + box.offsets.right);
|
|
box.height = item.getHeight() - (box.offsets.bottom + box.offsets.top);
|
|
box.y += box.offsets.top;
|
|
if (horizontal) {
|
|
box.x = (item.align == 'right') ? bodyBox.width - box.width : bodyBox.x;
|
|
box.x += box.offsets.left;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (box.width === undefined) {
|
|
box.width = item.getWidth() + item.el.getMargin('lr');
|
|
}
|
|
if (box.height === undefined) {
|
|
box.height = item.getHeight() + item.el.getMargin('tb');
|
|
}
|
|
|
|
return box;
|
|
},
|
|
|
|
|
|
getLayoutItems : function() {
|
|
var it = this.owner.getDockedItems(),
|
|
ln = it.length,
|
|
i = 0,
|
|
result = [];
|
|
for (; i < ln; i++) {
|
|
if (it[i].isVisible(true)) {
|
|
result.push(it[i]);
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
|
|
renderItems: function(items, target) {
|
|
var cns = target.dom.childNodes,
|
|
cnsLn = cns.length,
|
|
ln = items.length,
|
|
domLn = 0,
|
|
i, j, cn, item;
|
|
|
|
|
|
for (i = 0; i < cnsLn; i++) {
|
|
cn = Ext.get(cns[i]);
|
|
for (j = 0; j < ln; j++) {
|
|
item = items[j];
|
|
if (item.rendered && (cn.id == item.el.id || cn.contains(item.el.id))) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (j === ln) {
|
|
domLn++;
|
|
}
|
|
}
|
|
|
|
|
|
for (i = 0, j = 0; i < ln; i++, j++) {
|
|
item = items[i];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (i === j && (item.dock === 'right' || item.dock === 'bottom')) {
|
|
j += domLn;
|
|
}
|
|
|
|
|
|
if (item && !item.rendered) {
|
|
this.renderItem(item, target, j);
|
|
}
|
|
else if (!this.isValidParent(item, target, j)) {
|
|
this.moveItem(item, target, j);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
setBodyBox : function(box) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
body = owner.body,
|
|
info = me.info,
|
|
bodyMargin = info.bodyMargin,
|
|
padding = info.padding,
|
|
border = info.border,
|
|
frameSize = me.frameSize;
|
|
|
|
|
|
if (owner.collapsed) {
|
|
return;
|
|
}
|
|
|
|
if (Ext.isNumber(box.width)) {
|
|
box.width -= bodyMargin.left + bodyMargin.right;
|
|
}
|
|
|
|
if (Ext.isNumber(box.height)) {
|
|
box.height -= bodyMargin.top + bodyMargin.bottom;
|
|
}
|
|
|
|
me.setElementSize(body, box.width, box.height);
|
|
if (Ext.isNumber(box.x)) {
|
|
body.setLeft(box.x - padding.left - frameSize.left);
|
|
}
|
|
if (Ext.isNumber(box.y)) {
|
|
body.setTop(box.y - padding.top - frameSize.top);
|
|
}
|
|
},
|
|
|
|
|
|
configureItem : function(item, pos) {
|
|
this.callParent(arguments);
|
|
if (item.dock == 'top' || item.dock == 'bottom') {
|
|
item.layoutManagedWidth = 1;
|
|
item.layoutManagedHeight = 2;
|
|
} else {
|
|
item.layoutManagedWidth = 2;
|
|
item.layoutManagedHeight = 1;
|
|
}
|
|
|
|
item.addCls(Ext.baseCSSPrefix + 'docked');
|
|
item.addClsWithUI('docked-' + item.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;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.util.Memento', function () {
|
|
|
|
function captureOne (src, target, prop) {
|
|
src[prop] = target[prop];
|
|
}
|
|
|
|
function removeOne (src, target, prop) {
|
|
delete src[prop];
|
|
}
|
|
|
|
function restoreOne (src, target, prop) {
|
|
var value = src[prop];
|
|
if (value || src.hasOwnProperty(prop)) {
|
|
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) {
|
|
if (src) {
|
|
if (Ext.isArray(props)) {
|
|
Ext.each(props, function (prop) {
|
|
doOne(src, target, prop);
|
|
});
|
|
} else {
|
|
doOne(src, target, props);
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
|
|
data: null,
|
|
|
|
|
|
target: null,
|
|
|
|
|
|
constructor: function (target, props) {
|
|
if (target) {
|
|
this.target = target;
|
|
if (props) {
|
|
this.capture(props);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
capture: function (props, target) {
|
|
doMany(captureOne, this.data || (this.data = {}), target || this.target, props);
|
|
},
|
|
|
|
|
|
remove: function (props) {
|
|
doMany(removeOne, this.data, null, props);
|
|
},
|
|
|
|
|
|
restore: function (props, clear, target) {
|
|
doMany(restoreOne, this.data, target || this.target, props);
|
|
if (clear !== false) {
|
|
this.remove(props);
|
|
}
|
|
},
|
|
|
|
|
|
restoreAll: function (clear, target) {
|
|
var me = this,
|
|
t = target || this.target;
|
|
|
|
Ext.Object.each(me.data, function (prop, value) {
|
|
restoreValue(t, prop, value);
|
|
});
|
|
|
|
if (clear !== false) {
|
|
delete me.data;
|
|
}
|
|
}
|
|
};
|
|
}());
|
|
|
|
|
|
Ext.define('Ext.app.EventBus', {
|
|
requires: [
|
|
'Ext.util.Event'
|
|
],
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
constructor: function() {
|
|
this.mixins.observable.constructor.call(this);
|
|
|
|
this.bus = {};
|
|
|
|
var me = this;
|
|
Ext.override(Ext.Component, {
|
|
fireEvent: function(ev) {
|
|
if (Ext.util.Observable.prototype.fireEvent.apply(this, arguments) !== false) {
|
|
return me.dispatch.call(me, ev, this, arguments);
|
|
}
|
|
return false;
|
|
}
|
|
});
|
|
},
|
|
|
|
dispatch: function(ev, target, args) {
|
|
var bus = this.bus,
|
|
selectors = bus[ev],
|
|
selector, controllers, id, events, event, i, ln;
|
|
|
|
if (selectors) {
|
|
|
|
for (selector in selectors) {
|
|
|
|
if (target.is(selector)) {
|
|
|
|
controllers = selectors[selector];
|
|
for (id in controllers) {
|
|
|
|
events = controllers[id];
|
|
for (i = 0, ln = events.length; i < ln; i++) {
|
|
event = events[i];
|
|
|
|
if (event.fire.apply(event, Array.prototype.slice.call(args, 1)) === false) {
|
|
return false;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
control: function(selectors, listeners, controller) {
|
|
var bus = this.bus,
|
|
selector, fn;
|
|
|
|
if (Ext.isString(selectors)) {
|
|
selector = selectors;
|
|
selectors = {};
|
|
selectors[selector] = listeners;
|
|
this.control(selectors, null, controller);
|
|
return;
|
|
}
|
|
|
|
Ext.Object.each(selectors, function(selector, listeners) {
|
|
Ext.Object.each(listeners, function(ev, listener) {
|
|
var options = {},
|
|
scope = controller,
|
|
event = Ext.create('Ext.util.Event', controller, ev);
|
|
|
|
|
|
if (Ext.isObject(listener)) {
|
|
options = listener;
|
|
listener = options.fn;
|
|
scope = options.scope || controller;
|
|
delete options.fn;
|
|
delete options.scope;
|
|
}
|
|
|
|
event.addListener(listener, scope, options);
|
|
|
|
|
|
bus[ev] = bus[ev] || {};
|
|
bus[ev][selector] = bus[ev][selector] || {};
|
|
bus[ev][selector][controller.id] = bus[ev][selector][controller.id] || [];
|
|
|
|
|
|
bus[ev][selector][controller.id].push(event);
|
|
});
|
|
});
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.data.Types', {
|
|
singleton: true,
|
|
requires: ['Ext.data.SortTypes']
|
|
}, function() {
|
|
var st = Ext.data.SortTypes;
|
|
|
|
Ext.apply(Ext.data.Types, {
|
|
|
|
stripRe: /[\$,%]/g,
|
|
|
|
|
|
AUTO: {
|
|
convert: function(v) {
|
|
return v;
|
|
},
|
|
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) {
|
|
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) {
|
|
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 (this.useNull && (v === undefined || v === null || v === '')) {
|
|
return null;
|
|
}
|
|
return v === true || v === 'true' || v == 1;
|
|
},
|
|
sortType: st.none,
|
|
type: 'bool'
|
|
},
|
|
|
|
|
|
DATE: {
|
|
convert: function(v) {
|
|
var df = this.dateFormat,
|
|
parsed;
|
|
|
|
if (!v) {
|
|
return null;
|
|
}
|
|
if (Ext.isDate(v)) {
|
|
return v;
|
|
}
|
|
if (df) {
|
|
if (df == 'timestamp') {
|
|
return new Date(v*1000);
|
|
}
|
|
if (df == 'time') {
|
|
return new Date(parseInt(v, 10));
|
|
}
|
|
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', {
|
|
requires: ['Ext.data.Types', 'Ext.data.SortTypes'],
|
|
alias: 'data.field',
|
|
|
|
constructor : function(config) {
|
|
if (Ext.isString(config)) {
|
|
config = {name: config};
|
|
}
|
|
Ext.apply(this, config);
|
|
|
|
var types = Ext.data.Types,
|
|
st = this.sortType,
|
|
t;
|
|
|
|
if (this.type) {
|
|
if (Ext.isString(this.type)) {
|
|
this.type = types[this.type.toUpperCase()] || types.AUTO;
|
|
}
|
|
} else {
|
|
this.type = types.AUTO;
|
|
}
|
|
|
|
|
|
if (Ext.isString(st)) {
|
|
this.sortType = Ext.data.SortTypes[st];
|
|
} else if(Ext.isEmpty(st)) {
|
|
this.sortType = this.type.sortType;
|
|
}
|
|
|
|
if (!this.convert) {
|
|
this.convert = this.type.convert;
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dateFormat: null,
|
|
|
|
|
|
useNull: false,
|
|
|
|
|
|
defaultValue: "",
|
|
|
|
|
|
mapping: null,
|
|
|
|
|
|
sortType : null,
|
|
|
|
|
|
sortDir : "ASC",
|
|
|
|
|
|
allowBlank : true,
|
|
|
|
|
|
persist: true
|
|
});
|
|
|
|
|
|
Ext.define('Ext.util.AbstractMixedCollection', {
|
|
requires: ['Ext.util.Filter'],
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
constructor: function(allowFunctions, keyFn) {
|
|
var me = this;
|
|
|
|
me.items = [];
|
|
me.map = {};
|
|
me.keys = [];
|
|
me.length = 0;
|
|
|
|
me.addEvents(
|
|
|
|
'clear',
|
|
|
|
|
|
'add',
|
|
|
|
|
|
'replace',
|
|
|
|
|
|
'remove'
|
|
);
|
|
|
|
me.allowFunctions = allowFunctions === true;
|
|
|
|
if (keyFn) {
|
|
me.getKey = keyFn;
|
|
}
|
|
|
|
me.mixins.observable.constructor.call(me);
|
|
},
|
|
|
|
|
|
allowFunctions : false,
|
|
|
|
|
|
add : function(key, obj){
|
|
var me = this,
|
|
myObj = obj,
|
|
myKey = key,
|
|
old;
|
|
|
|
if (arguments.length == 1) {
|
|
myObj = myKey;
|
|
myKey = me.getKey(myObj);
|
|
}
|
|
if (typeof myKey != 'undefined' && myKey !== null) {
|
|
old = me.map[myKey];
|
|
if (typeof old != 'undefined') {
|
|
return me.replace(myKey, myObj);
|
|
}
|
|
me.map[myKey] = myObj;
|
|
}
|
|
me.length++;
|
|
me.items.push(myObj);
|
|
me.keys.push(myKey);
|
|
me.fireEvent('add', me.length - 1, myObj, myKey);
|
|
return myObj;
|
|
},
|
|
|
|
|
|
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);
|
|
}
|
|
index = me.indexOfKey(key);
|
|
me.items[index] = o;
|
|
me.map[key] = o;
|
|
me.fireEvent('replace', key, old, o);
|
|
return o;
|
|
},
|
|
|
|
|
|
addAll : function(objs){
|
|
var me = this,
|
|
i = 0,
|
|
args,
|
|
len,
|
|
key;
|
|
|
|
if (arguments.length > 1 || Ext.isArray(objs)) {
|
|
args = arguments.length > 1 ? arguments : objs;
|
|
for (len = args.length; i < len; i++) {
|
|
me.add(args[i]);
|
|
}
|
|
} 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 = [].concat(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 me = this,
|
|
myKey = key,
|
|
myObj = obj;
|
|
|
|
if (arguments.length == 2) {
|
|
myObj = myKey;
|
|
myKey = me.getKey(myObj);
|
|
}
|
|
if (me.containsKey(myKey)) {
|
|
me.suspendEvents();
|
|
me.removeAtKey(myKey);
|
|
me.resumeEvents();
|
|
}
|
|
if (index >= me.length) {
|
|
return me.add(myKey, myObj);
|
|
}
|
|
me.length++;
|
|
Ext.Array.splice(me.items, index, 0, myObj);
|
|
if (typeof myKey != 'undefined' && myKey !== null) {
|
|
me.map[myKey] = myObj;
|
|
}
|
|
Ext.Array.splice(me.keys, index, 0, myKey);
|
|
me.fireEvent('add', index, myObj, myKey);
|
|
return myObj;
|
|
},
|
|
|
|
|
|
remove : function(o){
|
|
return this.removeAt(this.indexOf(o));
|
|
},
|
|
|
|
|
|
removeAll : function(items){
|
|
Ext.each(items || [], function(item) {
|
|
this.remove(item);
|
|
}, this);
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
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);
|
|
me.fireEvent('remove', o, key);
|
|
return o;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
|
|
removeAtKey : function(key){
|
|
return this.removeAt(this.indexOfKey(key));
|
|
},
|
|
|
|
|
|
getCount : function(){
|
|
return this.length;
|
|
},
|
|
|
|
|
|
indexOf : function(o){
|
|
return Ext.Array.indexOf(this.items, o);
|
|
},
|
|
|
|
|
|
indexOfKey : function(key){
|
|
return Ext.Array.indexOf(this.keys, key);
|
|
},
|
|
|
|
|
|
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){
|
|
return Ext.Array.contains(this.items, o);
|
|
},
|
|
|
|
|
|
containsKey : function(key){
|
|
return typeof this.map[key] != 'undefined';
|
|
},
|
|
|
|
|
|
clear : function(){
|
|
var me = this;
|
|
|
|
me.length = 0;
|
|
me.items = [];
|
|
me.keys = [];
|
|
me.map = {};
|
|
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);
|
|
},
|
|
|
|
|
|
getRange : function(start, end){
|
|
var me = this,
|
|
items = me.items,
|
|
range = [],
|
|
i;
|
|
|
|
if (items.length < 1) {
|
|
return range;
|
|
}
|
|
|
|
start = start || 0;
|
|
end = Math.min(typeof end == 'undefined' ? me.length - 1 : end, me.length - 1);
|
|
if (start <= end) {
|
|
for (i = start; i <= end; i++) {
|
|
range[range.length] = items[i];
|
|
}
|
|
} else {
|
|
for (i = start; i >= end; i--) {
|
|
range[range.length] = items[i];
|
|
}
|
|
}
|
|
return range;
|
|
},
|
|
|
|
|
|
filter : function(property, value, anyMatch, caseSensitive) {
|
|
var filters = [],
|
|
filterFn;
|
|
|
|
|
|
if (Ext.isString(property)) {
|
|
filters.push(Ext.create('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);
|
|
}
|
|
|
|
|
|
|
|
filterFn = function(record) {
|
|
var isMatch = true,
|
|
length = filters.length,
|
|
i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
var filter = filters[i],
|
|
fn = filter.filterFn,
|
|
scope = filter.scope;
|
|
|
|
isMatch = isMatch && fn.call(scope, record);
|
|
}
|
|
|
|
return isMatch;
|
|
};
|
|
|
|
return this.filterBy(filterFn);
|
|
},
|
|
|
|
|
|
filterBy : function(fn, scope) {
|
|
var me = this,
|
|
newMC = new this.self(),
|
|
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]);
|
|
}
|
|
}
|
|
|
|
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 this.self(),
|
|
keys = me.keys,
|
|
items = me.items,
|
|
i = 0,
|
|
len = items.length;
|
|
|
|
for(; i < len; i++){
|
|
copy.add(keys[i], items[i]);
|
|
}
|
|
copy.getKey = me.getKey;
|
|
return copy;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define("Ext.util.Sortable", {
|
|
|
|
isSortable: true,
|
|
|
|
|
|
defaultSortDirection: "ASC",
|
|
|
|
requires: [
|
|
'Ext.util.Sorter'
|
|
],
|
|
|
|
|
|
|
|
|
|
initSortable: function() {
|
|
var me = this,
|
|
sorters = me.sorters;
|
|
|
|
|
|
me.sorters = Ext.create('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, sorterFn,
|
|
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') {
|
|
sorters = me.sorters.clone().items;
|
|
|
|
me.sorters.clear();
|
|
me.sorters.addAll(newSorters);
|
|
me.sorters.addAll(sorters);
|
|
}
|
|
else {
|
|
me.sorters.addAll(newSorters);
|
|
}
|
|
}
|
|
else {
|
|
me.sorters.clear();
|
|
me.sorters.addAll(newSorters);
|
|
}
|
|
}
|
|
|
|
if (doSort !== false) {
|
|
me.onBeforeSort(newSorters);
|
|
|
|
sorters = me.sorters.items;
|
|
if (sorters.length) {
|
|
|
|
sorterFn = function(r1, r2) {
|
|
var result = sorters[0].sort(r1, r2),
|
|
length = sorters.length,
|
|
i;
|
|
|
|
|
|
for (i = 1; i < length; i++) {
|
|
result = result || sorters[i].sort.call(this, r1, r2);
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
me.doSort(sorterFn);
|
|
}
|
|
}
|
|
|
|
return sorters;
|
|
},
|
|
|
|
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 : undefined;
|
|
}
|
|
sorters[i] = Ext.create('Ext.util.Sorter', config);
|
|
}
|
|
}
|
|
|
|
return sorters;
|
|
},
|
|
|
|
getSorters: function() {
|
|
return this.sorters.items;
|
|
}
|
|
});
|
|
|
|
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;
|
|
|
|
|
|
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){
|
|
var v = fn(a[property], b[property]) * dsc;
|
|
if(v === 0){
|
|
v = (a.index < b.index ? -1 : 1);
|
|
}
|
|
return v;
|
|
});
|
|
|
|
|
|
for(i = 0, len = c.length; i < len; i++){
|
|
items[i] = c[i].value;
|
|
keys[i] = c[i].key;
|
|
}
|
|
|
|
me.fireEvent('sort', me);
|
|
},
|
|
|
|
|
|
sortBy: function(sorterFn) {
|
|
var me = this,
|
|
items = me.items,
|
|
keys = me.keys,
|
|
length = items.length,
|
|
temp = [],
|
|
i;
|
|
|
|
|
|
for (i = 0; i < length; i++) {
|
|
temp[i] = {
|
|
key : keys[i],
|
|
value: items[i],
|
|
index: i
|
|
};
|
|
}
|
|
|
|
Ext.Array.sort(temp, function(a, b) {
|
|
var v = sorterFn(a.value, b.value);
|
|
if (v === 0) {
|
|
v = (a.index < b.index ? -1 : 1);
|
|
}
|
|
|
|
return v;
|
|
});
|
|
|
|
|
|
for (i = 0; i < length; i++) {
|
|
items[i] = temp[i].value;
|
|
keys[i] = temp[i].key;
|
|
}
|
|
|
|
me.fireEvent('sort', me, items, keys);
|
|
},
|
|
|
|
|
|
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.data.Errors', {
|
|
extend: 'Ext.util.MixedCollection',
|
|
|
|
|
|
isValid: function() {
|
|
return this.length === 0;
|
|
},
|
|
|
|
|
|
getByField: function(fieldName) {
|
|
var errors = [],
|
|
error, field, 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.reader.Reader', {
|
|
requires: ['Ext.data.ResultSet'],
|
|
alternateClassName: ['Ext.data.Reader', 'Ext.data.DataReader'],
|
|
|
|
|
|
|
|
|
|
totalProperty: 'total',
|
|
|
|
|
|
successProperty: 'success',
|
|
|
|
|
|
root: '',
|
|
|
|
|
|
|
|
|
|
implicitIncludes: true,
|
|
|
|
isReader: true,
|
|
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
Ext.apply(me, config || {});
|
|
me.fieldCount = 0;
|
|
me.model = Ext.ModelManager.getModel(config.model);
|
|
if (me.model) {
|
|
me.buildExtractors();
|
|
}
|
|
},
|
|
|
|
|
|
setModel: function(model, setOnProxy) {
|
|
var me = this;
|
|
|
|
me.model = Ext.ModelManager.getModel(model);
|
|
me.buildExtractors(true);
|
|
|
|
if (setOnProxy && me.proxy) {
|
|
me.proxy.setModel(me.model, true);
|
|
}
|
|
},
|
|
|
|
|
|
read: function(response) {
|
|
var data = response;
|
|
|
|
if (response && response.responseText) {
|
|
data = this.getResponseData(response);
|
|
}
|
|
|
|
if (data) {
|
|
return this.readRecords(data);
|
|
} else {
|
|
return this.nullResultSet;
|
|
}
|
|
},
|
|
|
|
|
|
readRecords: function(data) {
|
|
var me = this;
|
|
|
|
|
|
if (me.fieldCount !== me.getFields().length) {
|
|
me.buildExtractors(true);
|
|
}
|
|
|
|
|
|
me.rawData = data;
|
|
|
|
data = me.getData(data);
|
|
|
|
|
|
|
|
var root = Ext.isArray(data) ? data : me.getRoot(data),
|
|
success = true,
|
|
recordCount = 0,
|
|
total, value, records, message;
|
|
|
|
if (root) {
|
|
total = root.length;
|
|
}
|
|
|
|
if (me.totalProperty) {
|
|
value = parseInt(me.getTotal(data), 10);
|
|
if (!isNaN(value)) {
|
|
total = value;
|
|
}
|
|
}
|
|
|
|
if (me.successProperty) {
|
|
value = me.getSuccess(data);
|
|
if (value === false || value === 'false') {
|
|
success = false;
|
|
}
|
|
}
|
|
|
|
if (me.messageProperty) {
|
|
message = me.getMessage(data);
|
|
}
|
|
|
|
if (root) {
|
|
records = me.extractData(root);
|
|
recordCount = records.length;
|
|
} else {
|
|
recordCount = 0;
|
|
records = [];
|
|
}
|
|
|
|
return Ext.create('Ext.data.ResultSet', {
|
|
total : total || recordCount,
|
|
count : recordCount,
|
|
records: records,
|
|
success: success,
|
|
message: message
|
|
});
|
|
},
|
|
|
|
|
|
extractData : function(root) {
|
|
var me = this,
|
|
values = [],
|
|
records = [],
|
|
Model = me.model,
|
|
i = 0,
|
|
length = root.length,
|
|
idProp = me.getIdProperty(),
|
|
node, id, record;
|
|
|
|
if (!root.length && Ext.isObject(root)) {
|
|
root = [root];
|
|
length = 1;
|
|
}
|
|
|
|
for (; i < length; i++) {
|
|
node = root[i];
|
|
values = me.extractValues(node);
|
|
id = me.getId(node);
|
|
|
|
|
|
record = new Model(values, id, node);
|
|
records.push(record);
|
|
|
|
if (me.implicitIncludes) {
|
|
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.associationKey || association.name);
|
|
|
|
if (associationData) {
|
|
reader = association.getReader();
|
|
if (!reader) {
|
|
proxy = association.associatedModel.proxy;
|
|
|
|
if (proxy) {
|
|
reader = proxy.getReader();
|
|
} else {
|
|
reader = new this.constructor({
|
|
model: association.associatedName
|
|
});
|
|
}
|
|
}
|
|
association.read(record, reader, associationData);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getAssociatedDataRoot: function(data, associationName) {
|
|
return data[associationName];
|
|
},
|
|
|
|
getFields: function() {
|
|
return this.model.prototype.fields.items;
|
|
},
|
|
|
|
|
|
extractValues: function(data) {
|
|
var fields = this.getFields(),
|
|
i = 0,
|
|
length = fields.length,
|
|
output = {},
|
|
field, value;
|
|
|
|
for (; i < length; i++) {
|
|
field = fields[i];
|
|
value = this.extractorFunctions[i](data);
|
|
|
|
output[field.name] = value;
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
|
|
getData: function(data) {
|
|
return data;
|
|
},
|
|
|
|
|
|
getRoot: function(data) {
|
|
return data;
|
|
},
|
|
|
|
|
|
getResponseData: function(response) {
|
|
},
|
|
|
|
|
|
onMetaChange : function(meta) {
|
|
var fields = meta.fields,
|
|
newModel;
|
|
|
|
Ext.apply(this, meta);
|
|
|
|
if (fields) {
|
|
newModel = Ext.define("Ext.data.reader.Json-Model" + Ext.id(), {
|
|
extend: 'Ext.data.Model',
|
|
fields: fields
|
|
});
|
|
this.setModel(newModel, true);
|
|
} else {
|
|
this.buildExtractors(true);
|
|
}
|
|
},
|
|
|
|
|
|
getIdProperty: function(){
|
|
var prop = this.idProperty;
|
|
if (Ext.isEmpty(prop)) {
|
|
prop = this.model.prototype.idProperty;
|
|
}
|
|
return prop;
|
|
},
|
|
|
|
|
|
buildExtractors: function(force) {
|
|
var me = this,
|
|
idProp = me.getIdProperty(),
|
|
totalProp = me.totalProperty,
|
|
successProp = me.successProperty,
|
|
messageProp = me.messageProperty,
|
|
accessor;
|
|
|
|
if (force === true) {
|
|
delete me.extractorFunctions;
|
|
}
|
|
|
|
if (me.extractorFunctions) {
|
|
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.buildFieldExtractors();
|
|
},
|
|
|
|
|
|
buildFieldExtractors: function() {
|
|
|
|
var me = this,
|
|
fields = me.getFields(),
|
|
ln = fields.length,
|
|
i = 0,
|
|
extractorFunctions = [],
|
|
field, map;
|
|
|
|
for (; i < ln; i++) {
|
|
field = fields[i];
|
|
map = (field.mapping !== undefined && field.mapping !== null) ? field.mapping : field.name;
|
|
|
|
extractorFunctions.push(me.createAccessor(map));
|
|
}
|
|
me.fieldCount = ln;
|
|
|
|
me.extractorFunctions = extractorFunctions;
|
|
}
|
|
}, function() {
|
|
Ext.apply(this, {
|
|
|
|
nullResultSet: Ext.create('Ext.data.ResultSet', {
|
|
total : 0,
|
|
count : 0,
|
|
records: [],
|
|
success: true
|
|
})
|
|
});
|
|
});
|
|
|
|
Ext.define('Ext.data.reader.Json', {
|
|
extend: 'Ext.data.reader.Reader',
|
|
alternateClassName: 'Ext.data.JsonReader',
|
|
alias : 'reader.json',
|
|
|
|
root: '',
|
|
|
|
|
|
|
|
|
|
useSimpleAccessors: false,
|
|
|
|
|
|
readRecords: function(data) {
|
|
|
|
if (data.metaData) {
|
|
this.onMetaChange(data.metaData);
|
|
}
|
|
|
|
|
|
this.jsonData = data;
|
|
return this.callParent([data]);
|
|
},
|
|
|
|
|
|
getResponseData: function(response) {
|
|
var data;
|
|
try {
|
|
data = Ext.decode(response.responseText);
|
|
}
|
|
catch (ex) {
|
|
Ext.Error.raise({
|
|
response: response,
|
|
json: response.responseText,
|
|
parseError: ex,
|
|
msg: 'Unable to parse the JSON returned by the server: ' + ex.toString()
|
|
});
|
|
}
|
|
|
|
return data;
|
|
},
|
|
|
|
|
|
buildExtractors : function() {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (me.root) {
|
|
me.getRoot = me.createAccessor(me.root);
|
|
} else {
|
|
me.getRoot = function(root) {
|
|
return root;
|
|
};
|
|
}
|
|
},
|
|
|
|
|
|
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];
|
|
};
|
|
};
|
|
}()
|
|
});
|
|
|
|
Ext.define('Ext.data.writer.Json', {
|
|
extend: 'Ext.data.writer.Writer',
|
|
alternateClassName: 'Ext.data.JsonWriter',
|
|
alias: 'writer.json',
|
|
|
|
|
|
root: undefined,
|
|
|
|
|
|
encode: false,
|
|
|
|
|
|
allowSingle: true,
|
|
|
|
|
|
writeRecords: function(request, data) {
|
|
var root = this.root;
|
|
|
|
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'],
|
|
requires: [
|
|
'Ext.data.reader.Json',
|
|
'Ext.data.writer.Json'
|
|
],
|
|
uses: [
|
|
'Ext.data.Batch',
|
|
'Ext.data.Operation',
|
|
'Ext.data.Model'
|
|
],
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
|
|
batchOrder: 'create,update,destroy',
|
|
|
|
|
|
batchActions: true,
|
|
|
|
|
|
defaultReaderType: 'json',
|
|
|
|
|
|
defaultWriterType: 'json',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isProxy: true,
|
|
|
|
|
|
constructor: function(config) {
|
|
config = config || {};
|
|
|
|
if (config.model === undefined) {
|
|
delete config.model;
|
|
}
|
|
|
|
this.mixins.observable.constructor.call(this, config);
|
|
|
|
if (this.model !== undefined && !(this.model instanceof Ext.data.Model)) {
|
|
this.setModel(this.model);
|
|
}
|
|
},
|
|
|
|
|
|
setModel: function(model, setOnStore) {
|
|
this.model = Ext.ModelManager.getModel(model);
|
|
|
|
var reader = this.reader,
|
|
writer = this.writer;
|
|
|
|
this.setReader(reader);
|
|
this.setWriter(writer);
|
|
|
|
if (setOnStore && this.store) {
|
|
this.store.setModel(this.model);
|
|
}
|
|
},
|
|
|
|
|
|
getModel: function() {
|
|
return this.model;
|
|
},
|
|
|
|
|
|
setReader: function(reader) {
|
|
var me = this;
|
|
|
|
if (reader === undefined || typeof reader == 'string') {
|
|
reader = {
|
|
type: reader
|
|
};
|
|
}
|
|
|
|
if (reader.isReader) {
|
|
reader.setModel(me.model);
|
|
} else {
|
|
Ext.applyIf(reader, {
|
|
proxy: me,
|
|
model: me.model,
|
|
type : me.defaultReaderType
|
|
});
|
|
|
|
reader = Ext.createByAlias('reader.' + reader.type, reader);
|
|
}
|
|
|
|
me.reader = reader;
|
|
return me.reader;
|
|
},
|
|
|
|
|
|
getReader: function() {
|
|
return this.reader;
|
|
},
|
|
|
|
|
|
setWriter: function(writer) {
|
|
if (writer === undefined || typeof writer == 'string') {
|
|
writer = {
|
|
type: writer
|
|
};
|
|
}
|
|
|
|
if (!(writer instanceof Ext.data.writer.Writer)) {
|
|
Ext.applyIf(writer, {
|
|
model: this.model,
|
|
type : this.defaultWriterType
|
|
});
|
|
|
|
writer = Ext.createByAlias('writer.' + writer.type, writer);
|
|
}
|
|
|
|
this.writer = writer;
|
|
|
|
return this.writer;
|
|
},
|
|
|
|
|
|
getWriter: function() {
|
|
return this.writer;
|
|
},
|
|
|
|
|
|
create: Ext.emptyFn,
|
|
|
|
|
|
read: Ext.emptyFn,
|
|
|
|
|
|
update: Ext.emptyFn,
|
|
|
|
|
|
destroy: Ext.emptyFn,
|
|
|
|
|
|
batch: function(operations, listeners) {
|
|
var me = this,
|
|
batch = Ext.create('Ext.data.Batch', {
|
|
proxy: me,
|
|
listeners: listeners || {}
|
|
}),
|
|
useBatch = me.batchActions,
|
|
records;
|
|
|
|
Ext.each(me.batchOrder.split(','), function(action) {
|
|
records = operations[action];
|
|
if (records) {
|
|
if (useBatch) {
|
|
batch.add(Ext.create('Ext.data.Operation', {
|
|
action: action,
|
|
records: records
|
|
}));
|
|
} else {
|
|
Ext.each(records, function(record){
|
|
batch.add(Ext.create('Ext.data.Operation', {
|
|
action : action,
|
|
records: [record]
|
|
}));
|
|
});
|
|
}
|
|
}
|
|
}, me);
|
|
|
|
batch.start();
|
|
return batch;
|
|
}
|
|
}, function() {
|
|
|
|
|
|
|
|
Ext.data.DataProxy = this;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.data.proxy.Server', {
|
|
extend: 'Ext.data.proxy.Proxy',
|
|
alias : 'proxy.server',
|
|
alternateClassName: 'Ext.data.ServerProxy',
|
|
uses : ['Ext.data.Request'],
|
|
|
|
|
|
|
|
|
|
pageParam: 'page',
|
|
|
|
|
|
startParam: 'start',
|
|
|
|
|
|
limitParam: 'limit',
|
|
|
|
|
|
groupParam: 'group',
|
|
|
|
|
|
sortParam: 'sort',
|
|
|
|
|
|
filterParam: 'filter',
|
|
|
|
|
|
directionParam: 'dir',
|
|
|
|
|
|
simpleSortMode: false,
|
|
|
|
|
|
noCache : true,
|
|
|
|
|
|
cacheString: "_dc",
|
|
|
|
|
|
timeout : 30000,
|
|
|
|
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
config = config || {};
|
|
this.addEvents(
|
|
|
|
'exception'
|
|
);
|
|
me.callParent([config]);
|
|
|
|
|
|
me.extraParams = config.extraParams || {};
|
|
|
|
me.api = config.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);
|
|
},
|
|
|
|
|
|
buildRequest: function(operation) {
|
|
var params = Ext.applyIf(operation.params || {}, this.extraParams || {}),
|
|
request;
|
|
|
|
|
|
params = Ext.applyIf(params, this.getParams(operation));
|
|
|
|
if (operation.id && !params.id) {
|
|
params.id = operation.id;
|
|
}
|
|
|
|
request = Ext.create('Ext.data.Request', {
|
|
params : params,
|
|
action : operation.action,
|
|
records : operation.records,
|
|
operation: operation,
|
|
url : operation.url
|
|
});
|
|
|
|
request.url = this.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();
|
|
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: function(response){
|
|
return response;
|
|
},
|
|
|
|
|
|
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,
|
|
|
|
pageParam = me.pageParam,
|
|
startParam = me.startParam,
|
|
limitParam = me.limitParam,
|
|
groupParam = me.groupParam,
|
|
sortParam = me.sortParam,
|
|
filterParam = me.filterParam,
|
|
directionParam = me.directionParam;
|
|
|
|
if (pageParam && isDef(page)) {
|
|
params[pageParam] = page;
|
|
}
|
|
|
|
if (startParam && isDef(start)) {
|
|
params[startParam] = start;
|
|
}
|
|
|
|
if (limitParam && isDef(limit)) {
|
|
params[limitParam] = limit;
|
|
}
|
|
|
|
if (groupParam && groupers && groupers.length > 0) {
|
|
|
|
params[groupParam] = me.encodeSorters(groupers);
|
|
}
|
|
|
|
if (sortParam && sorters && sorters.length > 0) {
|
|
if (simpleSortMode) {
|
|
params[sortParam] = sorters[0].property;
|
|
params[directionParam] = sorters[0].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', {
|
|
requires: ['Ext.util.MixedCollection', 'Ext.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'
|
|
},
|
|
|
|
|
|
|
|
|
|
doRequest: function(operation, callback, scope) {
|
|
var writer = this.getWriter(),
|
|
request = this.buildRequest(operation, callback, scope);
|
|
|
|
if (operation.allowWrite()) {
|
|
request = writer.write(request);
|
|
}
|
|
|
|
Ext.apply(request, {
|
|
headers : this.headers,
|
|
timeout : this.timeout,
|
|
scope : this,
|
|
callback : this.createRequestCallback(request, operation, callback, scope),
|
|
method : this.getMethod(request),
|
|
disableCaching: false
|
|
});
|
|
|
|
Ext.Ajax.request(request);
|
|
|
|
return request;
|
|
},
|
|
|
|
|
|
getMethod: function(request) {
|
|
return this.actionMethods[request.action];
|
|
},
|
|
|
|
|
|
createRequestCallback: function(request, operation, callback, scope) {
|
|
var me = this;
|
|
|
|
return function(options, success, response) {
|
|
me.processResponse(success, operation, request, response, callback, scope);
|
|
};
|
|
}
|
|
}, function() {
|
|
|
|
Ext.data.HttpProxy = this;
|
|
});
|
|
|
|
|
|
Ext.define('Ext.data.Model', {
|
|
alternateClassName: 'Ext.data.Record',
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
requires: [
|
|
'Ext.ModelManager',
|
|
'Ext.data.IdGenerator',
|
|
'Ext.data.Field',
|
|
'Ext.data.Errors',
|
|
'Ext.data.Operation',
|
|
'Ext.data.validations',
|
|
'Ext.data.proxy.Ajax',
|
|
'Ext.util.MixedCollection'
|
|
],
|
|
|
|
onClassExtended: function(cls, data) {
|
|
var onBeforeClassCreated = data.onBeforeClassCreated;
|
|
|
|
data.onBeforeClassCreated = function(cls, data) {
|
|
var me = this,
|
|
name = Ext.getClassName(cls),
|
|
prototype = cls.prototype,
|
|
superCls = cls.prototype.superclass,
|
|
|
|
validations = data.validations || [],
|
|
fields = data.fields || [],
|
|
associations = data.associations || [],
|
|
belongsTo = data.belongsTo,
|
|
hasMany = data.hasMany,
|
|
idgen = data.idgen,
|
|
|
|
fieldsMixedCollection = new Ext.util.MixedCollection(false, function(field) {
|
|
return field.name;
|
|
}),
|
|
|
|
associationsMixedCollection = new Ext.util.MixedCollection(false, function(association) {
|
|
return association.name;
|
|
}),
|
|
|
|
superValidations = superCls.validations,
|
|
superFields = superCls.fields,
|
|
superAssociations = superCls.associations,
|
|
|
|
association, i, ln,
|
|
dependencies = [];
|
|
|
|
|
|
cls.modelName = name;
|
|
prototype.modelName = name;
|
|
|
|
|
|
if (superValidations) {
|
|
validations = superValidations.concat(validations);
|
|
}
|
|
|
|
data.validations = validations;
|
|
|
|
|
|
if (superFields) {
|
|
fields = superFields.items.concat(fields);
|
|
}
|
|
|
|
for (i = 0, ln = fields.length; i < ln; ++i) {
|
|
fieldsMixedCollection.add(new Ext.data.Field(fields[i]));
|
|
}
|
|
|
|
data.fields = fieldsMixedCollection;
|
|
|
|
if (idgen) {
|
|
data.idgen = Ext.data.IdGenerator.get(idgen);
|
|
}
|
|
|
|
|
|
|
|
if (belongsTo) {
|
|
belongsTo = Ext.Array.from(belongsTo);
|
|
|
|
for (i = 0, ln = belongsTo.length; i < ln; ++i) {
|
|
association = belongsTo[i];
|
|
|
|
if (!Ext.isObject(association)) {
|
|
association = {model: association};
|
|
}
|
|
|
|
association.type = 'belongsTo';
|
|
associations.push(association);
|
|
}
|
|
|
|
delete data.belongsTo;
|
|
}
|
|
|
|
if (hasMany) {
|
|
hasMany = Ext.Array.from(hasMany);
|
|
for (i = 0, ln = hasMany.length; i < ln; ++i) {
|
|
association = hasMany[i];
|
|
|
|
if (!Ext.isObject(association)) {
|
|
association = {model: association};
|
|
}
|
|
|
|
association.type = 'hasMany';
|
|
associations.push(association);
|
|
}
|
|
|
|
delete data.hasMany;
|
|
}
|
|
|
|
if (superAssociations) {
|
|
associations = superAssociations.items.concat(associations);
|
|
}
|
|
|
|
for (i = 0, ln = associations.length; i < ln; ++i) {
|
|
dependencies.push('association.' + associations[i].type.toLowerCase());
|
|
}
|
|
|
|
if (data.proxy) {
|
|
if (typeof data.proxy === 'string') {
|
|
dependencies.push('proxy.' + data.proxy);
|
|
}
|
|
else if (typeof data.proxy.type === 'string') {
|
|
dependencies.push('proxy.' + data.proxy.type);
|
|
}
|
|
}
|
|
|
|
Ext.require(dependencies, function() {
|
|
Ext.ModelManager.registerType(name, cls);
|
|
|
|
for (i = 0, ln = associations.length; i < ln; ++i) {
|
|
association = associations[i];
|
|
|
|
Ext.apply(association, {
|
|
ownerModel: name,
|
|
associatedModel: association.model
|
|
});
|
|
|
|
if (Ext.ModelManager.getModel(association.model) === undefined) {
|
|
Ext.ModelManager.registerDeferredAssociation(association);
|
|
} else {
|
|
associationsMixedCollection.add(Ext.data.Association.create(association));
|
|
}
|
|
}
|
|
|
|
data.associations = associationsMixedCollection;
|
|
|
|
onBeforeClassCreated.call(me, cls, data);
|
|
|
|
cls.setProxy(cls.prototype.proxy || cls.prototype.defaultProxyType);
|
|
|
|
|
|
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() {
|
|
return this.proxy;
|
|
},
|
|
|
|
|
|
load: function(id, config) {
|
|
config = Ext.apply({}, config);
|
|
config = Ext.applyIf(config, {
|
|
action: 'read',
|
|
id : id
|
|
});
|
|
|
|
var operation = Ext.create('Ext.data.Operation', config),
|
|
scope = config.scope || this,
|
|
record = null,
|
|
callback;
|
|
|
|
callback = function(operation) {
|
|
if (operation.wasSuccessful()) {
|
|
record = operation.getRecords()[0];
|
|
Ext.callback(config.success, scope, [record, operation]);
|
|
} else {
|
|
Ext.callback(config.failure, scope, [record, operation]);
|
|
}
|
|
Ext.callback(config.callback, scope, [record, operation]);
|
|
};
|
|
|
|
this.proxy.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',
|
|
|
|
|
|
defaultProxyType: 'ajax',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor: function(data, id, raw) {
|
|
data = data || {};
|
|
|
|
var me = this,
|
|
fields,
|
|
length,
|
|
field,
|
|
name,
|
|
i,
|
|
newId,
|
|
isArray = Ext.isArray(data),
|
|
newData = isArray ? {} : null;
|
|
|
|
|
|
me.internalId = (id || id === 0) ? id : Ext.data.Model.id(me);
|
|
|
|
|
|
me.raw = raw;
|
|
|
|
Ext.applyIf(me, {
|
|
data: {}
|
|
});
|
|
|
|
|
|
me.modified = {};
|
|
|
|
|
|
if (me.persistanceProperty) {
|
|
me.persistenceProperty = me.persistanceProperty;
|
|
}
|
|
me[me.persistenceProperty] = {};
|
|
|
|
me.mixins.observable.constructor.call(me);
|
|
|
|
|
|
fields = me.fields.items;
|
|
length = fields.length;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
field = fields[i];
|
|
name = field.name;
|
|
|
|
if (isArray){
|
|
|
|
|
|
newData[name] = data[i];
|
|
}
|
|
else if (data[name] === undefined) {
|
|
data[name] = field.defaultValue;
|
|
}
|
|
}
|
|
|
|
me.set(newData || data);
|
|
|
|
if (me.getId()) {
|
|
me.phantom = false;
|
|
} else if (me.phantom) {
|
|
newId = me.idgen.generate();
|
|
if (newId !== null) {
|
|
me.setId(newId);
|
|
}
|
|
}
|
|
|
|
|
|
me.dirty = false;
|
|
me.modified = {};
|
|
|
|
if (typeof me.init == 'function') {
|
|
me.init();
|
|
}
|
|
|
|
me.id = me.idgen.getRecId(me);
|
|
},
|
|
|
|
|
|
get: function(field) {
|
|
return this[this.persistenceProperty][field];
|
|
},
|
|
|
|
|
|
set: function(fieldName, value) {
|
|
var me = this,
|
|
fields = me.fields,
|
|
modified = me.modified,
|
|
convertFields = [],
|
|
field, key, i, currentValue, notEditing, count, length;
|
|
|
|
|
|
if (arguments.length == 1 && Ext.isObject(fieldName)) {
|
|
notEditing = !me.editing;
|
|
count = 0;
|
|
for (key in fieldName) {
|
|
if (fieldName.hasOwnProperty(key)) {
|
|
|
|
|
|
|
|
field = fields.get(key);
|
|
if (field && field.convert !== field.type.convert) {
|
|
convertFields.push(key);
|
|
continue;
|
|
}
|
|
|
|
if (!count && notEditing) {
|
|
me.beginEdit();
|
|
}
|
|
++count;
|
|
me.set(key, fieldName[key]);
|
|
}
|
|
}
|
|
|
|
length = convertFields.length;
|
|
if (length) {
|
|
if (!count && notEditing) {
|
|
me.beginEdit();
|
|
}
|
|
count += length;
|
|
for (i = 0; i < length; i++) {
|
|
field = convertFields[i];
|
|
me.set(field, fieldName[field]);
|
|
}
|
|
}
|
|
|
|
if (notEditing && count) {
|
|
me.endEdit();
|
|
}
|
|
} else {
|
|
if (fields) {
|
|
field = fields.get(fieldName);
|
|
|
|
if (field && field.convert) {
|
|
value = field.convert(value, me);
|
|
}
|
|
}
|
|
currentValue = me.get(fieldName);
|
|
me[me.persistenceProperty][fieldName] = value;
|
|
|
|
if (field && field.persist && !me.isEqual(currentValue, value)) {
|
|
if (me.isModified(fieldName)) {
|
|
if (me.isEqual(modified[fieldName], value)) {
|
|
|
|
|
|
delete modified[fieldName];
|
|
|
|
|
|
me.dirty = false;
|
|
for (key in modified) {
|
|
if (modified.hasOwnProperty(key)){
|
|
me.dirty = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
me.dirty = true;
|
|
modified[fieldName] = currentValue;
|
|
}
|
|
}
|
|
|
|
if (!me.editing) {
|
|
me.afterEdit();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
isEqual: function(a, b){
|
|
if (Ext.isDate(a) && Ext.isDate(b)) {
|
|
return a.getTime() === b.getTime();
|
|
}
|
|
return a === b;
|
|
},
|
|
|
|
|
|
beginEdit : function(){
|
|
var me = this;
|
|
if (!me.editing) {
|
|
me.editing = true;
|
|
me.dirtySave = me.dirty;
|
|
me.dataSave = Ext.apply({}, me[me.persistenceProperty]);
|
|
me.modifiedSave = Ext.apply({}, me.modified);
|
|
}
|
|
},
|
|
|
|
|
|
cancelEdit : function(){
|
|
var me = this;
|
|
if (me.editing) {
|
|
me.editing = false;
|
|
|
|
me.modified = me.modifiedSave;
|
|
me[me.persistenceProperty] = me.dataSave;
|
|
me.dirty = me.dirtySave;
|
|
delete me.modifiedSave;
|
|
delete me.dataSave;
|
|
delete me.dirtySave;
|
|
}
|
|
},
|
|
|
|
|
|
endEdit : function(silent){
|
|
var me = this,
|
|
didChange;
|
|
|
|
if (me.editing) {
|
|
me.editing = false;
|
|
didChange = me.dirty || me.changedWhileEditing();
|
|
delete me.modifiedSave;
|
|
delete me.dataSave;
|
|
delete me.dirtySave;
|
|
if (silent !== true && didChange) {
|
|
me.afterEdit();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
changedWhileEditing: function(){
|
|
var me = this,
|
|
saved = me.dataSave,
|
|
data = me[me.persistenceProperty],
|
|
key;
|
|
|
|
for (key in data) {
|
|
if (data.hasOwnProperty(key)) {
|
|
if (!me.isEqual(data[key], saved[key])) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
|
|
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,
|
|
name;
|
|
|
|
me.dirty = true;
|
|
|
|
me.fields.each(function(field) {
|
|
if (field.persist) {
|
|
name = field.name;
|
|
me.modified[name] = me.get(name);
|
|
}
|
|
}, me);
|
|
},
|
|
|
|
|
|
|
|
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) {
|
|
var me = this;
|
|
|
|
me.phantom = me.dirty = me.editing = false;
|
|
me.modified = {};
|
|
|
|
if (silent !== true) {
|
|
me.afterCommit();
|
|
}
|
|
},
|
|
|
|
|
|
copy : function(newId) {
|
|
var me = this;
|
|
|
|
return new me.self(Ext.apply({}, me[me.persistenceProperty]), newId || me.internalId);
|
|
},
|
|
|
|
|
|
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.proxy;
|
|
},
|
|
|
|
|
|
validate: function() {
|
|
var errors = Ext.create('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',
|
|
record = null,
|
|
scope = options.scope || me,
|
|
operation,
|
|
callback;
|
|
|
|
Ext.apply(options, {
|
|
records: [me],
|
|
action : action
|
|
});
|
|
|
|
operation = Ext.create('Ext.data.Operation', options);
|
|
|
|
callback = function(operation) {
|
|
if (operation.wasSuccessful()) {
|
|
record = operation.getRecords()[0];
|
|
|
|
|
|
me.set(record.data);
|
|
record.dirty = false;
|
|
|
|
Ext.callback(options.success, scope, [record, operation]);
|
|
} else {
|
|
Ext.callback(options.failure, scope, [record, operation]);
|
|
}
|
|
|
|
Ext.callback(options.callback, scope, [record, operation]);
|
|
};
|
|
|
|
me.getProxy()[action](operation, callback, me);
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
destroy: function(options){
|
|
options = Ext.apply({}, options);
|
|
|
|
var me = this,
|
|
record = null,
|
|
scope = options.scope || me,
|
|
operation,
|
|
callback;
|
|
|
|
Ext.apply(options, {
|
|
records: [me],
|
|
action : 'destroy'
|
|
});
|
|
|
|
operation = Ext.create('Ext.data.Operation', options);
|
|
callback = function(operation) {
|
|
if (operation.wasSuccessful()) {
|
|
Ext.callback(options.success, scope, [record, operation]);
|
|
} else {
|
|
Ext.callback(options.failure, scope, [record, operation]);
|
|
}
|
|
Ext.callback(options.callback, scope, [record, operation]);
|
|
};
|
|
|
|
me.getProxy().destroy(operation, callback, me);
|
|
return me;
|
|
},
|
|
|
|
|
|
getId: function() {
|
|
return this.get(this.idProperty);
|
|
},
|
|
|
|
|
|
setId: function(id) {
|
|
this.set(this.idProperty, id);
|
|
},
|
|
|
|
|
|
join : function(store) {
|
|
|
|
this.store = store;
|
|
},
|
|
|
|
|
|
unjoin: function(store) {
|
|
delete this.store;
|
|
},
|
|
|
|
|
|
afterEdit : function() {
|
|
this.callStore('afterEdit');
|
|
},
|
|
|
|
|
|
afterReject : function() {
|
|
this.callStore("afterReject");
|
|
},
|
|
|
|
|
|
afterCommit: function() {
|
|
this.callStore('afterCommit');
|
|
},
|
|
|
|
|
|
callStore: function(fn) {
|
|
var store = this.store;
|
|
|
|
if (store !== undefined && typeof store[fn] == "function") {
|
|
store[fn](this);
|
|
}
|
|
},
|
|
|
|
|
|
getAssociatedData: function(){
|
|
return this.prepareAssociatedData(this, [], null);
|
|
},
|
|
|
|
|
|
prepareAssociatedData: function(record, ids, associationType) {
|
|
|
|
var associations = record.associations.items,
|
|
associationCount = associations.length,
|
|
associationData = {},
|
|
associatedStore, associatedName, associatedRecords, associatedRecord,
|
|
associatedRecordCount, association, id, i, j, type, allow;
|
|
|
|
for (i = 0; i < associationCount; i++) {
|
|
association = associations[i];
|
|
type = association.type;
|
|
allow = true;
|
|
if (associationType) {
|
|
allow = type == associationType;
|
|
}
|
|
if (allow && type == 'hasMany') {
|
|
|
|
|
|
associatedStore = record[association.storeName];
|
|
|
|
|
|
associationData[association.name] = [];
|
|
|
|
|
|
if (associatedStore && associatedStore.data.length > 0) {
|
|
associatedRecords = associatedStore.data.items;
|
|
associatedRecordCount = associatedRecords.length;
|
|
|
|
|
|
for (j = 0; j < associatedRecordCount; j++) {
|
|
associatedRecord = associatedRecords[j];
|
|
|
|
id = associatedRecord.id;
|
|
|
|
|
|
|
|
if (Ext.Array.indexOf(ids, id) == -1) {
|
|
ids.push(id);
|
|
|
|
associationData[association.name][j] = associatedRecord.data;
|
|
Ext.apply(associationData[association.name][j], this.prepareAssociatedData(associatedRecord, ids, type));
|
|
}
|
|
}
|
|
}
|
|
} else if (allow && type == 'belongsTo') {
|
|
associatedRecord = record[association.instanceName];
|
|
if (associatedRecord !== undefined) {
|
|
id = associatedRecord.id;
|
|
if (Ext.Array.indexOf(ids, id) == -1) {
|
|
ids.push(id);
|
|
associationData[association.name] = associatedRecord.data;
|
|
Ext.apply(associationData[association.name], this.prepareAssociatedData(associatedRecord, ids, type));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return associationData;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.data.StoreManager', {
|
|
extend: 'Ext.util.MixedCollection',
|
|
alternateClassName: ['Ext.StoreMgr', 'Ext.data.StoreMgr', 'Ext.StoreManager'],
|
|
singleton: true,
|
|
uses: ['Ext.data.ArrayStore'],
|
|
|
|
|
|
|
|
|
|
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 Ext.create('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 = Ext.create('Ext.data.Store', config);
|
|
}
|
|
|
|
return Ext.data.StoreManager.register(store);
|
|
};
|
|
|
|
|
|
Ext.getStore = function(name) {
|
|
return Ext.data.StoreManager.lookup(name);
|
|
};
|
|
});
|
|
|
|
|
|
Ext.define('Ext.Component', {
|
|
|
|
|
|
|
|
alias: ['widget.component', 'widget.box'],
|
|
|
|
extend: 'Ext.AbstractComponent',
|
|
|
|
requires: [
|
|
'Ext.util.DelayedTask'
|
|
],
|
|
|
|
uses: [
|
|
'Ext.Layer',
|
|
'Ext.resizer.Resizer',
|
|
'Ext.util.ComponentDragger'
|
|
],
|
|
|
|
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,
|
|
|
|
|
|
toFrontOnShow: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hideMode: 'display',
|
|
|
|
hideParent: false,
|
|
|
|
ariaRole: 'presentation',
|
|
|
|
bubbleEvents: [],
|
|
|
|
actionMode: 'el',
|
|
monPropRe: /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
delete me.listeners;
|
|
}
|
|
me.enableBubble(me.bubbleEvents);
|
|
me.mons = [];
|
|
},
|
|
|
|
|
|
afterRender: function() {
|
|
var me = this,
|
|
resizable = me.resizable;
|
|
|
|
if (me.floating) {
|
|
me.makeFloating(me.floating);
|
|
} else {
|
|
me.el.setVisibilityMode(Ext.Element[me.hideMode.toUpperCase()]);
|
|
}
|
|
|
|
if (Ext.isDefined(me.autoScroll)) {
|
|
me.setAutoScroll(me.autoScroll);
|
|
}
|
|
me.callParent();
|
|
|
|
if (!(me.x && me.y) && (me.pageX || me.pageY)) {
|
|
me.setPagePosition(me.pageX, me.pageY);
|
|
}
|
|
|
|
if (resizable) {
|
|
me.initResizable(resizable);
|
|
}
|
|
|
|
if (me.draggable) {
|
|
me.initDraggable();
|
|
}
|
|
|
|
me.initAria();
|
|
},
|
|
|
|
initAria: function() {
|
|
var actionEl = this.getActionEl(),
|
|
role = this.ariaRole;
|
|
if (role) {
|
|
actionEl.dom.setAttribute('role', role);
|
|
}
|
|
},
|
|
|
|
|
|
setAutoScroll : function(scroll){
|
|
var me = this,
|
|
targetEl;
|
|
scroll = !!scroll;
|
|
if (me.rendered) {
|
|
targetEl = me.getTargetEl();
|
|
targetEl.setStyle('overflow', scroll ? 'auto' : '');
|
|
if (scroll && (Ext.isIE6 || Ext.isIE7)) {
|
|
|
|
|
|
targetEl.position();
|
|
}
|
|
}
|
|
me.autoScroll = scroll;
|
|
return me;
|
|
},
|
|
|
|
|
|
makeFloating : function(cfg){
|
|
this.mixins.floating.constructor.call(this, cfg);
|
|
},
|
|
|
|
initResizable: function(resizable) {
|
|
var me = this;
|
|
|
|
resizable = Ext.apply({
|
|
target: me,
|
|
dynamic: false,
|
|
constrainTo: me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.el.getScopeParent()),
|
|
handles: me.resizeHandles
|
|
}, resizable);
|
|
resizable.target = me;
|
|
me.resizer = Ext.create('Ext.resizer.Resizer', resizable);
|
|
},
|
|
|
|
getDragEl: function() {
|
|
return this.el;
|
|
},
|
|
|
|
initDraggable: function() {
|
|
var me = this,
|
|
ddConfig = Ext.applyIf({
|
|
el: me.getDragEl(),
|
|
constrainTo: me.constrain ? (me.constrainTo || (me.floatParent ? me.floatParent.getTargetEl() : me.el.getScopeParent())) : undefined
|
|
}, me.draggable);
|
|
|
|
|
|
if (me.constrain || me.constrainDelegate) {
|
|
ddConfig.constrain = me.constrain;
|
|
ddConfig.constrainDelegate = me.constrainDelegate;
|
|
}
|
|
|
|
me.dd = Ext.create('Ext.util.ComponentDragger', me, ddConfig);
|
|
},
|
|
|
|
|
|
setPosition: function(x, y, animate) {
|
|
var me = this,
|
|
el = me.el,
|
|
to = {},
|
|
adj, adjX, adjY, xIsNumber, yIsNumber;
|
|
|
|
if (Ext.isArray(x)) {
|
|
animate = y;
|
|
y = x[1];
|
|
x = x[0];
|
|
}
|
|
me.x = x;
|
|
me.y = y;
|
|
|
|
if (!me.rendered) {
|
|
return me;
|
|
}
|
|
|
|
adj = me.adjustPosition(x, y);
|
|
adjX = adj.x;
|
|
adjY = adj.y;
|
|
xIsNumber = Ext.isNumber(adjX);
|
|
yIsNumber = Ext.isNumber(adjY);
|
|
|
|
if (xIsNumber || yIsNumber) {
|
|
if (animate) {
|
|
if (xIsNumber) {
|
|
to.left = adjX;
|
|
}
|
|
if (yIsNumber) {
|
|
to.top = adjY;
|
|
}
|
|
|
|
me.stopAnimation();
|
|
me.animate(Ext.apply({
|
|
duration: 1000,
|
|
listeners: {
|
|
afteranimate: Ext.Function.bind(me.afterSetPosition, me, [adjX, adjY])
|
|
},
|
|
to: to
|
|
}, animate));
|
|
}
|
|
else {
|
|
if (!xIsNumber) {
|
|
el.setTop(adjY);
|
|
}
|
|
else if (!yIsNumber) {
|
|
el.setLeft(adjX);
|
|
}
|
|
else {
|
|
el.setLeftTop(adjX, adjY);
|
|
}
|
|
me.afterSetPosition(adjX, adjY);
|
|
}
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
afterSetPosition: function(ax, ay) {
|
|
this.onPosition(ax, ay);
|
|
this.fireEvent('move', this, ax, ay);
|
|
},
|
|
|
|
|
|
showAt: function(x, y, animate) {
|
|
var me = this;
|
|
|
|
if (me.floating) {
|
|
me.setPosition(x, y, animate);
|
|
} else {
|
|
me.setPagePosition(x, y, animate);
|
|
}
|
|
me.show();
|
|
},
|
|
|
|
|
|
setPagePosition: function(x, y, animate) {
|
|
var me = this,
|
|
p;
|
|
|
|
if (Ext.isArray(x)) {
|
|
y = x[1];
|
|
x = x[0];
|
|
}
|
|
me.pageX = x;
|
|
me.pageY = y;
|
|
if (me.floating && me.floatParent) {
|
|
|
|
p = me.floatParent.getTargetEl().getViewRegion();
|
|
if (Ext.isNumber(x) && Ext.isNumber(p.left)) {
|
|
x -= p.left;
|
|
}
|
|
if (Ext.isNumber(y) && Ext.isNumber(p.top)) {
|
|
y -= p.top;
|
|
}
|
|
me.setPosition(x, y, animate);
|
|
}
|
|
else {
|
|
p = me.el.translatePoints(x, y);
|
|
me.setPosition(p.left, p.top, animate);
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
getBox : function(local){
|
|
var pos = this.getPosition(local),
|
|
size = this.getSize();
|
|
|
|
size.x = pos[0];
|
|
size.y = pos[1];
|
|
return size;
|
|
},
|
|
|
|
|
|
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) {
|
|
|
|
|
|
if (this.floating && this.floatParent) {
|
|
var o = this.floatParent.getTargetEl().getViewRegion();
|
|
x += o.left;
|
|
y += o.top;
|
|
}
|
|
|
|
return {
|
|
x: x,
|
|
y: y
|
|
};
|
|
},
|
|
|
|
|
|
getPosition: function(local) {
|
|
var me = this,
|
|
el = me.el,
|
|
xy,
|
|
o;
|
|
|
|
|
|
if ((local === true) || (me.floating && !me.floatParent)) {
|
|
return [el.getLeft(true), el.getTop(true)];
|
|
}
|
|
xy = me.xy || el.getXY();
|
|
|
|
|
|
if (me.floating) {
|
|
o = me.floatParent.getTargetEl().getViewRegion();
|
|
xy[0] -= o.left;
|
|
xy[1] -= o.top;
|
|
}
|
|
return xy;
|
|
},
|
|
|
|
getId: function() {
|
|
var me = this,
|
|
xtype;
|
|
|
|
if (!me.id) {
|
|
xtype = me.getXType();
|
|
xtype = xtype ? xtype.replace(Ext.Component.INVALID_ID_CHARS_Re, '-') : 'ext-comp';
|
|
me.id = xtype + '-' + me.getAutoId();
|
|
}
|
|
return me.id;
|
|
},
|
|
|
|
onEnable: function() {
|
|
var actionEl = this.getActionEl();
|
|
actionEl.dom.removeAttribute('aria-disabled');
|
|
actionEl.dom.disabled = false;
|
|
this.callParent();
|
|
},
|
|
|
|
onDisable: function() {
|
|
var actionEl = this.getActionEl();
|
|
actionEl.dom.setAttribute('aria-disabled', true);
|
|
actionEl.dom.disabled = true;
|
|
this.callParent();
|
|
},
|
|
|
|
|
|
show: function(animateTarget, cb, scope) {
|
|
var me = this;
|
|
|
|
if (me.rendered && me.isVisible()) {
|
|
if (me.toFrontOnShow && me.floating) {
|
|
me.toFront();
|
|
}
|
|
} else if (me.fireEvent('beforeshow', me) !== false) {
|
|
me.hidden = false;
|
|
|
|
|
|
if (!me.rendered && (me.autoRender || me.floating)) {
|
|
me.doAutoRender();
|
|
}
|
|
if (me.rendered) {
|
|
me.beforeShow();
|
|
me.onShow.apply(me, arguments);
|
|
|
|
|
|
|
|
if (me.ownerCt && !me.floating && !(me.ownerCt.suspendLayout || me.ownerCt.layout.layoutBusy)) {
|
|
me.ownerCt.doLayout();
|
|
}
|
|
me.afterShow.apply(me, arguments);
|
|
}
|
|
}
|
|
return me;
|
|
},
|
|
|
|
beforeShow: Ext.emptyFn,
|
|
|
|
|
|
onShow: function() {
|
|
var me = this;
|
|
|
|
me.el.show();
|
|
me.callParent(arguments);
|
|
if (me.floating && me.constrain) {
|
|
me.doConstrain();
|
|
}
|
|
},
|
|
|
|
afterShow: function(animateTarget, cb, scope) {
|
|
var me = this,
|
|
fromBox,
|
|
toBox,
|
|
ghostPanel;
|
|
|
|
|
|
animateTarget = animateTarget || me.animateTarget;
|
|
|
|
|
|
if (!me.ghost) {
|
|
animateTarget = null;
|
|
}
|
|
|
|
if (animateTarget) {
|
|
animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget);
|
|
toBox = me.el.getBox();
|
|
fromBox = animateTarget.getBox();
|
|
me.el.addCls(Ext.baseCSSPrefix + 'hide-offsets');
|
|
ghostPanel = me.ghost();
|
|
ghostPanel.el.stopAnimation();
|
|
|
|
|
|
ghostPanel.el.setX(-10000);
|
|
|
|
ghostPanel.el.animate({
|
|
from: fromBox,
|
|
to: toBox,
|
|
listeners: {
|
|
afteranimate: function() {
|
|
delete ghostPanel.componentLayout.lastComponentSize;
|
|
me.unghost();
|
|
me.el.removeCls(Ext.baseCSSPrefix + 'hide-offsets');
|
|
me.onShowComplete(cb, scope);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
else {
|
|
me.onShowComplete(cb, scope);
|
|
}
|
|
},
|
|
|
|
onShowComplete: function(cb, scope) {
|
|
var me = this;
|
|
if (me.floating) {
|
|
me.toFront();
|
|
}
|
|
Ext.callback(cb, scope || me);
|
|
me.fireEvent('show', me);
|
|
},
|
|
|
|
|
|
hide: function() {
|
|
var me = this;
|
|
|
|
|
|
|
|
me.showOnParentShow = false;
|
|
|
|
if (!(me.rendered && !me.isVisible()) && me.fireEvent('beforehide', me) !== false) {
|
|
me.hidden = true;
|
|
if (me.rendered) {
|
|
me.onHide.apply(me, arguments);
|
|
|
|
|
|
|
|
if (me.ownerCt && !me.floating && !(me.ownerCt.suspendLayout || me.ownerCt.layout.layoutBusy)) {
|
|
me.ownerCt.doLayout();
|
|
}
|
|
}
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
onHide: function(animateTarget, cb, scope) {
|
|
var me = this,
|
|
ghostPanel,
|
|
toBox;
|
|
|
|
|
|
animateTarget = animateTarget || me.animateTarget;
|
|
|
|
|
|
if (!me.ghost) {
|
|
animateTarget = null;
|
|
}
|
|
|
|
if (animateTarget) {
|
|
animateTarget = animateTarget.el ? animateTarget.el : Ext.get(animateTarget);
|
|
ghostPanel = me.ghost();
|
|
ghostPanel.el.stopAnimation();
|
|
toBox = animateTarget.getBox();
|
|
toBox.width += 'px';
|
|
toBox.height += 'px';
|
|
ghostPanel.el.animate({
|
|
to: toBox,
|
|
listeners: {
|
|
afteranimate: function() {
|
|
delete ghostPanel.componentLayout.lastComponentSize;
|
|
ghostPanel.el.hide();
|
|
me.afterHide(cb, scope);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
me.el.hide();
|
|
if (!animateTarget) {
|
|
me.afterHide(cb, scope);
|
|
}
|
|
},
|
|
|
|
afterHide: function(cb, scope) {
|
|
Ext.callback(cb, scope || this);
|
|
this.fireEvent('hide', this);
|
|
},
|
|
|
|
|
|
onDestroy: function() {
|
|
var me = this;
|
|
|
|
|
|
if (me.rendered) {
|
|
Ext.destroy(
|
|
me.proxy,
|
|
me.proxyWrap,
|
|
me.resizer
|
|
);
|
|
|
|
if (me.actionMode == 'container' || me.removeMode == 'container') {
|
|
me.container.remove();
|
|
}
|
|
}
|
|
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) {
|
|
var me = this,
|
|
focusEl;
|
|
|
|
if (delay) {
|
|
if (!me.focusTask) {
|
|
me.focusTask = Ext.create('Ext.util.DelayedTask', me.focus);
|
|
}
|
|
me.focusTask.delay(Ext.isNumber(delay) ? delay : 10, null, me, [selectText, false]);
|
|
return me;
|
|
}
|
|
|
|
if (me.rendered && !me.isDestroyed) {
|
|
|
|
focusEl = me.getFocusEl();
|
|
focusEl.focus();
|
|
if (focusEl.dom && selectText === true) {
|
|
focusEl.dom.select();
|
|
}
|
|
|
|
|
|
|
|
if (me.floating) {
|
|
me.toFront(true);
|
|
}
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
getFocusEl: function() {
|
|
return this.el;
|
|
},
|
|
|
|
|
|
blur: function() {
|
|
if (this.rendered) {
|
|
this.getFocusEl().blur();
|
|
}
|
|
return this;
|
|
},
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
onResize: Ext.emptyFn,
|
|
|
|
|
|
getBubbleTarget: function() {
|
|
return this.ownerCt;
|
|
},
|
|
|
|
|
|
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.ownerCt; p && !fn(p, this); p = p.ownerCt);
|
|
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.ownerCt;
|
|
}
|
|
return this;
|
|
},
|
|
|
|
getProxy: function() {
|
|
var me = this,
|
|
target;
|
|
|
|
if (!me.proxy) {
|
|
target = Ext.getBody();
|
|
if (Ext.scopeResetCSS) {
|
|
me.proxyWrap = target = Ext.getBody().createChild({
|
|
cls: Ext.baseCSSPrefix + 'reset'
|
|
});
|
|
}
|
|
me.proxy = me.el.createProxy(Ext.baseCSSPrefix + 'proxy-el', target, true);
|
|
}
|
|
return me.proxy;
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.container.AbstractContainer', {
|
|
|
|
|
|
|
|
extend: 'Ext.layout.Layout',
|
|
|
|
|
|
|
|
type: 'container',
|
|
|
|
|
|
bindToOwnerCtComponent: false,
|
|
|
|
|
|
bindToOwnerCtContainer: false,
|
|
|
|
|
|
|
|
|
|
setItemSize: function(item, width, height) {
|
|
if (Ext.isObject(width)) {
|
|
height = width.height;
|
|
width = width.width;
|
|
}
|
|
item.setCalculatedSize(width, height, this.owner);
|
|
},
|
|
|
|
|
|
getLayoutItems: function() {
|
|
return this.owner && this.owner.items && this.owner.items.items || [];
|
|
},
|
|
|
|
|
|
beforeLayout: function() {
|
|
return !this.owner.collapsed && this.callParent(arguments);
|
|
},
|
|
|
|
afterLayout: function() {
|
|
this.owner.afterLayout(this);
|
|
},
|
|
|
|
getTarget: function() {
|
|
return this.owner.getTargetEl();
|
|
},
|
|
|
|
getRenderTarget: function() {
|
|
return this.owner.getTargetEl();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.container.Container', {
|
|
|
|
|
|
|
|
extend: 'Ext.layout.container.AbstractContainer',
|
|
alternateClassName: 'Ext.layout.ContainerLayout',
|
|
|
|
|
|
|
|
layoutItem: function(item, box) {
|
|
if (box) {
|
|
item.doComponentLayout(box.width, box.height);
|
|
} else {
|
|
item.doComponentLayout();
|
|
}
|
|
},
|
|
|
|
getLayoutTargetSize : function() {
|
|
var target = this.getTarget(),
|
|
ret;
|
|
|
|
if (target) {
|
|
ret = target.getViewSize();
|
|
|
|
|
|
|
|
|
|
if (Ext.isIE && ret.width == 0){
|
|
ret = target.getStyleSize();
|
|
}
|
|
|
|
ret.width -= target.getPadding('lr');
|
|
ret.height -= target.getPadding('tb');
|
|
}
|
|
return ret;
|
|
},
|
|
|
|
beforeLayout: function() {
|
|
if (this.owner.beforeLayout(arguments) !== false) {
|
|
return this.callParent(arguments);
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
|
|
getRenderedItems: function() {
|
|
var me = this,
|
|
target = me.getTarget(),
|
|
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;
|
|
},
|
|
|
|
|
|
getVisibleItems: function() {
|
|
var target = this.getTarget(),
|
|
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;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.layout.container.Auto', {
|
|
|
|
|
|
|
|
alias: ['layout.auto', 'layout.autocontainer'],
|
|
|
|
extend: 'Ext.layout.container.Container',
|
|
|
|
|
|
|
|
type: 'autocontainer',
|
|
|
|
bindToOwnerCtComponent: true,
|
|
|
|
|
|
onLayout : function(owner, target) {
|
|
var me = this,
|
|
items = me.getLayoutItems(),
|
|
ln = items.length,
|
|
i;
|
|
|
|
|
|
if (ln) {
|
|
|
|
|
|
|
|
if (!me.clearEl) {
|
|
me.clearEl = me.getRenderTarget().createChild({
|
|
cls: Ext.baseCSSPrefix + 'clear',
|
|
role: 'presentation'
|
|
});
|
|
}
|
|
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
me.setItemSize(items[i]);
|
|
}
|
|
}
|
|
},
|
|
|
|
configureItem: function(item) {
|
|
this.callParent(arguments);
|
|
|
|
|
|
item.layoutManagedHeight = 2;
|
|
item.layoutManagedWidth = 2;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.container.AbstractContainer', {
|
|
|
|
|
|
|
|
extend: 'Ext.Component',
|
|
|
|
requires: [
|
|
'Ext.util.MixedCollection',
|
|
'Ext.layout.container.Auto',
|
|
'Ext.ZIndexManager'
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
suspendLayout : false,
|
|
|
|
|
|
autoDestroy : true,
|
|
|
|
|
|
defaultType: 'panel',
|
|
|
|
isContainer : true,
|
|
|
|
|
|
layoutCounter : 0,
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'container',
|
|
|
|
|
|
bubbleEvents: ['add', 'remove'],
|
|
|
|
|
|
initComponent : function(){
|
|
var me = this;
|
|
me.addEvents(
|
|
|
|
'afterlayout',
|
|
|
|
'beforeadd',
|
|
|
|
'beforeremove',
|
|
|
|
'add',
|
|
|
|
'remove'
|
|
);
|
|
|
|
|
|
me.layoutOnShow = Ext.create('Ext.util.MixedCollection');
|
|
me.callParent();
|
|
me.initItems();
|
|
},
|
|
|
|
|
|
initItems : function() {
|
|
var me = this,
|
|
items = me.items;
|
|
|
|
|
|
me.items = Ext.create('Ext.util.MixedCollection', false, me.getComponentId);
|
|
|
|
if (items) {
|
|
if (!Ext.isArray(items)) {
|
|
items = [items];
|
|
}
|
|
|
|
me.add(items);
|
|
}
|
|
},
|
|
|
|
|
|
afterRender : function() {
|
|
this.getLayout();
|
|
this.callParent();
|
|
},
|
|
|
|
renderChildren: function () {
|
|
var me = this,
|
|
layout = me.getLayout();
|
|
|
|
me.callParent();
|
|
|
|
|
|
if (layout) {
|
|
me.suspendLayout = true;
|
|
layout.renderChildren();
|
|
delete me.suspendLayout;
|
|
}
|
|
},
|
|
|
|
|
|
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, 'autocontainer'));
|
|
}
|
|
|
|
return me.layout;
|
|
},
|
|
|
|
|
|
doLayout : function() {
|
|
var me = this,
|
|
layout = me.getLayout();
|
|
|
|
if (me.rendered && layout && !me.suspendLayout) {
|
|
|
|
if (!me.isFixedWidth() || !me.isFixedHeight()) {
|
|
|
|
if (me.componentLayout.layoutBusy !== true) {
|
|
me.doComponentLayout();
|
|
if (me.componentLayout.layoutCancelled === true) {
|
|
layout.layout();
|
|
}
|
|
}
|
|
}
|
|
|
|
else {
|
|
|
|
if (layout.layoutBusy !== true) {
|
|
layout.layout();
|
|
}
|
|
}
|
|
}
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
afterLayout : function(layout) {
|
|
++this.layoutCounter;
|
|
this.fireEvent('afterlayout', this, layout);
|
|
},
|
|
|
|
|
|
prepareItems : function(items, applyDefaults) {
|
|
if (!Ext.isArray(items)) {
|
|
items = [items];
|
|
}
|
|
|
|
|
|
var i = 0,
|
|
len = items.length,
|
|
item;
|
|
|
|
for (; i < len; i++) {
|
|
item = items[i];
|
|
if (applyDefaults) {
|
|
item = this.applyDefaults(item);
|
|
}
|
|
items[i] = this.lookupComponent(item);
|
|
}
|
|
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 Ext.isString(comp) ? Ext.ComponentManager.get(comp) : this.createComponent(comp);
|
|
},
|
|
|
|
|
|
createComponent : function(config, defaultType) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return Ext.ComponentManager.create(config, defaultType || this.defaultType);
|
|
},
|
|
|
|
|
|
getComponentId : function(comp) {
|
|
return comp.getItemId();
|
|
},
|
|
|
|
|
|
add : function() {
|
|
var me = this,
|
|
args = Array.prototype.slice.call(arguments),
|
|
hasMultipleArgs,
|
|
items,
|
|
results = [],
|
|
i,
|
|
ln,
|
|
item,
|
|
index = -1,
|
|
cmp;
|
|
|
|
if (typeof args[0] == 'number') {
|
|
index = args.shift();
|
|
}
|
|
|
|
hasMultipleArgs = args.length > 1;
|
|
if (hasMultipleArgs || Ext.isArray(args[0])) {
|
|
|
|
items = hasMultipleArgs ? args : args[0];
|
|
|
|
me.suspendLayout = true;
|
|
for (i = 0, ln = items.length; i < ln; i++) {
|
|
item = items[i];
|
|
|
|
|
|
if (index != -1) {
|
|
item = me.add(index + i, item);
|
|
} else {
|
|
item = me.add(item);
|
|
}
|
|
results.push(item);
|
|
}
|
|
|
|
me.suspendLayout = false;
|
|
me.doLayout();
|
|
return results;
|
|
}
|
|
|
|
cmp = me.prepareItems(args[0], true)[0];
|
|
|
|
|
|
|
|
|
|
if (cmp.floating) {
|
|
cmp.onAdded(me, index);
|
|
} else {
|
|
index = (index !== -1) ? index : me.items.length;
|
|
if (me.fireEvent('beforeadd', me, cmp, index) !== false && me.onBeforeAdd(cmp) !== false) {
|
|
me.items.insert(index, cmp);
|
|
cmp.onAdded(me, index);
|
|
me.onAdd(cmp, index);
|
|
me.fireEvent('add', me, cmp, index);
|
|
}
|
|
me.doLayout();
|
|
}
|
|
return cmp;
|
|
},
|
|
|
|
onAdd : Ext.emptyFn,
|
|
onRemove : Ext.emptyFn,
|
|
|
|
|
|
insert : function(index, comp) {
|
|
return this.add(index, comp);
|
|
},
|
|
|
|
|
|
move : function(fromIdx, toIdx) {
|
|
var items = this.items,
|
|
item;
|
|
item = items.removeAt(fromIdx);
|
|
if (item === false) {
|
|
return false;
|
|
}
|
|
items.insert(toIdx, item);
|
|
this.doLayout();
|
|
return item;
|
|
},
|
|
|
|
|
|
onBeforeAdd : function(item) {
|
|
var me = this;
|
|
|
|
if (item.ownerCt) {
|
|
item.ownerCt.remove(item, false);
|
|
}
|
|
|
|
if (me.border === false || me.border === 0) {
|
|
item.border = (item.border === true);
|
|
}
|
|
},
|
|
|
|
|
|
remove : function(comp, autoDestroy) {
|
|
var me = this,
|
|
c = me.getComponent(comp);
|
|
|
|
if (c && me.fireEvent('beforeremove', me, c) !== false) {
|
|
me.doRemove(c, autoDestroy);
|
|
me.fireEvent('remove', me, c);
|
|
}
|
|
|
|
return c;
|
|
},
|
|
|
|
|
|
doRemove : function(component, autoDestroy) {
|
|
var me = this,
|
|
layout = me.layout,
|
|
hasLayout = layout && me.rendered;
|
|
|
|
me.items.remove(component);
|
|
component.onRemoved();
|
|
|
|
if (hasLayout) {
|
|
layout.onRemove(component);
|
|
}
|
|
|
|
me.onRemove(component, autoDestroy);
|
|
|
|
if (autoDestroy === true || (autoDestroy !== false && me.autoDestroy)) {
|
|
component.destroy();
|
|
}
|
|
|
|
if (hasLayout && !autoDestroy) {
|
|
layout.afterRemove(component);
|
|
}
|
|
|
|
if (!me.destroying) {
|
|
me.doLayout();
|
|
}
|
|
},
|
|
|
|
|
|
removeAll : function(autoDestroy) {
|
|
var me = this,
|
|
removeItems = me.items.items.slice(),
|
|
items = [],
|
|
i = 0,
|
|
len = removeItems.length,
|
|
item;
|
|
|
|
|
|
me.suspendLayout = true;
|
|
for (; i < len; i++) {
|
|
item = removeItems[i];
|
|
me.remove(item, autoDestroy);
|
|
|
|
if (item.ownerCt !== me) {
|
|
items.push(item);
|
|
}
|
|
}
|
|
|
|
|
|
me.suspendLayout = false;
|
|
if (len) {
|
|
me.doLayout();
|
|
}
|
|
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.push(item);
|
|
if (deep && item.getRefItems) {
|
|
result.push.apply(result, item.getRefItems(true));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (me.floatingItems && me.floatingItems.accessList) {
|
|
result.push.apply(result, me.floatingItems.accessList);
|
|
}
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
getComponent : function(comp) {
|
|
if (Ext.isObject(comp)) {
|
|
comp = comp.getItemId();
|
|
}
|
|
|
|
return this.items.get(comp);
|
|
},
|
|
|
|
|
|
query : function(selector) {
|
|
selector = selector || '*';
|
|
return Ext.ComponentQuery.query(selector, this);
|
|
},
|
|
|
|
|
|
child : function(selector) {
|
|
selector = selector || '';
|
|
return this.query('> ' + selector)[0] || null;
|
|
},
|
|
|
|
|
|
down : function(selector) {
|
|
return this.query(selector)[0] || null;
|
|
},
|
|
|
|
|
|
show : function() {
|
|
this.callParent(arguments);
|
|
this.performDeferredLayouts();
|
|
return this;
|
|
},
|
|
|
|
|
|
|
|
performDeferredLayouts: function() {
|
|
var layoutCollection = this.layoutOnShow,
|
|
ln = layoutCollection.getCount(),
|
|
i = 0,
|
|
needsLayout,
|
|
item;
|
|
|
|
for (; i < ln; i++) {
|
|
item = layoutCollection.get(i);
|
|
needsLayout = item.needsLayout;
|
|
|
|
if (Ext.isObject(needsLayout)) {
|
|
item.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize, needsLayout.ownerCt);
|
|
}
|
|
}
|
|
layoutCollection.clear();
|
|
},
|
|
|
|
//@private
|
|
|
|
|
|
onEnable: function() {
|
|
Ext.Array.each(this.query('[isFormField]'), function(item) {
|
|
if (item.resetDisable) {
|
|
item.enable();
|
|
delete item.resetDisable;
|
|
}
|
|
});
|
|
this.callParent();
|
|
},
|
|
|
|
|
|
|
|
onDisable: function() {
|
|
Ext.Array.each(this.query('[isFormField]'), function(item) {
|
|
if (item.resetDisable !== false && !item.disabled) {
|
|
item.disable();
|
|
item.resetDisable = true;
|
|
}
|
|
});
|
|
this.callParent();
|
|
},
|
|
|
|
|
|
beforeLayout: function() {
|
|
return true;
|
|
},
|
|
|
|
|
|
beforeDestroy : function() {
|
|
var me = this,
|
|
items = me.items,
|
|
c;
|
|
|
|
if (items) {
|
|
while ((c = items.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) {
|
|
var item,
|
|
itemEl,
|
|
i = 0,
|
|
it = this.items.items,
|
|
ln = it.length;
|
|
|
|
el = Ext.getDom(el);
|
|
for (; i < ln; i++) {
|
|
item = it[i];
|
|
itemEl = item.getEl();
|
|
if ((itemEl.dom === el) || itemEl.contains(el)) {
|
|
return item;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.toolbar.Fill', {
|
|
extend: 'Ext.Component',
|
|
alias: 'widget.tbfill',
|
|
alternateClassName: 'Ext.Toolbar.Fill',
|
|
isFill : true,
|
|
flex: 1
|
|
});
|
|
|
|
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
|
|
});
|
|
|
|
Ext.define('Ext.menu.Manager', {
|
|
singleton: true,
|
|
requires: [
|
|
'Ext.util.MixedCollection',
|
|
'Ext.util.KeyMap'
|
|
],
|
|
alternateClassName: 'Ext.menu.MenuMgr',
|
|
|
|
uses: ['Ext.menu.Menu'],
|
|
|
|
menus: {},
|
|
groups: {},
|
|
attached: false,
|
|
lastShow: new Date(),
|
|
|
|
init: function() {
|
|
var me = this;
|
|
|
|
me.active = Ext.create('Ext.util.MixedCollection');
|
|
Ext.getDoc().addKeyListener(27, function() {
|
|
if (me.active.length > 0) {
|
|
me.hideAll();
|
|
}
|
|
}, me);
|
|
},
|
|
|
|
|
|
hideAll: function() {
|
|
var active = this.active,
|
|
c;
|
|
if (active && active.length > 0) {
|
|
c = active.clone();
|
|
c.each(function(m) {
|
|
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,
|
|
last = active.last(),
|
|
attached = me.attached,
|
|
menuEl = m.getEl(),
|
|
zIndex;
|
|
|
|
me.lastShow = new Date();
|
|
active.add(m);
|
|
if (!attached) {
|
|
Ext.getDoc().on('mousedown', me.onMouseDown, me);
|
|
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,
|
|
target = e.target;
|
|
|
|
if (Ext.Date.getElapsed(lastShow) > 50 && active.length > 0 && !e.getTarget('.' + Ext.baseCSSPrefix + 'menu')) {
|
|
me.hideAll();
|
|
|
|
|
|
if (Ext.isIE && Ext.fly(target).focusable()) {
|
|
target.focus();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
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 Ext.create('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.layout.component.Button', {
|
|
|
|
|
|
|
|
alias: ['layout.button'],
|
|
|
|
extend: 'Ext.layout.component.Component',
|
|
|
|
|
|
|
|
type: 'button',
|
|
|
|
cellClsRE: /-btn-(tl|br)\b/,
|
|
htmlRE: /<.*>/,
|
|
|
|
beforeLayout: function() {
|
|
return this.callParent(arguments) || this.lastText !== this.owner.text;
|
|
},
|
|
|
|
|
|
onLayout: function(width, height) {
|
|
var me = this,
|
|
isNum = Ext.isNumber,
|
|
owner = me.owner,
|
|
ownerEl = owner.el,
|
|
btnEl = owner.btnEl,
|
|
btnInnerEl = owner.btnInnerEl,
|
|
btnIconEl = owner.btnIconEl,
|
|
sizeIconEl = (owner.icon || owner.iconCls) && (owner.iconAlign == "top" || owner.iconAlign == "bottom"),
|
|
minWidth = owner.minWidth,
|
|
maxWidth = owner.maxWidth,
|
|
ownerWidth, btnFrameWidth, metrics;
|
|
|
|
me.getTargetInfo();
|
|
me.callParent(arguments);
|
|
|
|
btnInnerEl.unclip();
|
|
me.setTargetSize(width, height);
|
|
|
|
if (!isNum(width)) {
|
|
|
|
|
|
|
|
if (owner.text && (Ext.isIE6 || Ext.isIE7) && Ext.isStrict && btnEl && btnEl.getWidth() > 20) {
|
|
btnFrameWidth = me.btnFrameWidth;
|
|
metrics = Ext.util.TextMetrics.measure(btnInnerEl, owner.text);
|
|
ownerEl.setWidth(metrics.width + btnFrameWidth + me.adjWidth);
|
|
btnEl.setWidth(metrics.width + btnFrameWidth);
|
|
btnInnerEl.setWidth(metrics.width + btnFrameWidth);
|
|
|
|
if (sizeIconEl) {
|
|
btnIconEl.setWidth(metrics.width + btnFrameWidth);
|
|
}
|
|
} else {
|
|
|
|
ownerEl.setWidth(null);
|
|
btnEl.setWidth(null);
|
|
btnInnerEl.setWidth(null);
|
|
btnIconEl.setWidth(null);
|
|
}
|
|
|
|
|
|
if (minWidth || maxWidth) {
|
|
ownerWidth = ownerEl.getWidth();
|
|
if (minWidth && (ownerWidth < minWidth)) {
|
|
me.setTargetSize(minWidth, height);
|
|
}
|
|
else if (maxWidth && (ownerWidth > maxWidth)) {
|
|
btnInnerEl.clip();
|
|
me.setTargetSize(maxWidth, height);
|
|
}
|
|
}
|
|
}
|
|
|
|
this.lastText = owner.text;
|
|
},
|
|
|
|
setTargetSize: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
isNum = Ext.isNumber,
|
|
btnInnerEl = owner.btnInnerEl,
|
|
btnWidth = (isNum(width) ? width - me.adjWidth : width),
|
|
btnHeight = (isNum(height) ? height - me.adjHeight : height),
|
|
btnFrameHeight = me.btnFrameHeight,
|
|
text = owner.getText(),
|
|
textHeight;
|
|
|
|
me.callParent(arguments);
|
|
me.setElementSize(owner.btnEl, btnWidth, btnHeight);
|
|
me.setElementSize(btnInnerEl, btnWidth, btnHeight);
|
|
if (btnHeight >= 0) {
|
|
btnInnerEl.setStyle('line-height', btnHeight - btnFrameHeight + 'px');
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (text && this.htmlRE.test(text)) {
|
|
btnInnerEl.setStyle('line-height', 'normal');
|
|
textHeight = Ext.util.TextMetrics.measure(btnInnerEl, text).height;
|
|
btnInnerEl.setStyle('padding-top', me.btnFrameTop + Math.max(btnInnerEl.getHeight() - btnFrameHeight - textHeight, 0) / 2 + 'px');
|
|
me.setElementSize(btnInnerEl, btnWidth, btnHeight);
|
|
}
|
|
},
|
|
|
|
getTargetInfo: function() {
|
|
var me = this,
|
|
owner = me.owner,
|
|
ownerEl = owner.el,
|
|
frameSize = me.frameSize,
|
|
frameBody = owner.frameBody,
|
|
btnWrap = owner.btnWrap,
|
|
innerEl = owner.btnInnerEl;
|
|
|
|
if (!('adjWidth' in me)) {
|
|
Ext.apply(me, {
|
|
|
|
adjWidth: frameSize.left + frameSize.right + ownerEl.getBorderWidth('lr') + ownerEl.getPadding('lr') +
|
|
btnWrap.getPadding('lr') + (frameBody ? frameBody.getFrameWidth('lr') : 0),
|
|
adjHeight: frameSize.top + frameSize.bottom + ownerEl.getBorderWidth('tb') + ownerEl.getPadding('tb') +
|
|
btnWrap.getPadding('tb') + (frameBody ? frameBody.getFrameWidth('tb') : 0),
|
|
btnFrameWidth: innerEl.getFrameWidth('lr'),
|
|
btnFrameHeight: innerEl.getFrameWidth('tb'),
|
|
btnFrameTop: innerEl.getFrameWidth('t')
|
|
});
|
|
}
|
|
|
|
return me.callParent();
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.button.Button', {
|
|
|
|
|
|
alias: 'widget.button',
|
|
extend: 'Ext.Component',
|
|
|
|
requires: [
|
|
'Ext.menu.Manager',
|
|
'Ext.util.ClickRepeater',
|
|
'Ext.layout.component.Button',
|
|
'Ext.util.TextMetrics',
|
|
'Ext.util.KeyMap'
|
|
],
|
|
|
|
alternateClassName: 'Ext.Button',
|
|
|
|
|
|
isButton: true,
|
|
componentLayout: 'button',
|
|
|
|
|
|
hidden: false,
|
|
|
|
|
|
disabled: false,
|
|
|
|
|
|
pressed: false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enableToggle: false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
menuAlign: 'tl-bl?',
|
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
type: 'button',
|
|
|
|
|
|
clickEvent: 'click',
|
|
|
|
|
|
preventDefault: true,
|
|
|
|
|
|
handleMouseEvents: true,
|
|
|
|
|
|
tooltipType: 'qtip',
|
|
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'btn',
|
|
|
|
|
|
pressedCls: 'pressed',
|
|
|
|
|
|
overCls: 'over',
|
|
|
|
|
|
focusCls: 'focus',
|
|
|
|
|
|
menuActiveCls: 'menu-active',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ariaRole: 'button',
|
|
|
|
|
|
renderTpl:
|
|
'<em id="{id}-btnWrap" class="{splitCls}">' +
|
|
'<tpl if="href">' +
|
|
'<a id="{id}-btnEl" href="{href}" target="{target}"<tpl if="tabIndex"> tabIndex="{tabIndex}"</tpl> role="link">' +
|
|
'<span id="{id}-btnInnerEl" class="{baseCls}-inner">' +
|
|
'{text}' +
|
|
'</span>' +
|
|
'<span id="{id}-btnIconEl" class="{baseCls}-icon"></span>' +
|
|
'</a>' +
|
|
'</tpl>' +
|
|
'<tpl if="!href">' +
|
|
'<button id="{id}-btnEl" type="{type}" hidefocus="true"' +
|
|
|
|
|
|
'<tpl if="tabIndex"> tabIndex="{tabIndex}"</tpl> role="button" autocomplete="off">' +
|
|
'<span id="{id}-btnInnerEl" class="{baseCls}-inner" style="{innerSpanStyle}">' +
|
|
'{text}' +
|
|
'</span>' +
|
|
'<span id="{id}-btnIconEl" class="{baseCls}-icon {iconCls}"> </span>' +
|
|
'</button>' +
|
|
'</tpl>' +
|
|
'</em>' ,
|
|
|
|
|
|
scale: 'small',
|
|
|
|
|
|
allowedScales: ['small', 'medium', 'large'],
|
|
|
|
|
|
|
|
|
|
iconAlign: 'left',
|
|
|
|
|
|
arrowAlign: 'right',
|
|
|
|
|
|
arrowCls: 'arrow',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
maskOnDisable: false,
|
|
|
|
|
|
initComponent: function() {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
|
|
me.addEvents(
|
|
|
|
'click',
|
|
|
|
|
|
'toggle',
|
|
|
|
|
|
'mouseover',
|
|
|
|
|
|
'mouseout',
|
|
|
|
|
|
'menushow',
|
|
|
|
|
|
'menuhide',
|
|
|
|
|
|
'menutriggerover',
|
|
|
|
|
|
'menutriggerout'
|
|
);
|
|
|
|
if (me.menu) {
|
|
|
|
me.split = true;
|
|
|
|
|
|
me.menu = Ext.menu.Manager.get(me.menu);
|
|
me.menu.ownerCt = me;
|
|
}
|
|
|
|
|
|
if (me.url) {
|
|
me.href = me.url;
|
|
}
|
|
|
|
|
|
if (me.href && !me.hasOwnProperty('preventDefault')) {
|
|
me.preventDefault = false;
|
|
}
|
|
|
|
if (Ext.isString(me.toggleGroup)) {
|
|
me.enableToggle = true;
|
|
}
|
|
|
|
},
|
|
|
|
|
|
initAria: function() {
|
|
this.callParent();
|
|
var actionEl = this.getActionEl();
|
|
if (this.menu) {
|
|
actionEl.dom.setAttribute('aria-haspopup', true);
|
|
}
|
|
},
|
|
|
|
|
|
getActionEl: function() {
|
|
return this.btnEl;
|
|
},
|
|
|
|
|
|
getFocusEl: function() {
|
|
return this.btnEl;
|
|
},
|
|
|
|
|
|
setButtonCls: function() {
|
|
var me = this,
|
|
cls = [],
|
|
btnIconEl = me.btnIconEl,
|
|
hide = 'x-hide-display';
|
|
|
|
if (me.useSetClass) {
|
|
if (!Ext.isEmpty(me.oldCls)) {
|
|
me.removeClsWithUI(me.oldCls);
|
|
me.removeClsWithUI(me.pressedCls);
|
|
}
|
|
|
|
|
|
if (me.iconCls || me.icon) {
|
|
if (me.text) {
|
|
cls.push('icon-text-' + me.iconAlign);
|
|
} else {
|
|
cls.push('icon');
|
|
}
|
|
if (btnIconEl) {
|
|
btnIconEl.removeCls(hide);
|
|
}
|
|
} else {
|
|
if (me.text) {
|
|
cls.push('noicon');
|
|
}
|
|
if (btnIconEl) {
|
|
btnIconEl.addCls(hide);
|
|
}
|
|
}
|
|
|
|
me.oldCls = cls;
|
|
me.addClsWithUI(cls);
|
|
me.addClsWithUI(me.pressed ? me.pressedCls : null);
|
|
}
|
|
},
|
|
|
|
|
|
onRender: function(ct, position) {
|
|
|
|
var me = this,
|
|
repeater, btn;
|
|
|
|
|
|
Ext.applyIf(me.renderData, me.getTemplateArgs());
|
|
|
|
me.addChildEls('btnEl', 'btnWrap', 'btnInnerEl', 'btnIconEl');
|
|
|
|
if (me.scale) {
|
|
me.ui = me.ui + '-' + me.scale;
|
|
}
|
|
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
if (me.split && me.arrowTooltip) {
|
|
me.arrowEl.dom.setAttribute(me.getTipAttr(), me.arrowTooltip);
|
|
}
|
|
|
|
|
|
me.mon(me.btnEl, {
|
|
scope: me,
|
|
focus: me.onFocus,
|
|
blur : me.onBlur
|
|
});
|
|
|
|
|
|
btn = me.el;
|
|
|
|
if (me.icon) {
|
|
me.setIcon(me.icon);
|
|
}
|
|
|
|
if (me.iconCls) {
|
|
me.setIconCls(me.iconCls);
|
|
}
|
|
|
|
if (me.tooltip) {
|
|
me.setTooltip(me.tooltip, true);
|
|
}
|
|
|
|
if (me.textAlign) {
|
|
me.setTextAlign(me.textAlign);
|
|
}
|
|
|
|
|
|
if (me.handleMouseEvents) {
|
|
me.mon(btn, {
|
|
scope: me,
|
|
mouseover: me.onMouseOver,
|
|
mouseout: me.onMouseOut,
|
|
mousedown: me.onMouseDown
|
|
});
|
|
|
|
if (me.split) {
|
|
me.mon(btn, {
|
|
mousemove: me.onMouseMove,
|
|
scope: me
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
if (me.menu) {
|
|
me.mon(me.menu, {
|
|
scope: me,
|
|
show: me.onMenuShow,
|
|
hide: me.onMenuHide
|
|
});
|
|
|
|
me.keyMap = Ext.create('Ext.util.KeyMap', me.el, {
|
|
key: Ext.EventObject.DOWN,
|
|
handler: me.onDownKey,
|
|
scope: me
|
|
});
|
|
}
|
|
|
|
|
|
if (me.repeat) {
|
|
repeater = Ext.create('Ext.util.ClickRepeater', btn, Ext.isObject(me.repeat) ? me.repeat: {});
|
|
me.mon(repeater, 'click', me.onRepeatClick, me);
|
|
} else {
|
|
me.mon(btn, me.clickEvent, me.onClick, me);
|
|
}
|
|
|
|
|
|
Ext.ButtonToggleManager.register(me);
|
|
},
|
|
|
|
|
|
getTemplateArgs: function() {
|
|
var me = this,
|
|
persistentPadding = me.getPersistentBtnPadding(),
|
|
innerSpanStyle = '';
|
|
|
|
|
|
if (Math.max.apply(Math, persistentPadding) > 0) {
|
|
innerSpanStyle = 'margin:' + Ext.Array.map(persistentPadding, function(pad) {
|
|
return -pad + 'px';
|
|
}).join(' ');
|
|
}
|
|
|
|
return {
|
|
href : me.getHref(),
|
|
target : me.target || '_blank',
|
|
type : me.type,
|
|
splitCls : me.getSplitCls(),
|
|
cls : me.cls,
|
|
iconCls : me.iconCls || '',
|
|
text : me.text || ' ',
|
|
tabIndex : me.tabIndex,
|
|
innerSpanStyle: innerSpanStyle
|
|
};
|
|
},
|
|
|
|
|
|
getHref: function() {
|
|
var me = this,
|
|
params = Ext.apply({}, me.baseParams);
|
|
|
|
|
|
params = Ext.apply(params, me.params);
|
|
return me.href ? Ext.urlAppend(me.href, Ext.Object.toQueryString(params)) : false;
|
|
},
|
|
|
|
|
|
setParams: function(params) {
|
|
this.params = params;
|
|
this.btnEl.dom.href = this.getHref();
|
|
},
|
|
|
|
getSplitCls: function() {
|
|
var me = this;
|
|
return me.split ? (me.baseCls + '-' + me.arrowCls) + ' ' + (me.baseCls + '-' + me.arrowCls + '-' + me.arrowAlign) : '';
|
|
},
|
|
|
|
|
|
afterRender: function() {
|
|
var me = this;
|
|
me.useSetClass = true;
|
|
me.setButtonCls();
|
|
me.doc = Ext.getDoc();
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
setIconCls: function(cls) {
|
|
var me = this,
|
|
btnIconEl = me.btnIconEl,
|
|
oldCls = me.iconCls;
|
|
|
|
me.iconCls = cls;
|
|
if (btnIconEl) {
|
|
|
|
btnIconEl.removeCls(oldCls);
|
|
btnIconEl.addCls(cls || '');
|
|
me.setButtonCls();
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
setTooltip: function(tooltip, initial) {
|
|
var me = this;
|
|
|
|
if (me.rendered) {
|
|
if (!initial) {
|
|
me.clearTip();
|
|
}
|
|
if (Ext.isObject(tooltip)) {
|
|
Ext.tip.QuickTipManager.register(Ext.apply({
|
|
target: me.btnEl.id
|
|
},
|
|
tooltip));
|
|
me.tooltip = tooltip;
|
|
} else {
|
|
me.btnEl.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 + '-' + me.textAlign);
|
|
btnEl.addCls(me.baseCls + '-' + 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() {
|
|
if (Ext.isObject(this.tooltip)) {
|
|
Ext.tip.QuickTipManager.unregister(this.btnEl);
|
|
}
|
|
},
|
|
|
|
|
|
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);
|
|
me.doc.un('mouseup', me.onMouseUp, me);
|
|
delete me.doc;
|
|
Ext.ButtonToggleManager.unregister(me);
|
|
|
|
Ext.destroy(me.keyMap);
|
|
delete me.keyMap;
|
|
}
|
|
me.callParent();
|
|
},
|
|
|
|
|
|
setHandler: function(handler, scope) {
|
|
this.handler = handler;
|
|
this.scope = scope;
|
|
return this;
|
|
},
|
|
|
|
|
|
setText: function(text) {
|
|
var me = this;
|
|
me.text = text;
|
|
if (me.el) {
|
|
me.btnInnerEl.update(text || ' ');
|
|
me.setButtonCls();
|
|
}
|
|
me.doComponentLayout();
|
|
return me;
|
|
},
|
|
|
|
|
|
setIcon: function(icon) {
|
|
var me = this,
|
|
iconEl = me.btnIconEl;
|
|
|
|
me.icon = icon;
|
|
if (iconEl) {
|
|
iconEl.setStyle('background-image', icon ? 'url(' + icon + ')': '');
|
|
me.setButtonCls();
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
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.btnEl.dom.setAttribute('aria-pressed', state);
|
|
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();
|
|
}
|
|
},
|
|
|
|
|
|
showMenu: function() {
|
|
var me = this;
|
|
if (me.rendered && me.menu) {
|
|
if (me.tooltip && me.getTipAttr() != 'title') {
|
|
Ext.tip.QuickTipManager.getQuickTip().cancelShow(me.btnEl);
|
|
}
|
|
if (me.menu.isVisible()) {
|
|
me.menu.hide();
|
|
}
|
|
|
|
me.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;
|
|
if (me.preventDefault || (me.disabled && me.getHref()) && e) {
|
|
e.preventDefault();
|
|
}
|
|
if (e.button !== 0) {
|
|
return;
|
|
}
|
|
if (!me.disabled) {
|
|
me.doToggle();
|
|
me.maybeShowMenu();
|
|
me.fireHandler(e);
|
|
}
|
|
},
|
|
|
|
fireHandler: function(e){
|
|
var me = this,
|
|
handler = me.handler;
|
|
|
|
me.fireEvent('click', me, e);
|
|
if (handler) {
|
|
handler.call(me.scope || me, me, e);
|
|
}
|
|
me.onBlur();
|
|
},
|
|
|
|
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,
|
|
overlap, btnSize;
|
|
|
|
if (me.split) {
|
|
if (me.arrowAlign === 'right') {
|
|
overlap = e.getX() - el.getX();
|
|
btnSize = el.getWidth();
|
|
} else {
|
|
overlap = e.getY() - el.getY();
|
|
btnSize = el.getHeight();
|
|
}
|
|
|
|
if (overlap > (btnSize - me.getTriggerSize())) {
|
|
if (!over) {
|
|
me.onMenuTriggerOver(e);
|
|
}
|
|
} else {
|
|
if (over) {
|
|
me.onMenuTriggerOut(e);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getTriggerSize: function() {
|
|
var me = this,
|
|
size = me.triggerSize,
|
|
side, sideFirstLetter, undef;
|
|
|
|
if (size === undef) {
|
|
side = me.arrowAlign;
|
|
sideFirstLetter = side.charAt(0);
|
|
size = me.triggerSize = me.el.getFrameWidth(sideFirstLetter) + me.btnWrap.getFrameWidth(sideFirstLetter) + (me.frameSize && me.frameSize[side] || 0);
|
|
}
|
|
return size;
|
|
},
|
|
|
|
|
|
onMouseEnter: function(e) {
|
|
var me = this;
|
|
me.addClsWithUI(me.overCls);
|
|
me.fireEvent('mouseover', me, e);
|
|
},
|
|
|
|
|
|
onMouseLeave: function(e) {
|
|
var me = this;
|
|
me.removeClsWithUI(me.overCls);
|
|
me.fireEvent('mouseout', me, e);
|
|
},
|
|
|
|
|
|
onMenuTriggerOver: function(e) {
|
|
var me = this;
|
|
me.overMenuTrigger = true;
|
|
me.fireEvent('menutriggerover', me, me.menu, e);
|
|
},
|
|
|
|
|
|
onMenuTriggerOut: function(e) {
|
|
var me = this;
|
|
delete me.overMenuTrigger;
|
|
me.fireEvent('menutriggerout', me, me.menu, e);
|
|
},
|
|
|
|
|
|
enable : function(silent) {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
me.removeClsWithUI('disabled');
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
disable : function(silent) {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
me.addClsWithUI('disabled');
|
|
me.removeClsWithUI(me.overCls);
|
|
|
|
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]);
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
onFocus: function(e) {
|
|
var me = this;
|
|
if (!me.disabled) {
|
|
me.addClsWithUI(me.focusCls);
|
|
}
|
|
},
|
|
|
|
|
|
onBlur: function(e) {
|
|
var me = this;
|
|
me.removeClsWithUI(me.focusCls);
|
|
},
|
|
|
|
|
|
onMouseDown: function(e) {
|
|
var me = this;
|
|
if (!me.disabled && e.button === 0) {
|
|
me.addClsWithUI(me.pressedCls);
|
|
me.doc.on('mouseup', me.onMouseUp, me);
|
|
}
|
|
},
|
|
|
|
onMouseUp: function(e) {
|
|
var me = this;
|
|
if (e.button === 0) {
|
|
if (!me.pressed) {
|
|
me.removeClsWithUI(me.pressedCls);
|
|
}
|
|
me.doc.un('mouseup', me.onMouseUp, me);
|
|
}
|
|
},
|
|
|
|
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);
|
|
},
|
|
|
|
|
|
restoreClick: function() {
|
|
this.ignoreNextClick = 0;
|
|
},
|
|
|
|
|
|
onDownKey: function() {
|
|
var me = this;
|
|
|
|
if (!me.disabled) {
|
|
if (me.menu) {
|
|
me.showMenu();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getPersistentBtnPadding: function() {
|
|
var cls = Ext.button.Button,
|
|
padding = cls.persistentPadding,
|
|
btn, leftTop, btnEl, btnInnerEl;
|
|
|
|
if (!padding) {
|
|
padding = cls.persistentPadding = [0, 0, 0, 0];
|
|
|
|
if (!Ext.isIE) {
|
|
|
|
btn = Ext.create('Ext.button.Button', {
|
|
renderTo: Ext.getBody(),
|
|
text: 'test',
|
|
style: 'position:absolute;top:-999px;'
|
|
});
|
|
btnEl = btn.btnEl;
|
|
btnInnerEl = btn.btnInnerEl;
|
|
btnEl.setSize(null, null);
|
|
|
|
leftTop = btnInnerEl.getOffsetsTo(btnEl);
|
|
padding[0] = leftTop[1];
|
|
padding[1] = btnEl.getWidth() - btnInnerEl.getWidth() - leftTop[0];
|
|
padding[2] = btnEl.getHeight() - btnInnerEl.getHeight() - leftTop[1];
|
|
padding[3] = leftTop[0];
|
|
|
|
btn.destroy();
|
|
}
|
|
}
|
|
|
|
return padding;
|
|
}
|
|
|
|
}, function() {
|
|
var groups = {};
|
|
|
|
function toggleGroup(btn, state) {
|
|
var g, i, l;
|
|
if (state) {
|
|
g = groups[btn.toggleGroup];
|
|
for (i = 0, l = g.length; i < l; i++) {
|
|
if (g[i] !== btn) {
|
|
g[i].toggle(false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
Ext.ButtonToggleManager = {
|
|
register: function(btn) {
|
|
if (!btn.toggleGroup) {
|
|
return;
|
|
}
|
|
var group = groups[btn.toggleGroup];
|
|
if (!group) {
|
|
group = groups[btn.toggleGroup] = [];
|
|
}
|
|
group.push(btn);
|
|
btn.on('toggle', toggleGroup);
|
|
},
|
|
|
|
unregister: function(btn) {
|
|
if (!btn.toggleGroup) {
|
|
return;
|
|
}
|
|
var group = groups[btn.toggleGroup];
|
|
if (group) {
|
|
Ext.Array.remove(group, btn);
|
|
btn.un('toggle', toggleGroup);
|
|
}
|
|
},
|
|
|
|
|
|
getPressed: function(group) {
|
|
var g = 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.layout.container.boxOverflow.Menu', {
|
|
|
|
|
|
|
|
extend: 'Ext.layout.container.boxOverflow.None',
|
|
requires: ['Ext.toolbar.Separator', 'Ext.button.Button'],
|
|
alternateClassName: 'Ext.layout.boxOverflow.Menu',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
noItemsMenuText : '<div class="' + Ext.baseCSSPrefix + 'toolbar-no-items">(None)</div>',
|
|
|
|
constructor: function(layout) {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
layout.beforeLayout = Ext.Function.createInterceptor(layout.beforeLayout, this.clearOverflow, this);
|
|
|
|
me.afterCtCls = me.afterCtCls || Ext.baseCSSPrefix + 'box-menu-' + layout.parallelAfter;
|
|
|
|
me.menuItems = [];
|
|
},
|
|
|
|
onRemove: function(comp){
|
|
Ext.Array.remove(this.menuItems, comp);
|
|
},
|
|
|
|
handleOverflow: function(calculations, targetSize) {
|
|
var me = this,
|
|
layout = me.layout,
|
|
methodName = 'get' + layout.parallelPrefixCap,
|
|
newSize = {},
|
|
posArgs = [null, null];
|
|
|
|
me.callParent(arguments);
|
|
this.createMenu(calculations, targetSize);
|
|
newSize[layout.perpendicularPrefix] = targetSize[layout.perpendicularPrefix];
|
|
newSize[layout.parallelPrefix] = targetSize[layout.parallelPrefix] - me.afterCt[methodName]();
|
|
|
|
|
|
|
|
posArgs[layout.perpendicularSizeIndex] = (calculations.meta.maxSize - me.menuTrigger['get' + layout.perpendicularPrefixCap]()) / 2;
|
|
me.menuTrigger.setPosition.apply(me.menuTrigger, posArgs);
|
|
|
|
return { targetSize: newSize };
|
|
},
|
|
|
|
|
|
clearOverflow: function(calculations, targetSize) {
|
|
var me = this,
|
|
newWidth = targetSize ? targetSize.width + (me.afterCt ? me.afterCt.getWidth() : 0) : 0,
|
|
items = me.menuItems,
|
|
i = 0,
|
|
length = items.length,
|
|
item;
|
|
|
|
me.hideTrigger();
|
|
for (; i < length; i++) {
|
|
items[i].show();
|
|
}
|
|
items.length = 0;
|
|
|
|
return targetSize ? {
|
|
targetSize: {
|
|
height: targetSize.height,
|
|
width : newWidth
|
|
}
|
|
} : null;
|
|
},
|
|
|
|
|
|
showTrigger: function() {
|
|
this.menuTrigger.show();
|
|
},
|
|
|
|
|
|
hideTrigger: function() {
|
|
if (this.menuTrigger !== undefined) {
|
|
this.menuTrigger.hide();
|
|
}
|
|
},
|
|
|
|
|
|
beforeMenuShow: function(menu) {
|
|
var me = this,
|
|
items = me.menuItems,
|
|
i = 0,
|
|
len = items.length,
|
|
item,
|
|
prev;
|
|
|
|
var needsSep = function(group, prev){
|
|
return group.isXType('buttongroup') && !(prev instanceof Ext.toolbar.Separator);
|
|
};
|
|
|
|
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);
|
|
}
|
|
},
|
|
|
|
|
|
createMenuConfig : function(component, hideOnClick) {
|
|
var config = Ext.apply({}, component.initialConfig),
|
|
group = component.toggleGroup;
|
|
|
|
Ext.copyTo(config, component, [
|
|
'iconCls', 'icon', 'itemId', 'disabled', 'handler', 'scope', 'menu'
|
|
]);
|
|
|
|
Ext.apply(config, {
|
|
text : component.overflowText || component.text,
|
|
hideOnClick: hideOnClick,
|
|
destroyMenu: false
|
|
});
|
|
|
|
if (group || component.enableToggle) {
|
|
Ext.apply(config, {
|
|
group : group,
|
|
checked: component.pressed,
|
|
listeners: {
|
|
checkchange: function(item, checked){
|
|
component.toggle(checked);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
delete config.ownerCt;
|
|
delete config.xtype;
|
|
delete config.id;
|
|
return config;
|
|
},
|
|
|
|
|
|
addComponentToMenu : function(menu, component) {
|
|
var me = this;
|
|
if (component instanceof Ext.toolbar.Separator) {
|
|
menu.add('-');
|
|
} else if (component.isComponent) {
|
|
if (component.isXType('splitbutton')) {
|
|
menu.add(me.createMenuConfig(component, true));
|
|
|
|
} else if (component.isXType('button')) {
|
|
menu.add(me.createMenuConfig(component, !component.menu));
|
|
|
|
} else if (component.isXType('buttongroup')) {
|
|
component.items.each(function(item){
|
|
me.addComponentToMenu(menu, item);
|
|
});
|
|
} else {
|
|
menu.add(Ext.create(Ext.getClassName(component), me.createMenuConfig(component)));
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
clearMenu : function() {
|
|
var menu = this.moreMenu;
|
|
if (menu && menu.items) {
|
|
menu.items.each(function(item) {
|
|
if (item.menu) {
|
|
delete item.menu;
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
createMenu: function(calculations, targetSize) {
|
|
var me = this,
|
|
layout = me.layout,
|
|
startProp = layout.parallelBefore,
|
|
sizeProp = layout.parallelPrefix,
|
|
available = targetSize[sizeProp],
|
|
boxes = calculations.boxes,
|
|
i = 0,
|
|
len = boxes.length,
|
|
box;
|
|
|
|
if (!me.menuTrigger) {
|
|
me.createInnerElements();
|
|
|
|
|
|
me.menu = Ext.create('Ext.menu.Menu', {
|
|
listeners: {
|
|
scope: me,
|
|
beforeshow: me.beforeMenuShow
|
|
}
|
|
});
|
|
|
|
|
|
me.menuTrigger = Ext.create('Ext.button.Button', {
|
|
ownerCt : me.layout.owner,
|
|
iconCls : me.layout.owner.menuTriggerCls,
|
|
ui : layout.owner instanceof Ext.toolbar.Toolbar ? 'default-toolbar' : 'default',
|
|
menu : me.menu,
|
|
getSplitCls: function() { return '';},
|
|
renderTo: me.afterCt
|
|
});
|
|
}
|
|
me.showTrigger();
|
|
available -= me.afterCt.getWidth();
|
|
|
|
|
|
|
|
me.menuItems.length = 0;
|
|
for (; i < len; i++) {
|
|
box = boxes[i];
|
|
if (box[startProp] + box[sizeProp] > available) {
|
|
me.menuItems.push(box.component);
|
|
box.component.hide();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
createInnerElements: function() {
|
|
var me = this,
|
|
target = me.layout.getRenderTarget();
|
|
|
|
if (!this.afterCt) {
|
|
target.addCls(Ext.baseCSSPrefix + me.layout.direction + '-box-overflow-body');
|
|
this.afterCt = target.insertSibling({cls: Ext.layout.container.Box.prototype.innerCls + ' ' + this.afterCtCls}, 'before');
|
|
}
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
Ext.destroy(this.menu, this.menuTrigger);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.util.Region', {
|
|
|
|
|
|
|
|
requires: ['Ext.util.Offset'],
|
|
|
|
statics: {
|
|
|
|
getRegion: function(el) {
|
|
return Ext.fly(el).getPageBox(true);
|
|
},
|
|
|
|
|
|
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 = Ext.create('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,
|
|
|
|
requires: ['Ext.util.Region'],
|
|
|
|
uses: ['Ext.tip.QuickTipManager'],
|
|
|
|
|
|
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,
|
|
|
|
|
|
_execOnAll: function(sMethod, args) {
|
|
for (var i in this.ids) {
|
|
for (var j in this.ids[i]) {
|
|
var oDD = this.ids[i][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) {
|
|
for (var g in oDD.groups) {
|
|
if (g && this.ids[g] && this.ids[g][oDD.id]) {
|
|
delete this.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 = [];
|
|
for (var i in p_oDD.groups) {
|
|
for (var j in this.ids[i]) {
|
|
var 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);
|
|
for (var i=0, len=targets.length;i<len;++i) {
|
|
if (targets[i].id == oTargetDD.id) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
|
|
isTypeOfDD: function (oDD) {
|
|
return (oDD && oDD.__ygDragDrop);
|
|
},
|
|
|
|
|
|
isHandle: function(sDDId, sHandleId) {
|
|
return ( this.handleIds[sDDId] &&
|
|
this.handleIds[sDDId][sHandleId] );
|
|
},
|
|
|
|
|
|
getDDById: function(id) {
|
|
for (var i in this.ids) {
|
|
if (this.ids[i][id]) {
|
|
return this.ids[i][id];
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
|
|
handleMouseDown: function(e, oDD) {
|
|
if(Ext.tip.QuickTipManager){
|
|
Ext.tip.QuickTipManager.ddDisable();
|
|
}
|
|
if(this.dragCurrent){
|
|
|
|
|
|
this.handleMouseUp(e);
|
|
}
|
|
|
|
this.currentTarget = e.getTarget();
|
|
this.dragCurrent = oDD;
|
|
|
|
var el = oDD.getEl();
|
|
|
|
|
|
this.startX = e.getPageX();
|
|
this.startY = e.getPageY();
|
|
|
|
this.deltaX = this.startX - el.offsetLeft;
|
|
this.deltaY = this.startY - el.offsetTop;
|
|
|
|
this.dragThreshMet = false;
|
|
|
|
this.clickTimeout = setTimeout(
|
|
function() {
|
|
var DDM = Ext.dd.DragDropManager;
|
|
DDM.startDrag(DDM.startX, DDM.startY);
|
|
},
|
|
this.clickTimeThresh );
|
|
},
|
|
|
|
|
|
startDrag: function(x, y) {
|
|
clearTimeout(this.clickTimeout);
|
|
if (this.dragCurrent) {
|
|
this.dragCurrent.b4StartDrag(x, y);
|
|
this.dragCurrent.startDrag(x, y);
|
|
}
|
|
this.dragThreshMet = true;
|
|
},
|
|
|
|
|
|
handleMouseUp: function(e) {
|
|
|
|
if(Ext.tip && Ext.tip.QuickTipManager){
|
|
Ext.tip.QuickTipManager.ddEnable();
|
|
}
|
|
if (! this.dragCurrent) {
|
|
return;
|
|
}
|
|
|
|
clearTimeout(this.clickTimeout);
|
|
|
|
if (this.dragThreshMet) {
|
|
this.fireEvents(e, true);
|
|
} else {
|
|
}
|
|
|
|
this.stopDrag(e);
|
|
|
|
this.stopEvent(e);
|
|
},
|
|
|
|
|
|
stopEvent: function(e){
|
|
if(this.stopPropagation) {
|
|
e.stopPropagation();
|
|
}
|
|
|
|
if (this.preventDefault) {
|
|
e.preventDefault();
|
|
}
|
|
},
|
|
|
|
|
|
stopDrag: function(e) {
|
|
|
|
if (this.dragCurrent) {
|
|
if (this.dragThreshMet) {
|
|
this.dragCurrent.b4EndDrag(e);
|
|
this.dragCurrent.endDrag(e);
|
|
}
|
|
|
|
this.dragCurrent.onMouseUp(e);
|
|
}
|
|
|
|
this.dragCurrent = null;
|
|
this.dragOvers = {};
|
|
},
|
|
|
|
|
|
handleMouseMove: function(e) {
|
|
if (! this.dragCurrent) {
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
if (Ext.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
|
|
this.stopEvent(e);
|
|
return this.handleMouseUp(e);
|
|
}
|
|
|
|
if (!this.dragThreshMet) {
|
|
var diffX = Math.abs(this.startX - e.getPageX());
|
|
var diffY = Math.abs(this.startY - e.getPageY());
|
|
if (diffX > this.clickPixelThresh ||
|
|
diffY > this.clickPixelThresh) {
|
|
this.startDrag(this.startX, this.startY);
|
|
}
|
|
}
|
|
|
|
if (this.dragThreshMet) {
|
|
this.dragCurrent.b4Drag(e);
|
|
this.dragCurrent.onDrag(e);
|
|
if(!this.dragCurrent.moveOnly){
|
|
this.fireEvents(e, false);
|
|
}
|
|
}
|
|
|
|
this.stopEvent(e);
|
|
|
|
return true;
|
|
},
|
|
|
|
|
|
fireEvents: function(e, isDrop) {
|
|
var dc = this.dragCurrent;
|
|
|
|
|
|
|
|
if (!dc || dc.isLocked()) {
|
|
return;
|
|
}
|
|
|
|
var pt = e.getPoint();
|
|
|
|
|
|
var oldOvers = [];
|
|
|
|
var outEvts = [];
|
|
var overEvts = [];
|
|
var dropEvts = [];
|
|
var enterEvts = [];
|
|
|
|
|
|
|
|
for (var i in this.dragOvers) {
|
|
|
|
var ddo = this.dragOvers[i];
|
|
|
|
if (! this.isTypeOfDD(ddo)) {
|
|
continue;
|
|
}
|
|
|
|
if (! this.isOverTarget(pt, ddo, this.mode)) {
|
|
outEvts.push( ddo );
|
|
}
|
|
|
|
oldOvers[i] = true;
|
|
delete this.dragOvers[i];
|
|
}
|
|
|
|
for (var sGroup in dc.groups) {
|
|
|
|
if ("string" != typeof sGroup) {
|
|
continue;
|
|
}
|
|
|
|
for (i in this.ids[sGroup]) {
|
|
var oDD = this.ids[sGroup][i];
|
|
if (! this.isTypeOfDD(oDD)) {
|
|
continue;
|
|
}
|
|
|
|
if (oDD.isTarget && !oDD.isLocked() && ((oDD != dc) || (dc.ignoreSelf === false))) {
|
|
if (this.isOverTarget(pt, oDD, this.mode)) {
|
|
|
|
if (isDrop) {
|
|
dropEvts.push( oDD );
|
|
|
|
} else {
|
|
|
|
|
|
if (!oldOvers[oDD.id]) {
|
|
enterEvts.push( oDD );
|
|
|
|
} else {
|
|
overEvts.push( oDD );
|
|
}
|
|
|
|
this.dragOvers[oDD.id] = oDD;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.mode) {
|
|
if (outEvts.length) {
|
|
dc.b4DragOut(e, outEvts);
|
|
dc.onDragOut(e, outEvts);
|
|
}
|
|
|
|
if (enterEvts.length) {
|
|
dc.onDragEnter(e, enterEvts);
|
|
}
|
|
|
|
if (overEvts.length) {
|
|
dc.b4DragOver(e, overEvts);
|
|
dc.onDragOver(e, overEvts);
|
|
}
|
|
|
|
if (dropEvts.length) {
|
|
dc.b4DragDrop(e, dropEvts);
|
|
dc.onDragDrop(e, dropEvts);
|
|
}
|
|
|
|
} else {
|
|
|
|
var len = 0;
|
|
for (i=0, len=outEvts.length; i<len; ++i) {
|
|
dc.b4DragOut(e, outEvts[i].id);
|
|
dc.onDragOut(e, outEvts[i].id);
|
|
}
|
|
|
|
|
|
for (i=0,len=enterEvts.length; i<len; ++i) {
|
|
|
|
dc.onDragEnter(e, enterEvts[i].id);
|
|
}
|
|
|
|
|
|
for (i=0,len=overEvts.length; i<len; ++i) {
|
|
dc.b4DragOver(e, overEvts[i].id);
|
|
dc.onDragOver(e, overEvts[i].id);
|
|
}
|
|
|
|
|
|
for (i=0, len=dropEvts.length; i<len; ++i) {
|
|
dc.b4DragDrop(e, dropEvts[i].id);
|
|
dc.onDragDrop(e, dropEvts[i].id);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
if (isDrop && !dropEvts.length) {
|
|
dc.onInvalidDrop(e);
|
|
}
|
|
|
|
},
|
|
|
|
|
|
getBestMatch: function(dds) {
|
|
var winner = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var len = dds.length;
|
|
|
|
if (len == 1) {
|
|
winner = dds[0];
|
|
} else {
|
|
|
|
for (var i=0; i<len; ++i) {
|
|
var dd = dds[i];
|
|
|
|
|
|
|
|
if (dd.cursorIsOver) {
|
|
winner = dd;
|
|
break;
|
|
|
|
} else {
|
|
if (!winner ||
|
|
winner.overlap.getArea() < dd.overlap.getArea()) {
|
|
winner = dd;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return winner;
|
|
},
|
|
|
|
|
|
refreshCache: function(groups) {
|
|
for (var sGroup in groups) {
|
|
if ("string" != typeof sGroup) {
|
|
continue;
|
|
}
|
|
for (var i in this.ids[sGroup]) {
|
|
var oDD = this.ids[sGroup][i];
|
|
|
|
if (this.isTypeOfDD(oDD)) {
|
|
|
|
var loc = this.getLocation(oDD);
|
|
if (loc) {
|
|
this.locationCache[oDD.id] = loc;
|
|
} else {
|
|
delete this.locationCache[oDD.id];
|
|
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
verifyEl: function(el) {
|
|
if (el) {
|
|
var parent;
|
|
if(Ext.isIE){
|
|
try{
|
|
parent = el.offsetParent;
|
|
}catch(e){}
|
|
}else{
|
|
parent = el.offsetParent;
|
|
}
|
|
if (parent) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
|
|
getLocation: function(oDD) {
|
|
if (! this.isTypeOfDD(oDD)) {
|
|
return null;
|
|
}
|
|
|
|
|
|
|
|
if (oDD.getRegion) {
|
|
return oDD.getRegion();
|
|
}
|
|
|
|
var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
|
|
|
|
try {
|
|
pos= Ext.Element.getXY(el);
|
|
} catch (e) { }
|
|
|
|
if (!pos) {
|
|
return null;
|
|
}
|
|
|
|
x1 = pos[0];
|
|
x2 = x1 + el.offsetWidth;
|
|
y1 = pos[1];
|
|
y2 = y1 + el.offsetHeight;
|
|
|
|
t = y1 - oDD.padding[0];
|
|
r = x2 + oDD.padding[1];
|
|
b = y2 + oDD.padding[2];
|
|
l = x1 - oDD.padding[3];
|
|
|
|
return Ext.create('Ext.util.Region', t, r, b, l);
|
|
},
|
|
|
|
|
|
isOverTarget: function(pt, oTarget, intersect) {
|
|
|
|
var loc = this.locationCache[oTarget.id];
|
|
if (!loc || !this.useCache) {
|
|
loc = this.getLocation(oTarget);
|
|
this.locationCache[oTarget.id] = loc;
|
|
|
|
}
|
|
|
|
if (!loc) {
|
|
return false;
|
|
}
|
|
|
|
oTarget.cursorIsOver = loc.contains( pt );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var dc = this.dragCurrent;
|
|
if (!dc || !dc.getTargetCoord ||
|
|
(!intersect && !dc.constrainX && !dc.constrainY)) {
|
|
return oTarget.cursorIsOver;
|
|
}
|
|
|
|
oTarget.overlap = null;
|
|
|
|
|
|
|
|
|
|
|
|
var pos = dc.getTargetCoord(pt.x, pt.y);
|
|
|
|
var el = dc.getDragEl();
|
|
var curRegion = Ext.create('Ext.util.Region', pos.y,
|
|
pos.x + el.offsetWidth,
|
|
pos.y + el.offsetHeight,
|
|
pos.x );
|
|
|
|
var overlap = curRegion.intersect(loc);
|
|
|
|
if (overlap) {
|
|
oTarget.overlap = overlap;
|
|
return (intersect) ? true : oTarget.cursorIsOver;
|
|
} else {
|
|
return false;
|
|
}
|
|
},
|
|
|
|
|
|
_onUnload: function(e, me) {
|
|
Ext.dd.DragDropManager.unregAll();
|
|
},
|
|
|
|
|
|
unregAll: function() {
|
|
|
|
if (this.dragCurrent) {
|
|
this.stopDrag();
|
|
this.dragCurrent = null;
|
|
}
|
|
|
|
this._execOnAll("unreg", []);
|
|
|
|
for (var i in this.elementCache) {
|
|
delete this.elementCache[i];
|
|
}
|
|
|
|
this.elementCache = {};
|
|
this.ids = {};
|
|
},
|
|
|
|
|
|
elementCache: {},
|
|
|
|
|
|
getElWrapper: function(id) {
|
|
var oWrapper = this.elementCache[id];
|
|
if (!oWrapper || !oWrapper.el) {
|
|
oWrapper = this.elementCache[id] =
|
|
new this.ElementWrapper(Ext.getDom(id));
|
|
}
|
|
return oWrapper;
|
|
},
|
|
|
|
|
|
getElement: function(id) {
|
|
return Ext.getDom(id);
|
|
},
|
|
|
|
|
|
getCss: function(id) {
|
|
var el = Ext.getDom(id);
|
|
return (el) ? el.style : null;
|
|
},
|
|
|
|
|
|
ElementWrapper: function(el) {
|
|
|
|
this.el = el || null;
|
|
|
|
this.id = this.el && el.id;
|
|
|
|
this.css = this.el && el.style;
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getPosX: function(el) {
|
|
return Ext.Element.getX(el);
|
|
},
|
|
|
|
|
|
getPosY: function(el) {
|
|
return Ext.Element.getY(el);
|
|
},
|
|
|
|
|
|
swapNode: function(n1, n2) {
|
|
if (n1.swapNode) {
|
|
n1.swapNode(n2);
|
|
} else {
|
|
var p = n2.parentNode;
|
|
var s = n2.nextSibling;
|
|
|
|
if (s == n1) {
|
|
p.insertBefore(n1, n2);
|
|
} else if (n2 == n1.nextSibling) {
|
|
p.insertBefore(n2, n1);
|
|
} else {
|
|
n1.parentNode.replaceChild(n2, n1);
|
|
p.insertBefore(n1, s);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getScroll: function () {
|
|
var doc = window.document,
|
|
docEl = doc.documentElement,
|
|
body = doc.body,
|
|
top = 0,
|
|
left = 0;
|
|
|
|
if (Ext.isGecko4) {
|
|
top = window.scrollYOffset;
|
|
left = window.scrollXOffset;
|
|
} else {
|
|
if (docEl && (docEl.scrollTop || docEl.scrollLeft)) {
|
|
top = docEl.scrollTop;
|
|
left = docEl.scrollLeft;
|
|
} else if (body) {
|
|
top = body.scrollTop;
|
|
left = body.scrollLeft;
|
|
}
|
|
}
|
|
return {
|
|
top: top,
|
|
left: left
|
|
};
|
|
},
|
|
|
|
|
|
getStyle: function(el, styleProp) {
|
|
return Ext.fly(el).getStyle(styleProp);
|
|
},
|
|
|
|
|
|
getScrollTop: function () {
|
|
return this.getScroll().top;
|
|
},
|
|
|
|
|
|
getScrollLeft: function () {
|
|
return this.getScroll().left;
|
|
},
|
|
|
|
|
|
moveToEl: function (moveEl, targetEl) {
|
|
var aCoord = Ext.Element.getXY(targetEl);
|
|
Ext.Element.setXY(moveEl, aCoord);
|
|
},
|
|
|
|
|
|
numericSort: function(a, b) {
|
|
return (a - b);
|
|
},
|
|
|
|
|
|
_timeoutCount: 0,
|
|
|
|
|
|
_addListeners: function() {
|
|
if ( document ) {
|
|
this._onLoad();
|
|
} else {
|
|
if (this._timeoutCount > 2000) {
|
|
} else {
|
|
setTimeout(this._addListeners, 10);
|
|
if (document && document.body) {
|
|
this._timeoutCount += 1;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
handleWasClicked: function(node, id) {
|
|
if (this.isHandle(id, node.id)) {
|
|
return true;
|
|
} else {
|
|
|
|
var p = node.parentNode;
|
|
|
|
while (p) {
|
|
if (this.isHandle(id, p.id)) {
|
|
return true;
|
|
} else {
|
|
p = p.parentNode;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}, function() {
|
|
this._addListeners();
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.layout.container.Box', {
|
|
|
|
|
|
|
|
alias: ['layout.box'],
|
|
extend: 'Ext.layout.container.Container',
|
|
alternateClassName: 'Ext.layout.BoxLayout',
|
|
|
|
requires: [
|
|
'Ext.layout.container.boxOverflow.None',
|
|
'Ext.layout.container.boxOverflow.Menu',
|
|
'Ext.layout.container.boxOverflow.Scroller',
|
|
'Ext.util.Format',
|
|
'Ext.dd.DragDropManager'
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defaultMargins: {
|
|
top: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
left: 0
|
|
},
|
|
|
|
|
|
padding: '0',
|
|
|
|
pack: 'start',
|
|
|
|
|
|
|
|
|
|
type: 'box',
|
|
scrollOffset: 0,
|
|
itemCls: Ext.baseCSSPrefix + 'box-item',
|
|
targetCls: Ext.baseCSSPrefix + 'box-layout-ct',
|
|
innerCls: Ext.baseCSSPrefix + 'box-inner',
|
|
|
|
bindToOwnerCtContainer: true,
|
|
|
|
|
|
|
|
availableSpaceOffset: 0,
|
|
|
|
|
|
reserveOffset: true,
|
|
|
|
|
|
shrinkToFit: true,
|
|
|
|
|
|
clearInnerCtOnLayout: false,
|
|
|
|
flexSortFn: function (a, b) {
|
|
var maxParallelPrefix = 'max' + this.parallelPrefixCap,
|
|
infiniteValue = Infinity;
|
|
a = a.component[maxParallelPrefix] || infiniteValue;
|
|
b = b.component[maxParallelPrefix] || infiniteValue;
|
|
|
|
if (!isFinite(a) && !isFinite(b)) {
|
|
return false;
|
|
}
|
|
return a - b;
|
|
},
|
|
|
|
|
|
minSizeSortFn: function(a, b) {
|
|
return b.available - a.available;
|
|
},
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
me.flexSortFn = Ext.Function.bind(me.flexSortFn, me);
|
|
|
|
me.initOverflowHandler();
|
|
},
|
|
|
|
|
|
getChildBox: function(child) {
|
|
child = child.el || this.owner.getComponent(child).el;
|
|
var size = child.getBox(false, true);
|
|
return {
|
|
left: size.left,
|
|
top: size.top,
|
|
width: size.width,
|
|
height: size.height
|
|
};
|
|
},
|
|
|
|
|
|
calculateChildBox: function(child) {
|
|
var me = this,
|
|
boxes = me.calculateChildBoxes(me.getVisibleItems(), me.getLayoutTargetSize()).boxes,
|
|
ln = boxes.length,
|
|
i = 0;
|
|
|
|
child = me.owner.getComponent(child);
|
|
for (; i < ln; i++) {
|
|
if (boxes[i].component === child) {
|
|
return boxes[i];
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
calculateChildBoxes: function(visibleItems, targetSize) {
|
|
var me = this,
|
|
math = Math,
|
|
mmax = math.max,
|
|
infiniteValue = Infinity,
|
|
undefinedValue,
|
|
|
|
parallelPrefix = me.parallelPrefix,
|
|
parallelPrefixCap = me.parallelPrefixCap,
|
|
perpendicularPrefix = me.perpendicularPrefix,
|
|
perpendicularPrefixCap = me.perpendicularPrefixCap,
|
|
parallelMinString = 'min' + parallelPrefixCap,
|
|
perpendicularMinString = 'min' + perpendicularPrefixCap,
|
|
perpendicularMaxString = 'max' + perpendicularPrefixCap,
|
|
|
|
parallelSize = targetSize[parallelPrefix] - me.scrollOffset,
|
|
perpendicularSize = targetSize[perpendicularPrefix],
|
|
padding = me.padding,
|
|
parallelOffset = padding[me.parallelBefore],
|
|
paddingParallel = parallelOffset + padding[me.parallelAfter],
|
|
perpendicularOffset = padding[me.perpendicularLeftTop],
|
|
paddingPerpendicular = perpendicularOffset + padding[me.perpendicularRightBottom],
|
|
availPerpendicularSize = mmax(0, perpendicularSize - paddingPerpendicular),
|
|
|
|
innerCtBorderWidth = me.innerCt.getBorderWidth(me.perpendicularLT + me.perpendicularRB),
|
|
|
|
isStart = me.pack == 'start',
|
|
isCenter = me.pack == 'center',
|
|
isEnd = me.pack == 'end',
|
|
|
|
constrain = Ext.Number.constrain,
|
|
visibleCount = visibleItems.length,
|
|
nonFlexSize = 0,
|
|
totalFlex = 0,
|
|
desiredSize = 0,
|
|
minimumSize = 0,
|
|
maxSize = 0,
|
|
boxes = [],
|
|
minSizes = [],
|
|
calculatedWidth,
|
|
|
|
i, child, childParallel, childPerpendicular, childMargins, childSize, minParallel, tmpObj, shortfall,
|
|
tooNarrow, availableSpace, minSize, item, length, itemIndex, box, oldSize, newSize, reduction, diff,
|
|
flexedBoxes, remainingSpace, remainingFlex, flexedSize, parallelMargins, calcs, offset,
|
|
perpendicularMargins, stretchSize;
|
|
|
|
|
|
for (i = 0; i < visibleCount; i++) {
|
|
child = visibleItems[i];
|
|
childPerpendicular = child[perpendicularPrefix];
|
|
if (!child.flex || !(me.align == 'stretch' || me.align == 'stretchmax')) {
|
|
if (child.componentLayout.initialized !== true) {
|
|
me.layoutItem(child);
|
|
}
|
|
}
|
|
|
|
childMargins = child.margins;
|
|
parallelMargins = childMargins[me.parallelBefore] + childMargins[me.parallelAfter];
|
|
|
|
|
|
tmpObj = {
|
|
component: child,
|
|
margins: childMargins
|
|
};
|
|
|
|
|
|
if (child.flex) {
|
|
totalFlex += child.flex;
|
|
childParallel = undefinedValue;
|
|
}
|
|
|
|
else {
|
|
if (!(child[parallelPrefix] && childPerpendicular)) {
|
|
childSize = child.getSize();
|
|
}
|
|
childParallel = child[parallelPrefix] || childSize[parallelPrefix];
|
|
childPerpendicular = childPerpendicular || childSize[perpendicularPrefix];
|
|
}
|
|
|
|
nonFlexSize += parallelMargins + (childParallel || 0);
|
|
desiredSize += parallelMargins + (child.flex ? child[parallelMinString] || 0 : childParallel);
|
|
minimumSize += parallelMargins + (child[parallelMinString] || childParallel || 0);
|
|
|
|
|
|
if (typeof childPerpendicular != 'number') {
|
|
|
|
|
|
childPerpendicular = child['get' + perpendicularPrefixCap]();
|
|
}
|
|
|
|
|
|
|
|
maxSize = mmax(maxSize, mmax(childPerpendicular, child[perpendicularMinString]||0) + childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom]);
|
|
|
|
tmpObj[parallelPrefix] = childParallel || undefinedValue;
|
|
tmpObj.dirtySize = child.componentLayout.lastComponentSize ? (tmpObj[parallelPrefix] !== child.componentLayout.lastComponentSize[parallelPrefix]) : false;
|
|
tmpObj[perpendicularPrefix] = childPerpendicular || undefinedValue;
|
|
boxes.push(tmpObj);
|
|
}
|
|
|
|
|
|
if (!me.autoSize) {
|
|
shortfall = desiredSize - parallelSize;
|
|
tooNarrow = minimumSize > parallelSize;
|
|
}
|
|
|
|
|
|
availableSpace = mmax(0, parallelSize - nonFlexSize - paddingParallel - (me.reserveOffset ? me.availableSpaceOffset : 0));
|
|
|
|
if (tooNarrow) {
|
|
for (i = 0; i < visibleCount; i++) {
|
|
box = boxes[i];
|
|
minSize = visibleItems[i][parallelMinString] || visibleItems[i][parallelPrefix] || box[parallelPrefix];
|
|
box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
|
|
box[parallelPrefix] = minSize;
|
|
}
|
|
}
|
|
else {
|
|
|
|
|
|
if (shortfall > 0) {
|
|
|
|
for (i = 0; i < visibleCount; i++) {
|
|
item = visibleItems[i];
|
|
minSize = item[parallelMinString] || 0;
|
|
|
|
|
|
|
|
if (item.flex) {
|
|
box = boxes[i];
|
|
box.dirtySize = box.dirtySize || box[parallelPrefix] != minSize;
|
|
box[parallelPrefix] = minSize;
|
|
} else if (me.shrinkToFit) {
|
|
minSizes.push({
|
|
minSize: minSize,
|
|
available: boxes[i][parallelPrefix] - minSize,
|
|
index: i
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
Ext.Array.sort(minSizes, me.minSizeSortFn);
|
|
|
|
|
|
for (i = 0, length = minSizes.length; i < length; i++) {
|
|
itemIndex = minSizes[i].index;
|
|
|
|
if (itemIndex == undefinedValue) {
|
|
continue;
|
|
}
|
|
item = visibleItems[itemIndex];
|
|
minSize = minSizes[i].minSize;
|
|
|
|
box = boxes[itemIndex];
|
|
oldSize = box[parallelPrefix];
|
|
newSize = mmax(minSize, oldSize - math.ceil(shortfall / (length - i)));
|
|
reduction = oldSize - newSize;
|
|
|
|
box.dirtySize = box.dirtySize || box[parallelPrefix] != newSize;
|
|
box[parallelPrefix] = newSize;
|
|
shortfall -= reduction;
|
|
}
|
|
tooNarrow = (shortfall > 0);
|
|
}
|
|
else {
|
|
remainingSpace = availableSpace;
|
|
remainingFlex = totalFlex;
|
|
flexedBoxes = [];
|
|
|
|
|
|
for (i = 0; i < visibleCount; i++) {
|
|
child = visibleItems[i];
|
|
if (isStart && child.flex) {
|
|
flexedBoxes.push(boxes[Ext.Array.indexOf(visibleItems, child)]);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
Ext.Array.sort(flexedBoxes, me.flexSortFn);
|
|
|
|
|
|
for (i = 0; i < flexedBoxes.length; i++) {
|
|
calcs = flexedBoxes[i];
|
|
child = calcs.component;
|
|
childMargins = calcs.margins;
|
|
|
|
flexedSize = math.ceil((child.flex / remainingFlex) * remainingSpace);
|
|
|
|
|
|
flexedSize = Math.max(child['min' + parallelPrefixCap] || 0, math.min(child['max' + parallelPrefixCap] || infiniteValue, flexedSize));
|
|
|
|
|
|
remainingSpace -= flexedSize;
|
|
remainingFlex -= child.flex;
|
|
|
|
calcs.dirtySize = calcs.dirtySize || calcs[parallelPrefix] != flexedSize;
|
|
calcs[parallelPrefix] = flexedSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (isCenter) {
|
|
parallelOffset += availableSpace / 2;
|
|
}
|
|
else if (isEnd) {
|
|
parallelOffset += availableSpace;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (me.owner.dock && (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) && !me.owner.width && me.direction == 'vertical') {
|
|
|
|
calculatedWidth = maxSize + me.owner.el.getPadding('lr') + me.owner.el.getBorderWidth('lr');
|
|
if (me.owner.frameSize) {
|
|
calculatedWidth += me.owner.frameSize.left + me.owner.frameSize.right;
|
|
}
|
|
|
|
availPerpendicularSize = Math.min(availPerpendicularSize, targetSize.width = maxSize + padding.left + padding.right);
|
|
}
|
|
|
|
|
|
for (i = 0; i < visibleCount; i++) {
|
|
child = visibleItems[i];
|
|
calcs = boxes[i];
|
|
|
|
childMargins = calcs.margins;
|
|
|
|
perpendicularMargins = childMargins[me.perpendicularLeftTop] + childMargins[me.perpendicularRightBottom];
|
|
|
|
|
|
parallelOffset += childMargins[me.parallelBefore];
|
|
|
|
calcs[me.parallelBefore] = parallelOffset;
|
|
calcs[me.perpendicularLeftTop] = perpendicularOffset + childMargins[me.perpendicularLeftTop];
|
|
|
|
if (me.align == 'stretch') {
|
|
stretchSize = constrain(availPerpendicularSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
|
|
calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
|
|
calcs[perpendicularPrefix] = stretchSize;
|
|
}
|
|
else if (me.align == 'stretchmax') {
|
|
stretchSize = constrain(maxSize - perpendicularMargins, child[perpendicularMinString] || 0, child[perpendicularMaxString] || infiniteValue);
|
|
calcs.dirtySize = calcs.dirtySize || calcs[perpendicularPrefix] != stretchSize;
|
|
calcs[perpendicularPrefix] = stretchSize;
|
|
}
|
|
else if (me.align == me.alignCenteringString) {
|
|
|
|
|
|
|
|
diff = mmax(availPerpendicularSize, maxSize) - innerCtBorderWidth - calcs[perpendicularPrefix];
|
|
if (diff > 0) {
|
|
calcs[me.perpendicularLeftTop] = perpendicularOffset + Math.round(diff / 2);
|
|
}
|
|
}
|
|
|
|
|
|
parallelOffset += (calcs[parallelPrefix] || 0) + childMargins[me.parallelAfter];
|
|
}
|
|
|
|
return {
|
|
boxes: boxes,
|
|
meta : {
|
|
calculatedWidth: calculatedWidth,
|
|
maxSize: maxSize,
|
|
nonFlexSize: nonFlexSize,
|
|
desiredSize: desiredSize,
|
|
minimumSize: minimumSize,
|
|
shortfall: shortfall,
|
|
tooNarrow: tooNarrow
|
|
}
|
|
};
|
|
},
|
|
|
|
onRemove: function(comp){
|
|
this.callParent(arguments);
|
|
if (this.overflowHandler) {
|
|
this.overflowHandler.onRemove(comp);
|
|
}
|
|
},
|
|
|
|
|
|
initOverflowHandler: function() {
|
|
var handler = this.overflowHandler;
|
|
|
|
if (typeof handler == 'string') {
|
|
handler = {
|
|
type: handler
|
|
};
|
|
}
|
|
|
|
var handlerType = 'None';
|
|
if (handler && handler.type !== undefined) {
|
|
handlerType = handler.type;
|
|
}
|
|
|
|
var constructor = Ext.layout.container.boxOverflow[handlerType];
|
|
if (constructor[this.type]) {
|
|
constructor = constructor[this.type];
|
|
}
|
|
|
|
this.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.' + handlerType, this, handler);
|
|
},
|
|
|
|
|
|
onLayout: function() {
|
|
this.callParent();
|
|
|
|
if (this.clearInnerCtOnLayout === true && this.adjustmentPass !== true) {
|
|
this.innerCt.setSize(null, null);
|
|
}
|
|
|
|
var me = this,
|
|
targetSize = me.getLayoutTargetSize(),
|
|
items = me.getVisibleItems(),
|
|
calcs = me.calculateChildBoxes(items, targetSize),
|
|
boxes = calcs.boxes,
|
|
meta = calcs.meta,
|
|
handler, method, results;
|
|
|
|
if (me.autoSize && calcs.meta.desiredSize) {
|
|
targetSize[me.parallelPrefix] = calcs.meta.desiredSize;
|
|
}
|
|
|
|
|
|
if (meta.shortfall > 0) {
|
|
handler = me.overflowHandler;
|
|
method = meta.tooNarrow ? 'handleOverflow': 'clearOverflow';
|
|
|
|
results = handler[method](calcs, targetSize);
|
|
|
|
if (results) {
|
|
if (results.targetSize) {
|
|
targetSize = results.targetSize;
|
|
}
|
|
|
|
if (results.recalculate) {
|
|
items = me.getVisibleItems();
|
|
calcs = me.calculateChildBoxes(items, targetSize);
|
|
boxes = calcs.boxes;
|
|
}
|
|
}
|
|
} else {
|
|
me.overflowHandler.clearOverflow();
|
|
}
|
|
|
|
|
|
me.layoutTargetLastSize = targetSize;
|
|
|
|
|
|
me.childBoxCache = calcs;
|
|
|
|
me.updateInnerCtSize(targetSize, calcs);
|
|
me.updateChildBoxes(boxes);
|
|
me.handleTargetOverflow(targetSize);
|
|
},
|
|
|
|
animCallback: Ext.emptyFn,
|
|
|
|
|
|
updateChildBoxes: function(boxes) {
|
|
var me = this,
|
|
i = 0,
|
|
length = boxes.length,
|
|
animQueue = [],
|
|
dd = Ext.dd.DDM.getDDById(me.innerCt.id),
|
|
oldBox, newBox, changed, comp, boxAnim, animCallback;
|
|
|
|
for (; i < length; i++) {
|
|
newBox = boxes[i];
|
|
comp = newBox.component;
|
|
|
|
|
|
|
|
if (dd && (dd.getDragEl() === comp.el.dom)) {
|
|
continue;
|
|
}
|
|
|
|
changed = false;
|
|
|
|
oldBox = me.getChildBox(comp);
|
|
|
|
|
|
|
|
|
|
if (me.animate) {
|
|
|
|
animCallback = me.animate.callback || me.animate;
|
|
boxAnim = {
|
|
layoutAnimation: true,
|
|
target: comp,
|
|
from: {},
|
|
to: {},
|
|
listeners: {}
|
|
};
|
|
|
|
|
|
|
|
|
|
if (!isNaN(newBox.width) && (newBox.width != oldBox.width)) {
|
|
changed = true;
|
|
|
|
boxAnim.to.width = newBox.width;
|
|
}
|
|
if (!isNaN(newBox.height) && (newBox.height != oldBox.height)) {
|
|
changed = true;
|
|
|
|
boxAnim.to.height = newBox.height;
|
|
}
|
|
if (!isNaN(newBox.left) && (newBox.left != oldBox.left)) {
|
|
changed = true;
|
|
|
|
boxAnim.to.left = newBox.left;
|
|
}
|
|
if (!isNaN(newBox.top) && (newBox.top != oldBox.top)) {
|
|
changed = true;
|
|
|
|
boxAnim.to.top = newBox.top;
|
|
}
|
|
if (changed) {
|
|
animQueue.push(boxAnim);
|
|
}
|
|
} else {
|
|
if (newBox.dirtySize) {
|
|
if (newBox.width !== oldBox.width || newBox.height !== oldBox.height) {
|
|
me.setItemSize(comp, newBox.width, newBox.height);
|
|
}
|
|
}
|
|
|
|
if (isNaN(newBox.left) || isNaN(newBox.top)) {
|
|
continue;
|
|
}
|
|
comp.setPosition(newBox.left, newBox.top);
|
|
}
|
|
}
|
|
|
|
|
|
length = animQueue.length;
|
|
if (length) {
|
|
|
|
|
|
|
|
var afterAnimate = function(anim) {
|
|
|
|
length -= 1;
|
|
if (!length) {
|
|
me.animCallback(anim);
|
|
me.layoutBusy = false;
|
|
if (Ext.isFunction(animCallback)) {
|
|
animCallback();
|
|
}
|
|
}
|
|
};
|
|
|
|
var beforeAnimate = function() {
|
|
me.layoutBusy = true;
|
|
};
|
|
|
|
|
|
for (i = 0, length = animQueue.length; i < length; i++) {
|
|
boxAnim = animQueue[i];
|
|
|
|
|
|
boxAnim.listeners.afteranimate = afterAnimate;
|
|
|
|
|
|
if (!i) {
|
|
boxAnim.listeners.beforeanimate = beforeAnimate;
|
|
}
|
|
if (me.animate.duration) {
|
|
boxAnim.duration = me.animate.duration;
|
|
}
|
|
comp = boxAnim.target;
|
|
delete boxAnim.target;
|
|
|
|
comp.stopAnimation();
|
|
comp.animate(boxAnim);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
updateInnerCtSize: function(tSize, calcs) {
|
|
var me = this,
|
|
mmax = Math.max,
|
|
align = me.align,
|
|
padding = me.padding,
|
|
width = tSize.width,
|
|
height = tSize.height,
|
|
meta = calcs.meta,
|
|
innerCtWidth,
|
|
innerCtHeight;
|
|
|
|
if (me.direction == 'horizontal') {
|
|
innerCtWidth = width;
|
|
innerCtHeight = meta.maxSize + padding.top + padding.bottom + me.innerCt.getBorderWidth('tb');
|
|
|
|
if (align == 'stretch') {
|
|
innerCtHeight = height;
|
|
}
|
|
else if (align == 'middle') {
|
|
innerCtHeight = mmax(height, innerCtHeight);
|
|
}
|
|
} else {
|
|
innerCtHeight = height;
|
|
innerCtWidth = meta.maxSize + padding.left + padding.right + me.innerCt.getBorderWidth('lr');
|
|
|
|
if (align == 'stretch') {
|
|
innerCtWidth = width;
|
|
}
|
|
else if (align == 'center') {
|
|
innerCtWidth = mmax(width, innerCtWidth);
|
|
}
|
|
}
|
|
me.getRenderTarget().setSize(innerCtWidth || undefined, innerCtHeight || undefined);
|
|
|
|
|
|
|
|
if (meta.calculatedWidth && me.owner.el.getWidth() > meta.calculatedWidth) {
|
|
me.owner.el.setWidth(meta.calculatedWidth);
|
|
}
|
|
|
|
if (me.innerCt.dom.scrollTop) {
|
|
me.innerCt.dom.scrollTop = 0;
|
|
}
|
|
},
|
|
|
|
|
|
handleTargetOverflow: function(previousTargetSize) {
|
|
var target = this.getTarget(),
|
|
overflow = target.getStyle('overflow'),
|
|
newTargetSize;
|
|
|
|
if (overflow && overflow != 'hidden' && !this.adjustmentPass) {
|
|
newTargetSize = this.getLayoutTargetSize();
|
|
if (newTargetSize.width != previousTargetSize.width || newTargetSize.height != previousTargetSize.height) {
|
|
this.adjustmentPass = true;
|
|
this.onLayout();
|
|
return true;
|
|
}
|
|
}
|
|
|
|
delete this.adjustmentPass;
|
|
},
|
|
|
|
|
|
isValidParent : function(item, target, position) {
|
|
|
|
|
|
var itemEl = item.el ? item.el.dom : Ext.getDom(item);
|
|
return (itemEl && this.innerCt && itemEl.parentNode === this.innerCt.dom) || false;
|
|
},
|
|
|
|
|
|
|
|
getRenderTarget: function() {
|
|
if (!this.innerCt) {
|
|
|
|
this.innerCt = this.getTarget().createChild({
|
|
cls: this.innerCls,
|
|
role: 'presentation'
|
|
});
|
|
this.padding = Ext.util.Format.parseBox(this.padding);
|
|
}
|
|
return this.innerCt;
|
|
},
|
|
|
|
|
|
renderItem: function(item, target) {
|
|
this.callParent(arguments);
|
|
var me = this,
|
|
itemEl = item.getEl(),
|
|
style = itemEl.dom.style,
|
|
margins = item.margins || item.margin;
|
|
|
|
|
|
if (margins) {
|
|
if (Ext.isString(margins) || Ext.isNumber(margins)) {
|
|
margins = Ext.util.Format.parseBox(margins);
|
|
} else {
|
|
Ext.applyIf(margins, {top: 0, right: 0, bottom: 0, left: 0});
|
|
}
|
|
} else {
|
|
margins = Ext.apply({}, me.defaultMargins);
|
|
}
|
|
|
|
|
|
margins.top += itemEl.getMargin('t');
|
|
margins.right += itemEl.getMargin('r');
|
|
margins.bottom += itemEl.getMargin('b');
|
|
margins.left += itemEl.getMargin('l');
|
|
margins.height = margins.top + margins.bottom;
|
|
margins.width = margins.left + margins.right;
|
|
style.marginTop = style.marginRight = style.marginBottom = style.marginLeft = '0';
|
|
|
|
|
|
item.margins = margins;
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
Ext.destroy(this.innerCt, this.overflowHandler);
|
|
this.callParent(arguments);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.layout.container.HBox', {
|
|
|
|
|
|
|
|
alias: ['layout.hbox'],
|
|
extend: 'Ext.layout.container.Box',
|
|
alternateClassName: 'Ext.layout.HBoxLayout',
|
|
|
|
|
|
|
|
|
|
align: 'top',
|
|
|
|
//@private
|
|
|
|
alignCenteringString: 'middle',
|
|
|
|
type : 'hbox',
|
|
|
|
direction: 'horizontal',
|
|
|
|
|
|
parallelSizeIndex: 0,
|
|
perpendicularSizeIndex: 1,
|
|
|
|
parallelPrefix: 'width',
|
|
parallelPrefixCap: 'Width',
|
|
parallelLT: 'l',
|
|
parallelRB: 'r',
|
|
parallelBefore: 'left',
|
|
parallelBeforeCap: 'Left',
|
|
parallelAfter: 'right',
|
|
parallelPosition: 'x',
|
|
|
|
perpendicularPrefix: 'height',
|
|
perpendicularPrefixCap: 'Height',
|
|
perpendicularLT: 't',
|
|
perpendicularRB: 'b',
|
|
perpendicularLeftTop: 'top',
|
|
perpendicularRightBottom: 'bottom',
|
|
perpendicularPosition: 'y',
|
|
configureItem: function(item) {
|
|
if (item.flex) {
|
|
item.layoutManagedWidth = 1;
|
|
} else {
|
|
item.layoutManagedWidth = 2;
|
|
}
|
|
|
|
if (this.align === 'stretch' || this.align === 'stretchmax') {
|
|
item.layoutManagedHeight = 1;
|
|
} else {
|
|
item.layoutManagedHeight = 2;
|
|
}
|
|
this.callParent(arguments);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.layout.container.VBox', {
|
|
|
|
|
|
|
|
alias: ['layout.vbox'],
|
|
extend: 'Ext.layout.container.Box',
|
|
alternateClassName: 'Ext.layout.VBoxLayout',
|
|
|
|
|
|
|
|
|
|
align : 'left',
|
|
|
|
//@private
|
|
|
|
alignCenteringString: 'center',
|
|
|
|
type: 'vbox',
|
|
|
|
direction: 'vertical',
|
|
|
|
|
|
parallelSizeIndex: 1,
|
|
perpendicularSizeIndex: 0,
|
|
|
|
parallelPrefix: 'height',
|
|
parallelPrefixCap: 'Height',
|
|
parallelLT: 't',
|
|
parallelRB: 'b',
|
|
parallelBefore: 'top',
|
|
parallelBeforeCap: 'Top',
|
|
parallelAfter: 'bottom',
|
|
parallelPosition: 'y',
|
|
|
|
perpendicularPrefix: 'width',
|
|
perpendicularPrefixCap: 'Width',
|
|
perpendicularLT: 'l',
|
|
perpendicularRB: 'r',
|
|
perpendicularLeftTop: 'left',
|
|
perpendicularRightBottom: 'right',
|
|
perpendicularPosition: 'x',
|
|
configureItem: function(item) {
|
|
if (item.flex) {
|
|
item.layoutManagedHeight = 1;
|
|
} else {
|
|
item.layoutManagedHeight = 2;
|
|
}
|
|
|
|
if (this.align === 'stretch' || this.align === 'stretchmax') {
|
|
item.layoutManagedWidth = 1;
|
|
} else {
|
|
item.layoutManagedWidth = 2;
|
|
}
|
|
this.callParent(arguments);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.FocusManager', {
|
|
singleton: true,
|
|
alternateClassName: 'Ext.FocusMgr',
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
requires: [
|
|
'Ext.ComponentManager',
|
|
'Ext.ComponentQuery',
|
|
'Ext.util.HashMap',
|
|
'Ext.util.KeyNav'
|
|
],
|
|
|
|
|
|
enabled: false,
|
|
|
|
|
|
|
|
focusElementCls: Ext.baseCSSPrefix + 'focus-element',
|
|
|
|
focusFrameCls: Ext.baseCSSPrefix + 'focus-frame',
|
|
|
|
|
|
whitelist: [
|
|
'textfield'
|
|
],
|
|
|
|
tabIndexWhitelist: [
|
|
'a',
|
|
'button',
|
|
'embed',
|
|
'frame',
|
|
'iframe',
|
|
'img',
|
|
'input',
|
|
'object',
|
|
'select',
|
|
'textarea'
|
|
],
|
|
|
|
constructor: function() {
|
|
var me = this,
|
|
CQ = Ext.ComponentQuery;
|
|
|
|
me.addEvents(
|
|
|
|
'beforecomponentfocus',
|
|
|
|
|
|
'componentfocus',
|
|
|
|
|
|
'disable',
|
|
|
|
|
|
'enable'
|
|
);
|
|
|
|
|
|
|
|
me.keyNav = Ext.create('Ext.util.KeyNav', Ext.getDoc(), {
|
|
disabled: true,
|
|
scope: me,
|
|
|
|
backspace: me.focusLast,
|
|
enter: me.navigateIn,
|
|
esc: me.navigateOut,
|
|
tab: me.navigateSiblings
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
me.focusData = {};
|
|
me.subscribers = Ext.create('Ext.util.HashMap');
|
|
me.focusChain = {};
|
|
|
|
|
|
Ext.apply(CQ.pseudos, {
|
|
focusable: function(cmps) {
|
|
var len = cmps.length,
|
|
results = [],
|
|
i = 0,
|
|
c,
|
|
|
|
isFocusable = function(x) {
|
|
return x && x.focusable !== false && CQ.is(x, '[rendered]:not([destroying]):not([isDestroyed]):not([disabled]){isVisible(true)}{el && c.el.dom && c.el.isVisible()}');
|
|
};
|
|
|
|
for (; i < len; i++) {
|
|
c = cmps[i];
|
|
if (isFocusable(c)) {
|
|
results.push(c);
|
|
}
|
|
}
|
|
|
|
return results;
|
|
},
|
|
|
|
nextFocus: function(cmps, idx, step) {
|
|
step = step || 1;
|
|
idx = parseInt(idx, 10);
|
|
|
|
var len = cmps.length,
|
|
i = idx + step,
|
|
c;
|
|
|
|
for (; i != idx; i += step) {
|
|
if (i >= len) {
|
|
i = 0;
|
|
} else if (i < 0) {
|
|
i = len - 1;
|
|
}
|
|
|
|
c = cmps[i];
|
|
if (CQ.is(c, ':focusable')) {
|
|
return [c];
|
|
} else if (c.placeholder && CQ.is(c.placeholder, ':focusable')) {
|
|
return [c.placeholder];
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
Ext.ComponentManager.all.un('add', me.onComponentCreated, me);
|
|
|
|
me.removeDOM();
|
|
|
|
|
|
me.keyNav.disable();
|
|
|
|
|
|
me.setFocusAll(false);
|
|
|
|
me.fireEvent('disable', me);
|
|
},
|
|
|
|
|
|
enable: function(options) {
|
|
var me = this;
|
|
|
|
if (options === true) {
|
|
options = { focusFrame: true };
|
|
}
|
|
me.options = options = options || {};
|
|
|
|
if (me.enabled) {
|
|
return;
|
|
}
|
|
|
|
|
|
Ext.ComponentManager.all.on('add', me.onComponentCreated, me);
|
|
|
|
me.initDOM(options);
|
|
|
|
|
|
me.keyNav.enable();
|
|
|
|
|
|
me.setFocusAll(true, options);
|
|
|
|
|
|
me.focusEl.focus();
|
|
delete me.focusedCmp;
|
|
|
|
me.enabled = true;
|
|
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 me = this,
|
|
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,
|
|
sp = ' ',
|
|
cls = me.focusFrameCls;
|
|
|
|
if (!Ext.isReady) {
|
|
Ext.onReady(me.initDOM, me);
|
|
return;
|
|
}
|
|
|
|
|
|
if (!me.focusEl) {
|
|
me.focusEl = Ext.getBody().createChild({
|
|
tabIndex: '-1',
|
|
cls: me.focusElementCls,
|
|
html: sp
|
|
});
|
|
}
|
|
|
|
|
|
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.focusFrameWidth = 2;
|
|
me.focusFrame.hide().setLeftTop(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,
|
|
rootCmps,
|
|
firstChild;
|
|
|
|
if (!focusedCmp) {
|
|
|
|
rootCmps = me.getRootComponents();
|
|
if (rootCmps.length) {
|
|
rootCmps[0].focus();
|
|
}
|
|
} else {
|
|
|
|
|
|
firstChild = Ext.ComponentQuery.query('>:focusable', focusedCmp)[0];
|
|
if (firstChild) {
|
|
firstChild.focus();
|
|
} else {
|
|
|
|
if (Ext.isFunction(focusedCmp.onClick)) {
|
|
e.button = 0;
|
|
focusedCmp.onClick(e);
|
|
focusedCmp.focus();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
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;
|
|
|
|
focusedCmp = (src.focusedCmp && src.focusedCmp.comp) || src.focusedCmp;
|
|
if (!focusedCmp && !parent) {
|
|
return;
|
|
}
|
|
|
|
if (checkWhitelist && me.isWhitelisted(focusedCmp)) {
|
|
return true;
|
|
}
|
|
|
|
parent = parent || focusedCmp.up();
|
|
if (parent) {
|
|
idx = focusedCmp ? Ext.Array.indexOf(parent.getRefItems(), focusedCmp) : -1;
|
|
next = Ext.ComponentQuery.query('>:' + nextSelector + 'Focus(' + idx + ')', parent)[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();
|
|
}
|
|
},
|
|
|
|
onComponentCreated: function(hash, id, cmp) {
|
|
this.setFocus(cmp, true, this.options);
|
|
},
|
|
|
|
onComponentDestroy: function(cmp) {
|
|
this.setFocus(cmp, false);
|
|
},
|
|
|
|
onComponentFocus: function(cmp, e) {
|
|
var me = this,
|
|
chain = me.focusChain;
|
|
|
|
if (!Ext.ComponentQuery.is(cmp, ':focusable')) {
|
|
me.clearComponent(cmp);
|
|
|
|
|
|
|
|
|
|
|
|
if (chain[cmp.id]) {
|
|
return;
|
|
}
|
|
|
|
|
|
var parent = cmp.up();
|
|
if (parent) {
|
|
|
|
|
|
|
|
chain[cmp.id] = true;
|
|
parent.focus();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
me.focusChain = {};
|
|
|
|
|
|
|
|
clearTimeout(me.cmpFocusDelay);
|
|
if (arguments.length !== 2) {
|
|
me.cmpFocusDelay = Ext.defer(me.onComponentFocus, 90, me, [cmp, e]);
|
|
return;
|
|
}
|
|
|
|
if (me.fireEvent('beforecomponentfocus', me, cmp, me.previousFocusedCmp) === false) {
|
|
me.clearComponent(cmp);
|
|
return;
|
|
}
|
|
|
|
me.focusedCmp = cmp;
|
|
|
|
|
|
if (me.shouldShowFocusFrame(cmp)) {
|
|
var cls = '.' + me.focusFrameCls + '-',
|
|
ff = me.focusFrame,
|
|
fw = me.focusFrameWidth,
|
|
box = cmp.el.getPageBox(),
|
|
|
|
|
|
|
|
|
|
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).setLeftTop(bl, bt);
|
|
fb.setWidth(bw).setLeftTop(bl, bt + bh - fw);
|
|
fl.setHeight(bh - fw - fw).setLeftTop(bl, bt + fw);
|
|
fr.setHeight(bh - fw - fw).setLeftTop(bl + bw - fw, bt + fw);
|
|
|
|
ff.show();
|
|
}
|
|
|
|
me.fireEvent('componentfocus', me, cmp, me.previousFocusedCmp);
|
|
},
|
|
|
|
onComponentHide: function(cmp) {
|
|
var me = this,
|
|
CQ = Ext.ComponentQuery,
|
|
cmpHadFocus = false,
|
|
focusedCmp,
|
|
parent;
|
|
|
|
if (me.focusedCmp) {
|
|
focusedCmp = CQ.query('[id=' + me.focusedCmp.id + ']', cmp)[0];
|
|
cmpHadFocus = me.focusedCmp.id === cmp.id || focusedCmp;
|
|
|
|
if (focusedCmp) {
|
|
me.clearComponent(focusedCmp);
|
|
}
|
|
}
|
|
|
|
me.clearComponent(cmp);
|
|
|
|
if (cmpHadFocus) {
|
|
parent = CQ.query('^:focusable', cmp)[0];
|
|
if (parent) {
|
|
parent.focus();
|
|
}
|
|
}
|
|
},
|
|
|
|
removeDOM: function() {
|
|
var me = this;
|
|
|
|
|
|
|
|
if (me.enabled || me.subscribers.length) {
|
|
return;
|
|
}
|
|
|
|
Ext.destroy(
|
|
me.focusEl,
|
|
me.focusFrame
|
|
);
|
|
delete me.focusEl;
|
|
delete me.focusFrame;
|
|
delete me.focusFrameWidth;
|
|
},
|
|
|
|
|
|
removeXTypeFromWhitelist: function(xtype) {
|
|
var me = this;
|
|
|
|
if (Ext.isArray(xtype)) {
|
|
Ext.Array.forEach(xtype, me.removeXTypeFromWhitelist, me);
|
|
return;
|
|
}
|
|
|
|
Ext.Array.remove(me.whitelist, xtype);
|
|
},
|
|
|
|
setFocus: function(cmp, focusable, options) {
|
|
var me = this,
|
|
el, dom, data,
|
|
|
|
needsTabIndex = function(n) {
|
|
return !Ext.Array.contains(me.tabIndexWhitelist, n.tagName.toLowerCase())
|
|
&& n.tabIndex <= 0;
|
|
};
|
|
|
|
options = options || {};
|
|
|
|
|
|
if (!cmp.rendered) {
|
|
cmp.on('afterrender', Ext.pass(me.setFocus, arguments, me), me, { single: true });
|
|
return;
|
|
}
|
|
|
|
el = cmp.getFocusEl();
|
|
dom = el.dom;
|
|
|
|
|
|
if ((focusable && !me.focusData[cmp.id]) || (!focusable && me.focusData[cmp.id])) {
|
|
if (focusable) {
|
|
data = {
|
|
focusFrame: options.focusFrame
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (needsTabIndex(dom)) {
|
|
data.tabIndex = dom.tabIndex;
|
|
dom.tabIndex = -1;
|
|
}
|
|
|
|
el.on({
|
|
focus: data.focusFn = Ext.bind(me.onComponentFocus, me, [cmp], 0),
|
|
blur: data.blurFn = Ext.bind(me.onComponentBlur, me, [cmp], 0),
|
|
scope: me
|
|
});
|
|
cmp.on({
|
|
hide: me.onComponentHide,
|
|
close: me.onComponentHide,
|
|
beforedestroy: me.onComponentDestroy,
|
|
scope: me
|
|
});
|
|
|
|
me.focusData[cmp.id] = data;
|
|
} else {
|
|
data = me.focusData[cmp.id];
|
|
if ('tabIndex' in data) {
|
|
dom.tabIndex = data.tabIndex;
|
|
}
|
|
el.un('focus', data.focusFn, me);
|
|
el.un('blur', data.blurFn, me);
|
|
cmp.un('hide', me.onComponentHide, me);
|
|
cmp.un('close', me.onComponentHide, me);
|
|
cmp.un('beforedestroy', me.onComponentDestroy, me);
|
|
|
|
delete me.focusData[cmp.id];
|
|
}
|
|
}
|
|
},
|
|
|
|
setFocusAll: function(focusable, options) {
|
|
var me = this,
|
|
cmps = Ext.ComponentManager.all.getArray(),
|
|
len = cmps.length,
|
|
cmp,
|
|
i = 0;
|
|
|
|
for (; i < len; i++) {
|
|
me.setFocus(cmps[i], focusable, options);
|
|
}
|
|
},
|
|
|
|
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 Ext.create('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;
|
|
},
|
|
|
|
|
|
subscribe: function(container, options) {
|
|
var me = this,
|
|
EA = Ext.Array,
|
|
data = {},
|
|
subs = me.subscribers,
|
|
|
|
|
|
|
|
|
|
safeSetFocus = function(cmp) {
|
|
if (cmp.isContainer && !subs.containsKey(cmp.id)) {
|
|
EA.forEach(cmp.query('>'), safeSetFocus);
|
|
me.setFocus(cmp, true, options);
|
|
cmp.on('add', data.onAdd, me);
|
|
} else if (!cmp.isContainer) {
|
|
me.setFocus(cmp, true, options);
|
|
}
|
|
};
|
|
|
|
|
|
if (!container || !container.isContainer) {
|
|
return;
|
|
}
|
|
|
|
if (!container.rendered) {
|
|
container.on('afterrender', Ext.pass(me.subscribe, arguments, me), me, { single: true });
|
|
return;
|
|
}
|
|
|
|
|
|
me.initDOM(options);
|
|
|
|
|
|
data.keyNav = me.setupSubscriberKeys(container, options.keys);
|
|
|
|
|
|
|
|
|
|
|
|
data.onAdd = function(ct, cmp, idx) {
|
|
safeSetFocus(cmp);
|
|
};
|
|
container.on('beforedestroy', me.unsubscribe, me);
|
|
|
|
|
|
safeSetFocus(container);
|
|
|
|
|
|
subs.add(container.id, data);
|
|
},
|
|
|
|
|
|
unsubscribe: function(container) {
|
|
var me = this,
|
|
EA = Ext.Array,
|
|
subs = me.subscribers,
|
|
data,
|
|
|
|
|
|
|
|
|
|
safeSetFocus = function(cmp) {
|
|
if (cmp.isContainer && !subs.containsKey(cmp.id)) {
|
|
EA.forEach(cmp.query('>'), safeSetFocus);
|
|
me.setFocus(cmp, false);
|
|
cmp.un('add', data.onAdd, me);
|
|
} else if (!cmp.isContainer) {
|
|
me.setFocus(cmp, false);
|
|
}
|
|
};
|
|
|
|
if (!container || !subs.containsKey(container.id)) {
|
|
return;
|
|
}
|
|
|
|
data = subs.get(container.id);
|
|
data.keyNav.destroy();
|
|
container.un('beforedestroy', me.unsubscribe, me);
|
|
subs.removeAtKey(container.id);
|
|
safeSetFocus(container);
|
|
me.removeDOM();
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.toolbar.Toolbar', {
|
|
extend: 'Ext.container.Container',
|
|
requires: [
|
|
'Ext.toolbar.Fill',
|
|
'Ext.layout.container.HBox',
|
|
'Ext.layout.container.VBox',
|
|
'Ext.FocusManager'
|
|
],
|
|
uses: [
|
|
'Ext.toolbar.Separator'
|
|
],
|
|
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',
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
keys;
|
|
|
|
|
|
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',
|
|
clearInnerCtOnLayout: true
|
|
});
|
|
|
|
if (me.vertical) {
|
|
me.addClsWithUI('vertical');
|
|
}
|
|
|
|
|
|
if (me.ui === 'footer') {
|
|
me.ignoreBorderManagement = true;
|
|
}
|
|
|
|
me.callParent();
|
|
|
|
|
|
me.addEvents('overflowchange');
|
|
|
|
|
|
keys = me.vertical ? ['up', 'down'] : ['left', 'right'];
|
|
Ext.FocusManager.subscribe(me, {
|
|
keys: keys
|
|
});
|
|
},
|
|
|
|
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) {
|
|
if (Ext.isString(c)) {
|
|
var shortcut = Ext.toolbar.Toolbar.shortcuts[c];
|
|
if (shortcut) {
|
|
c = {
|
|
xtype: shortcut
|
|
};
|
|
} else {
|
|
c = {
|
|
xtype: 'tbtext',
|
|
text: c
|
|
};
|
|
}
|
|
this.applyDefaults(c);
|
|
}
|
|
return this.callParent(arguments);
|
|
},
|
|
|
|
|
|
applyDefaults: function(c) {
|
|
if (!Ext.isString(c)) {
|
|
c = this.callParent(arguments);
|
|
var d = this.internalDefaults;
|
|
if (c.events) {
|
|
Ext.applyIf(c.initialConfig, d);
|
|
Ext.apply(c, d);
|
|
} else {
|
|
Ext.applyIf(c, d);
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
},
|
|
|
|
|
|
constructButton: function(item) {
|
|
return item.events ? item : this.createComponent(item, item.split ? 'splitbutton' : this.defaultType);
|
|
},
|
|
|
|
|
|
onBeforeAdd: function(component) {
|
|
if (component.is('field') || (component.is('button') && this.ui != 'footer')) {
|
|
component.ui = component.ui + '-toolbar';
|
|
}
|
|
|
|
|
|
if (component instanceof Ext.toolbar.Separator) {
|
|
component.setUI((this.vertical) ? 'vertical' : 'horizontal');
|
|
}
|
|
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
onAdd: function(component) {
|
|
this.callParent(arguments);
|
|
|
|
this.trackMenu(component);
|
|
if (this.disabled) {
|
|
component.disable();
|
|
}
|
|
},
|
|
|
|
|
|
onRemove: function(c) {
|
|
this.callParent(arguments);
|
|
this.trackMenu(c, true);
|
|
},
|
|
|
|
|
|
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;
|
|
}
|
|
}, function() {
|
|
this.shortcuts = {
|
|
'-' : 'tbseparator',
|
|
' ' : 'tbspacer',
|
|
'->': 'tbfill'
|
|
};
|
|
});
|
|
|
|
Ext.define('Ext.panel.AbstractPanel', {
|
|
|
|
|
|
|
|
extend: 'Ext.container.Container',
|
|
|
|
requires: ['Ext.util.MixedCollection', 'Ext.Element', 'Ext.toolbar.Toolbar'],
|
|
|
|
|
|
|
|
|
|
baseCls : Ext.baseCSSPrefix + 'panel',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isPanel: true,
|
|
|
|
componentLayout: 'dock',
|
|
|
|
|
|
defaultDockWeights: { top: 1, left: 3, right: 5, bottom: 7 },
|
|
|
|
renderTpl: [
|
|
'<div id="{id}-body" class="{baseCls}-body<tpl if="bodyCls"> {bodyCls}</tpl>',
|
|
' {baseCls}-body-{ui}<tpl if="uiCls">',
|
|
'<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl>',
|
|
'</tpl>"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>>',
|
|
'</div>'
|
|
],
|
|
|
|
|
|
|
|
|
|
border: true,
|
|
|
|
initComponent : function() {
|
|
var me = this;
|
|
|
|
me.addEvents(
|
|
|
|
'bodyresize'
|
|
|
|
|
|
|
|
|
|
);
|
|
|
|
me.addChildEls('body');
|
|
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
me.callParent();
|
|
},
|
|
|
|
|
|
initItems : function() {
|
|
var me = this,
|
|
items = me.dockedItems;
|
|
|
|
me.callParent();
|
|
me.dockedItems = Ext.create('Ext.util.MixedCollection', false, me.getComponentId);
|
|
if (items) {
|
|
me.addDocked(items);
|
|
}
|
|
},
|
|
|
|
|
|
getDockedComponent: function(comp) {
|
|
if (Ext.isObject(comp)) {
|
|
comp = comp.getItemId();
|
|
}
|
|
return this.dockedItems.get(comp);
|
|
},
|
|
|
|
|
|
getComponent: function(comp) {
|
|
var component = this.callParent(arguments);
|
|
if (component === undefined && !Ext.isNumber(comp)) {
|
|
|
|
component = this.getDockedComponent(comp);
|
|
}
|
|
return component;
|
|
},
|
|
|
|
|
|
initBodyStyles: function() {
|
|
var me = this,
|
|
bodyStyle = me.bodyStyle,
|
|
styles = [],
|
|
Element = Ext.Element,
|
|
prop;
|
|
|
|
if (Ext.isFunction(bodyStyle)) {
|
|
bodyStyle = bodyStyle();
|
|
}
|
|
if (Ext.isString(bodyStyle)) {
|
|
styles = bodyStyle.split(';');
|
|
} else {
|
|
for (prop in bodyStyle) {
|
|
if (bodyStyle.hasOwnProperty(prop)) {
|
|
styles.push(prop + ':' + bodyStyle[prop]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (me.bodyPadding !== undefined) {
|
|
styles.push('padding: ' + Element.unitizeBox((me.bodyPadding === true) ? 5 : me.bodyPadding));
|
|
}
|
|
if (me.frame && me.bodyBorder) {
|
|
if (!Ext.isNumber(me.bodyBorder)) {
|
|
me.bodyBorder = 1;
|
|
}
|
|
styles.push('border-width: ' + Element.unitizeBox(me.bodyBorder));
|
|
}
|
|
delete me.bodyStyle;
|
|
return styles.length ? styles.join(';') : undefined;
|
|
},
|
|
|
|
|
|
initBodyCls: function() {
|
|
var me = this,
|
|
cls = '',
|
|
bodyCls = me.bodyCls;
|
|
|
|
if (bodyCls) {
|
|
Ext.each(bodyCls, function(v) {
|
|
cls += " " + v;
|
|
});
|
|
delete me.bodyCls;
|
|
}
|
|
return cls.length > 0 ? cls : undefined;
|
|
},
|
|
|
|
|
|
initRenderData: function() {
|
|
return Ext.applyIf(this.callParent(), {
|
|
bodyStyle: this.initBodyStyles(),
|
|
bodyCls: this.initBodyCls()
|
|
});
|
|
},
|
|
|
|
|
|
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 (me.border === false) {
|
|
|
|
}
|
|
|
|
if (pos !== undefined) {
|
|
me.dockedItems.insert(pos + i, item);
|
|
}
|
|
else {
|
|
me.dockedItems.add(item);
|
|
}
|
|
item.onAdded(me, i);
|
|
me.onDockedAdd(item);
|
|
}
|
|
|
|
|
|
me.componentLayout.childrenChanged = true;
|
|
if (me.rendered && !me.suspendLayout) {
|
|
me.doComponentLayout();
|
|
}
|
|
return items;
|
|
},
|
|
|
|
|
|
onDockedAdd : Ext.emptyFn,
|
|
onDockedRemove : Ext.emptyFn,
|
|
|
|
|
|
insertDocked : function(pos, items) {
|
|
this.addDocked(items, pos);
|
|
},
|
|
|
|
|
|
removeDocked : function(item, autoDestroy) {
|
|
var me = this,
|
|
layout,
|
|
hasLayout;
|
|
|
|
if (!me.dockedItems.contains(item)) {
|
|
return item;
|
|
}
|
|
|
|
layout = me.componentLayout;
|
|
hasLayout = layout && me.rendered;
|
|
|
|
if (hasLayout) {
|
|
layout.onRemove(item);
|
|
}
|
|
|
|
me.dockedItems.remove(item);
|
|
item.onRemoved();
|
|
me.onDockedRemove(item);
|
|
|
|
if (autoDestroy === true || (autoDestroy !== false && me.autoDestroy)) {
|
|
item.destroy();
|
|
} else if (hasLayout) {
|
|
|
|
layout.afterRemove(item);
|
|
}
|
|
|
|
|
|
|
|
me.componentLayout.childrenChanged = true;
|
|
if (!me.destroying && !me.suspendLayout) {
|
|
me.doComponentLayout();
|
|
}
|
|
|
|
return item;
|
|
},
|
|
|
|
|
|
getDockedItems : function(cqSelector) {
|
|
var me = this,
|
|
defaultWeight = me.defaultDockWeights,
|
|
dockedItems;
|
|
|
|
if (me.dockedItems && me.dockedItems.items.length) {
|
|
|
|
if (cqSelector) {
|
|
dockedItems = Ext.ComponentQuery.query(cqSelector, me.dockedItems.items);
|
|
} else {
|
|
dockedItems = me.dockedItems.items.slice();
|
|
}
|
|
|
|
Ext.Array.sort(dockedItems, function(a, b) {
|
|
|
|
var aw = a.weight || defaultWeight[a.dock],
|
|
bw = b.weight || defaultWeight[b.dock];
|
|
if (Ext.isNumber(aw) && Ext.isNumber(bw)) {
|
|
return aw - bw;
|
|
}
|
|
return 0;
|
|
});
|
|
|
|
return dockedItems;
|
|
}
|
|
return [];
|
|
},
|
|
|
|
|
|
addUIClsToElement: function(cls, force) {
|
|
var me = this,
|
|
result = me.callParent(arguments),
|
|
classes = [Ext.baseCSSPrefix + cls, me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
|
|
array, i;
|
|
|
|
if (!force && me.rendered) {
|
|
if (me.bodyCls) {
|
|
me.body.addCls(me.bodyCls);
|
|
} else {
|
|
me.body.addCls(classes);
|
|
}
|
|
} else {
|
|
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, force) {
|
|
var me = this,
|
|
result = me.callParent(arguments),
|
|
classes = [Ext.baseCSSPrefix + cls, me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
|
|
array, i;
|
|
|
|
if (!force && me.rendered) {
|
|
if (me.bodyCls) {
|
|
me.body.removeCls(me.bodyCls);
|
|
} else {
|
|
me.body.removeCls(classes);
|
|
}
|
|
} else {
|
|
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(force) {
|
|
var me = this,
|
|
cls = me.baseCls + '-body-' + me.ui,
|
|
array;
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (!force && 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;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
removeUIFromElement: function() {
|
|
var me = this,
|
|
cls = me.baseCls + '-body-' + me.ui,
|
|
array;
|
|
|
|
me.callParent(arguments);
|
|
|
|
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;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getTargetEl : function() {
|
|
return this.body;
|
|
},
|
|
|
|
getRefItems: function(deep) {
|
|
var items = this.callParent(arguments),
|
|
|
|
dockedItems = this.getDockedItems(deep ? '*,* *' : undefined),
|
|
ln = dockedItems.length,
|
|
i = 0,
|
|
item;
|
|
|
|
|
|
for (; i < ln; i++) {
|
|
item = dockedItems[i];
|
|
if (item.dock === 'right' || item.dock === 'bottom') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
return Ext.Array.splice(dockedItems, 0, i).concat(items).concat(dockedItems);
|
|
},
|
|
|
|
beforeDestroy: function(){
|
|
var docked = this.dockedItems,
|
|
c;
|
|
|
|
if (docked) {
|
|
while ((c = docked.first())) {
|
|
this.removeDocked(c, true);
|
|
}
|
|
}
|
|
this.callParent();
|
|
},
|
|
|
|
setBorder: function(border) {
|
|
var me = this;
|
|
me.border = (border !== undefined) ? border : true;
|
|
if (me.rendered) {
|
|
me.doComponentLayout();
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.panel.Header', {
|
|
extend: 'Ext.container.Container',
|
|
uses: ['Ext.panel.Tool', 'Ext.draw.Component', 'Ext.util.CSS'],
|
|
alias: 'widget.header',
|
|
|
|
isHeader : true,
|
|
defaultType : 'tool',
|
|
indicateDrag : false,
|
|
weight : -1,
|
|
|
|
renderTpl: [
|
|
'<div id="{id}-body" class="{baseCls}-body<tpl if="bodyCls"> {bodyCls}</tpl>',
|
|
'<tpl if="uiCls">',
|
|
'<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl>',
|
|
'</tpl>"',
|
|
'<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>'],
|
|
|
|
|
|
|
|
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
ruleStyle,
|
|
rule,
|
|
style,
|
|
titleTextEl,
|
|
ui;
|
|
|
|
me.indicateDragCls = me.baseCls + '-draggable';
|
|
me.title = me.title || ' ';
|
|
me.tools = me.tools || [];
|
|
me.items = me.items || [];
|
|
me.orientation = me.orientation || 'horizontal';
|
|
me.dock = (me.dock) ? me.dock : (me.orientation == 'horizontal') ? 'top' : 'left';
|
|
|
|
|
|
|
|
me.addClsWithUI(me.orientation);
|
|
me.addClsWithUI(me.dock);
|
|
|
|
me.addChildEls('body');
|
|
|
|
|
|
if (!Ext.isEmpty(me.iconCls)) {
|
|
me.initIconCmp();
|
|
me.items.push(me.iconCmp);
|
|
}
|
|
|
|
|
|
if (me.orientation == 'vertical') {
|
|
|
|
if (Ext.isIE6 || Ext.isIE7) {
|
|
me.width = this.width || 24;
|
|
} else if (Ext.isIEQuirks) {
|
|
me.width = this.width || 25;
|
|
}
|
|
|
|
me.layout = {
|
|
type : 'vbox',
|
|
align: 'center',
|
|
clearInnerCtOnLayout: true,
|
|
bindToOwnerCtContainer: false
|
|
};
|
|
me.textConfig = {
|
|
cls: me.baseCls + '-text',
|
|
type: 'text',
|
|
text: me.title,
|
|
rotate: {
|
|
degrees: 90
|
|
}
|
|
};
|
|
ui = me.ui;
|
|
if (Ext.isArray(ui)) {
|
|
ui = ui[0];
|
|
}
|
|
ruleStyle = '.' + me.baseCls + '-text-' + ui;
|
|
if (Ext.scopeResetCSS) {
|
|
ruleStyle = '.' + Ext.baseCSSPrefix + 'reset ' + ruleStyle;
|
|
}
|
|
rule = Ext.util.CSS.getRule(ruleStyle);
|
|
if (rule) {
|
|
style = rule.style;
|
|
}
|
|
if (style) {
|
|
Ext.apply(me.textConfig, {
|
|
'font-family': style.fontFamily,
|
|
'font-weight': style.fontWeight,
|
|
'font-size': style.fontSize,
|
|
fill: style.color
|
|
});
|
|
}
|
|
me.titleCmp = Ext.create('Ext.draw.Component', {
|
|
ariaRole : 'heading',
|
|
focusable: false,
|
|
viewBox: false,
|
|
flex : 1,
|
|
autoSize: true,
|
|
margins: '5 0 0 0',
|
|
items: [ me.textConfig ],
|
|
|
|
|
|
renderSelectors: {
|
|
textEl: '.' + me.baseCls + '-text'
|
|
}
|
|
});
|
|
} else {
|
|
me.layout = {
|
|
type : 'hbox',
|
|
align: 'middle',
|
|
clearInnerCtOnLayout: true,
|
|
bindToOwnerCtContainer: false
|
|
};
|
|
me.titleCmp = Ext.create('Ext.Component', {
|
|
xtype : 'component',
|
|
ariaRole : 'heading',
|
|
focusable: false,
|
|
flex : 1,
|
|
cls: me.baseCls + '-text-container',
|
|
renderTpl : [
|
|
'<span id="{id}-textEl" class="{cls}-text {cls}-text-{ui}">{title}</span>'
|
|
],
|
|
renderData: {
|
|
title: me.title,
|
|
cls : me.baseCls,
|
|
ui : me.ui
|
|
},
|
|
childEls: ['textEl']
|
|
});
|
|
}
|
|
me.items.push(me.titleCmp);
|
|
|
|
|
|
me.items = me.items.concat(me.tools);
|
|
this.callParent();
|
|
},
|
|
|
|
initIconCmp: function() {
|
|
this.iconCmp = Ext.create('Ext.Component', {
|
|
focusable: false,
|
|
renderTpl : [
|
|
'<img id="{id}-iconEl" alt="" src="{blank}" class="{cls}-icon {iconCls}"/>'
|
|
],
|
|
renderData: {
|
|
blank : Ext.BLANK_IMAGE_URL,
|
|
cls : this.baseCls,
|
|
iconCls: this.iconCls,
|
|
orientation: this.orientation
|
|
},
|
|
childEls: ['iconEl'],
|
|
iconCls: this.iconCls
|
|
});
|
|
},
|
|
|
|
afterRender: function() {
|
|
var me = this;
|
|
|
|
me.el.unselectable();
|
|
if (me.indicateDrag) {
|
|
me.el.addCls(me.indicateDragCls);
|
|
}
|
|
me.mon(me.el, {
|
|
click: me.onClick,
|
|
scope: me
|
|
});
|
|
me.callParent();
|
|
},
|
|
|
|
afterLayout: function() {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
|
|
|
|
if (Ext.isIE7) {
|
|
me.el.repaint();
|
|
}
|
|
},
|
|
|
|
|
|
addUIClsToElement: function(cls, force) {
|
|
var me = this,
|
|
result = me.callParent(arguments),
|
|
classes = [me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
|
|
array, i;
|
|
|
|
if (!force && me.rendered) {
|
|
if (me.bodyCls) {
|
|
me.body.addCls(me.bodyCls);
|
|
} else {
|
|
me.body.addCls(classes);
|
|
}
|
|
} else {
|
|
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, force) {
|
|
var me = this,
|
|
result = me.callParent(arguments),
|
|
classes = [me.baseCls + '-body-' + cls, me.baseCls + '-body-' + me.ui + '-' + cls],
|
|
array, i;
|
|
|
|
if (!force && me.rendered) {
|
|
if (me.bodyCls) {
|
|
me.body.removeCls(me.bodyCls);
|
|
} else {
|
|
me.body.removeCls(classes);
|
|
}
|
|
} else {
|
|
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(force) {
|
|
var me = this,
|
|
array, cls;
|
|
|
|
me.callParent(arguments);
|
|
|
|
cls = me.baseCls + '-body-' + me.ui;
|
|
if (!force && 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 (!force && me.titleCmp && me.titleCmp.rendered && me.titleCmp.textEl) {
|
|
me.titleCmp.textEl.addCls(me.baseCls + '-text-' + 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.textEl) {
|
|
me.titleCmp.textEl.removeCls(me.baseCls + '-text-' + me.ui);
|
|
}
|
|
},
|
|
|
|
onClick: function(e) {
|
|
if (!e.getTarget(Ext.baseCSSPrefix + 'tool')) {
|
|
this.fireEvent('click', e);
|
|
}
|
|
},
|
|
|
|
getTargetEl: function() {
|
|
return this.body || this.frameBody || this.el;
|
|
},
|
|
|
|
|
|
setTitle: function(title) {
|
|
var me = this;
|
|
if (me.rendered) {
|
|
if (me.titleCmp.rendered) {
|
|
if (me.titleCmp.surface) {
|
|
me.title = title || '';
|
|
var sprite = me.titleCmp.surface.items.items[0],
|
|
surface = me.titleCmp.surface;
|
|
|
|
surface.remove(sprite);
|
|
me.textConfig.type = 'text';
|
|
me.textConfig.text = title;
|
|
sprite = surface.add(me.textConfig);
|
|
sprite.setAttributes({
|
|
rotate: {
|
|
degrees: 90
|
|
}
|
|
}, true);
|
|
me.titleCmp.autoSizeSurface();
|
|
} else {
|
|
me.title = title || ' ';
|
|
me.titleCmp.textEl.update(me.title);
|
|
}
|
|
} else {
|
|
me.titleCmp.on({
|
|
render: function() {
|
|
me.setTitle(title);
|
|
},
|
|
single: true
|
|
});
|
|
}
|
|
} else {
|
|
me.on({
|
|
render: function() {
|
|
me.layout.layout();
|
|
me.setTitle(title);
|
|
},
|
|
single: true
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
setIconCls: function(cls) {
|
|
var me = this,
|
|
isEmpty = !cls || !cls.length,
|
|
iconCmp = me.iconCmp,
|
|
el;
|
|
|
|
me.iconCls = cls;
|
|
if (!me.iconCmp && !isEmpty) {
|
|
me.initIconCmp();
|
|
me.insert(0, me.iconCmp);
|
|
} else if (iconCmp) {
|
|
if (isEmpty) {
|
|
me.iconCmp.destroy();
|
|
} else {
|
|
el = iconCmp.iconEl;
|
|
el.removeCls(iconCmp.iconCls);
|
|
el.addCls(cls);
|
|
iconCmp.iconCls = cls;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
addTool: function(tool) {
|
|
this.tools.push(this.add(tool));
|
|
},
|
|
|
|
|
|
onAdd: function(component, index) {
|
|
this.callParent([arguments]);
|
|
if (component instanceof Ext.panel.Tool) {
|
|
component.bindTo(this.ownerCt);
|
|
this.tools[component.type] = component;
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
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, element, value;
|
|
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];
|
|
element = o[0];
|
|
value = o[1];
|
|
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 {
|
|
element.setStyle(attr, value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
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;
|
|
target.each(function(el) {
|
|
out.push([el, this.getElVal(el, attr, val)]);
|
|
}, this);
|
|
return out;
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.fx.Manager', {
|
|
|
|
|
|
|
|
singleton: true,
|
|
|
|
requires: ['Ext.util.MixedCollection',
|
|
'Ext.fx.target.Element',
|
|
'Ext.fx.target.CompositeElement',
|
|
'Ext.fx.target.Sprite',
|
|
'Ext.fx.target.CompositeSprite',
|
|
'Ext.fx.target.Component'],
|
|
|
|
mixins: {
|
|
queue: 'Ext.fx.Queue'
|
|
},
|
|
|
|
|
|
|
|
constructor: function() {
|
|
this.items = Ext.create('Ext.util.MixedCollection');
|
|
this.mixins.queue.constructor.call(this);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
interval: 16,
|
|
|
|
|
|
forceJS: true,
|
|
|
|
|
|
createTarget: function(target) {
|
|
var me = this,
|
|
useCSS3 = !me.forceJS && Ext.supports.Transitions,
|
|
targetObj;
|
|
|
|
me.useCSS3 = useCSS3;
|
|
|
|
|
|
if (Ext.isString(target)) {
|
|
target = Ext.get(target);
|
|
}
|
|
|
|
if (target && target.tagName) {
|
|
target = Ext.get(target);
|
|
targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
|
|
me.targets.add(targetObj);
|
|
return targetObj;
|
|
}
|
|
if (Ext.isObject(target)) {
|
|
|
|
if (target.dom) {
|
|
targetObj = Ext.create('Ext.fx.target.' + 'Element' + (useCSS3 ? 'CSS' : ''), target);
|
|
}
|
|
|
|
else if (target.isComposite) {
|
|
targetObj = Ext.create('Ext.fx.target.' + 'CompositeElement' + (useCSS3 ? 'CSS' : ''), target);
|
|
}
|
|
|
|
else if (target.isSprite) {
|
|
targetObj = Ext.create('Ext.fx.target.Sprite', target);
|
|
}
|
|
|
|
else if (target.isCompositeSprite) {
|
|
targetObj = Ext.create('Ext.fx.target.CompositeSprite', target);
|
|
}
|
|
|
|
else if (target.isComponent) {
|
|
targetObj = Ext.create('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 items = this.items,
|
|
task = this.task;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
items.add(anim);
|
|
|
|
|
|
if (!task && items.length) {
|
|
task = this.task = {
|
|
run: this.runner,
|
|
interval: this.interval,
|
|
scope: this
|
|
};
|
|
Ext.TaskManager.start(task);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
removeAnim: function(anim) {
|
|
|
|
var items = this.items,
|
|
task = this.task;
|
|
items.remove(anim);
|
|
|
|
if (task && !items.length) {
|
|
Ext.TaskManager.stop(task);
|
|
delete this.task;
|
|
}
|
|
},
|
|
|
|
|
|
startingFilter: function(o) {
|
|
return o.paused === false && o.running === false && o.iterations > 0;
|
|
},
|
|
|
|
|
|
runningFilter: function(o) {
|
|
return o.paused === false && o.running === true && o.isAnimator !== true;
|
|
},
|
|
|
|
|
|
runner: function() {
|
|
var me = this,
|
|
items = me.items;
|
|
|
|
me.targetData = {};
|
|
me.targetArr = {};
|
|
|
|
|
|
me.timestamp = new Date();
|
|
|
|
|
|
items.filterBy(me.startingFilter).each(me.startAnim, me);
|
|
|
|
|
|
items.filterBy(me.runningFilter).each(me.runAnim, me);
|
|
|
|
|
|
me.applyPendingAttrs();
|
|
},
|
|
|
|
|
|
startAnim: function(anim) {
|
|
anim.start(this.timestamp);
|
|
},
|
|
|
|
|
|
runAnim: function(anim) {
|
|
if (!anim) {
|
|
return;
|
|
}
|
|
var me = this,
|
|
targetId = anim.target.getId(),
|
|
useCSS3 = me.useCSS3 && anim.target.type == 'element',
|
|
elapsedTime = me.timestamp - anim.startTime,
|
|
target, o;
|
|
|
|
this.collectTargetData(anim, elapsedTime, useCSS3);
|
|
|
|
|
|
|
|
if (useCSS3) {
|
|
|
|
anim.target.setAttr(me.targetData[targetId], true);
|
|
|
|
|
|
me.targetData[targetId] = [];
|
|
me.collectTargetData(anim, anim.duration, useCSS3);
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
else if (elapsedTime >= anim.duration) {
|
|
me.applyPendingAttrs(true);
|
|
delete me.targetData[targetId];
|
|
delete me.targetArr[targetId];
|
|
anim.lastFrame();
|
|
}
|
|
},
|
|
|
|
|
|
collectTargetData: function(anim, elapsedTime, useCSS3) {
|
|
var targetId = anim.target.getId(),
|
|
targetData = this.targetData[targetId],
|
|
data;
|
|
|
|
if (!targetData) {
|
|
targetData = this.targetData[targetId] = [];
|
|
this.targetArr[targetId] = anim.target;
|
|
}
|
|
|
|
data = {
|
|
duration: anim.duration,
|
|
easing: (useCSS3 && anim.reverse) ? anim.easingFn.reverse().toCSS3() : anim.easing,
|
|
attrs: {}
|
|
};
|
|
Ext.apply(data.attrs, anim.runAnim(elapsedTime));
|
|
targetData.push(data);
|
|
},
|
|
|
|
|
|
applyPendingAttrs: function(isLastFrame) {
|
|
var targetData = this.targetData,
|
|
targetArr = this.targetArr,
|
|
targetId;
|
|
for (targetId in targetData) {
|
|
if (targetData.hasOwnProperty(targetId)) {
|
|
targetArr[targetId].setAttr(targetData[targetId], false, isLastFrame);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.fx.Animator', {
|
|
|
|
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
requires: ['Ext.fx.Manager'],
|
|
|
|
|
|
|
|
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, anim, nextAnim, 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,
|
|
reverse = me.reverse,
|
|
ln = timeline.length,
|
|
anim, easing, damper, initial, attrs, lastAttrs, 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 = Ext.create('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);
|
|
}
|
|
});
|
|
|
|
Ext.ns('Ext.fx');
|
|
|
|
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.fx.Easing = {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
Ext.apply(Ext.fx.Easing, {
|
|
linear: function(n) {
|
|
return n;
|
|
},
|
|
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;
|
|
}
|
|
});
|
|
Ext.apply(Ext.fx.Easing, {
|
|
'back-in': Ext.fx.Easing.backIn,
|
|
'back-out': Ext.fx.Easing.backOut,
|
|
'ease-in': Ext.fx.Easing.easeIn,
|
|
'ease-out': Ext.fx.Easing.easeOut,
|
|
'elastic-in': Ext.fx.Easing.elasticIn,
|
|
'elastic-out': Ext.fx.Easing.elasticIn,
|
|
'bounce-in': Ext.fx.Easing.bounceIn,
|
|
'bounce-out': Ext.fx.Easing.bounceOut,
|
|
'ease-in-out': Ext.fx.Easing.easeInOut
|
|
});
|
|
});
|
|
|
|
Ext.define('Ext.draw.Draw', {
|
|
|
|
|
|
singleton: true,
|
|
|
|
requires: ['Ext.draw.Color'],
|
|
|
|
|
|
|
|
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},0,0,{3},{4},0z", attr.x, attr.y, attr.width, attr.height, -attr.width);
|
|
}
|
|
},
|
|
|
|
|
|
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;
|
|
if (pathArray[0][0] == "M") {
|
|
x = pathArray[0][1];
|
|
y = pathArray[0][2];
|
|
mx = x;
|
|
my = y;
|
|
start++;
|
|
res.push(["M", x, y]);
|
|
}
|
|
for (var i = start, ii = pathArray.length; i < ii; i++) {
|
|
var 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 (var 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 (var k = 0, kk = pa.length; k < kk; k++) {
|
|
res[i][k] = pa[k];
|
|
}
|
|
}
|
|
var 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;
|
|
}
|
|
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);
|
|
}
|
|
};
|
|
for (var 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);
|
|
var 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, cos, sin, 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;
|
|
cos = mcos(radian * angle);
|
|
sin = msin(radian * angle);
|
|
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, 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);
|
|
return {
|
|
x: xmin,
|
|
y: ymin,
|
|
path: path,
|
|
width: Math.max.apply(0, X) - xmin,
|
|
height: Math.max.apply(0, Y) - 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, point, 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;
|
|
},
|
|
|
|
curveDim: function (p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y) {
|
|
var a = (c2x - 2 * c1x + p1x) - (p2x - 2 * c2x + c1x),
|
|
b = 2 * (c1x - p1x) - 2 * (c2x - c1x),
|
|
c = p1x - c1x,
|
|
t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a,
|
|
t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a,
|
|
y = [p1y, p2y],
|
|
x = [p1x, p2x],
|
|
dot;
|
|
if (Math.abs(t1) > 1e12) {
|
|
t1 = 0.5;
|
|
}
|
|
if (Math.abs(t2) > 1e12) {
|
|
t2 = 0.5;
|
|
}
|
|
if (t1 > 0 && t1 < 1) {
|
|
dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
|
|
x.push(dot.x);
|
|
y.push(dot.y);
|
|
}
|
|
if (t2 > 0 && t2 < 1) {
|
|
dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
|
|
x.push(dot.x);
|
|
y.push(dot.y);
|
|
}
|
|
a = (c2y - 2 * c1y + p1y) - (p2y - 2 * c2y + c1y);
|
|
b = 2 * (c1y - p1y) - 2 * (c2y - c1y);
|
|
c = p1y - c1y;
|
|
t1 = (-b + Math.sqrt(b * b - 4 * a * c)) / 2 / a;
|
|
t2 = (-b - Math.sqrt(b * b - 4 * a * c)) / 2 / a;
|
|
if (Math.abs(t1) > 1e12) {
|
|
t1 = 0.5;
|
|
}
|
|
if (Math.abs(t2) > 1e12) {
|
|
t2 = 0.5;
|
|
}
|
|
if (t1 > 0 && t1 < 1) {
|
|
dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t1);
|
|
x.push(dot.x);
|
|
y.push(dot.y);
|
|
}
|
|
if (t2 > 0 && t2 < 1) {
|
|
dot = this.findDotAtSegment(p1x, p1y, c1x, c1y, c2x, c2y, p2x, p2y, t2);
|
|
x.push(dot.x);
|
|
y.push(dot.y);
|
|
}
|
|
return {
|
|
min: {x: Math.min.apply(0, x), y: Math.min.apply(0, y)},
|
|
max: {x: Math.max.apply(0, x), y: Math.max.apply(0, y)}
|
|
};
|
|
},
|
|
|
|
|
|
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,
|
|
cx = 0,
|
|
cy = 0;
|
|
for (; i < ii; i++) {
|
|
var 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++;
|
|
}
|
|
cx = path[j][5];
|
|
cy = path[j][6];
|
|
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")) {
|
|
var 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) {
|
|
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,
|
|
modulo = Math.round((step % m) * Math.pow(10, 2 - level)),
|
|
interval = [[0, 15], [20, 4], [30, 2], [40, 4], [50, 9], [60, 4], [70, 2], [80, 4], [100, 15]],
|
|
stepCount = 0,
|
|
value,
|
|
weight,
|
|
i,
|
|
topValue,
|
|
topWeight = 1e9,
|
|
ln = interval.length;
|
|
cur = from = Math.floor(from / m) * m;
|
|
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);
|
|
while (cur < to) {
|
|
cur += step;
|
|
stepCount++;
|
|
}
|
|
to = +cur.toFixed(10);
|
|
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, 3, 5, 10, 20, 30, 50, 100, 200, 300, 500]],
|
|
[Ext.Date.SECOND, [1, 2, 3, 5, 10, 15, 30]],
|
|
[Ext.Date.MINUTE, [1, 2, 3, 5, 10, 20, 30]],
|
|
[Ext.Date.HOUR, [1, 2, 3, 4, 6, 12]],
|
|
[Ext.Date.DAY, [1, 2, 3, 7, 14]],
|
|
[Ext.Date.MONTH, [1, 2, 3, 4, 6]]
|
|
], j, yearDiff;
|
|
|
|
|
|
Ext.each(scales, function(scale, i) {
|
|
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]];
|
|
return false;
|
|
}
|
|
}
|
|
});
|
|
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()],
|
|
steps = 0, testFrom, testTo;
|
|
if (lockEnds) {
|
|
testFrom = from;
|
|
} else {
|
|
switch (step[0]) {
|
|
case Ext.Date.MILLI:
|
|
testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
|
|
fromStat[4], fromStat[5], Math.floor(fromStat[6] / step[1]) * step[1]);
|
|
break;
|
|
case Ext.Date.SECOND:
|
|
testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
|
|
fromStat[4], Math.floor(fromStat[5] / step[1]) * step[1], 0);
|
|
break;
|
|
case Ext.Date.MINUTE:
|
|
testFrom = new Date(fromStat[0], fromStat[1], fromStat[2], fromStat[3],
|
|
Math.floor(fromStat[4] / step[1]) * step[1], 0, 0);
|
|
break;
|
|
case Ext.Date.HOUR:
|
|
testFrom = new Date(fromStat[0], fromStat[1], fromStat[2],
|
|
Math.floor(fromStat[3] / step[1]) * step[1], 0, 0, 0);
|
|
break;
|
|
case Ext.Date.DAY:
|
|
testFrom = new Date(fromStat[0], fromStat[1],
|
|
Math.floor(fromStat[2] - 1 / step[1]) * step[1] + 1, 0, 0, 0, 0);
|
|
break;
|
|
case Ext.Date.MONTH:
|
|
testFrom = new Date(fromStat[0], Math.floor(fromStat[1] / step[1]) * step[1], 1, 0, 0, 0, 0);
|
|
break;
|
|
default:
|
|
testFrom = new Date(Math.floor(fromStat[0] / step[1]) * step[1], 0, 1, 0, 0, 0, 0);
|
|
break;
|
|
}
|
|
}
|
|
|
|
testTo = testFrom;
|
|
|
|
while (testTo < to) {
|
|
testTo = Ext.Date.add(testTo, step[0], step[1]);
|
|
steps++;
|
|
}
|
|
|
|
if (lockEnds) {
|
|
testTo = to;
|
|
}
|
|
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;
|
|
},
|
|
|
|
degrees: function(radian) {
|
|
return radian * 180 / Math.PI % 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', {
|
|
|
|
|
|
|
|
requires: ['Ext.draw.Draw'],
|
|
|
|
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;
|
|
}
|
|
},
|
|
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 base,
|
|
out = false,
|
|
match;
|
|
|
|
Ext.each([this.hexRE, this.rgbRE, this.hex3RE], function(re, idx) {
|
|
base = (idx % 2 == 0) ? 16 : 10;
|
|
match = re.exec(color);
|
|
if (match && match.length == 4) {
|
|
if (idx == 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)
|
|
};
|
|
return false;
|
|
}
|
|
});
|
|
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] = parseInt(prop[p], 10) * 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] = Math.round(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() {
|
|
Ext.each([
|
|
'outlineColor',
|
|
'backgroundColor',
|
|
'borderColor',
|
|
'borderTopColor',
|
|
'borderRightColor',
|
|
'borderBottomColor',
|
|
'borderLeftColor',
|
|
'fill',
|
|
'stroke'
|
|
], function(prop) {
|
|
this[prop] = this.color;
|
|
}, this);
|
|
});
|
|
|
|
Ext.define('Ext.fx.Anim', {
|
|
|
|
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
requires: ['Ext.fx.Manager', 'Ext.fx.Animator', 'Ext.fx.Easing', 'Ext.fx.CubicBezier', 'Ext.fx.PropertyHandler'],
|
|
|
|
|
|
|
|
isAnimation: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
duration: 250,
|
|
|
|
|
|
delay: 0,
|
|
|
|
|
|
delayStart: 0,
|
|
|
|
|
|
dynamic: false,
|
|
|
|
|
|
easing: 'ease',
|
|
|
|
|
|
|
|
|
|
damper: 1,
|
|
|
|
|
|
bezierRE: /^(?:cubic-)?bezier\(([^,]+),([^,]+),([^,]+),([^\)]+)\)/,
|
|
|
|
|
|
reverse: false,
|
|
|
|
|
|
running: false,
|
|
|
|
|
|
paused: false,
|
|
|
|
|
|
iterations: 1,
|
|
|
|
|
|
alternate: false,
|
|
|
|
|
|
currentIteration: 0,
|
|
|
|
|
|
startTime: 0,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor: function(config) {
|
|
var me = this,
|
|
curve;
|
|
|
|
config = config || {};
|
|
|
|
if (config.keyframes) {
|
|
return Ext.create('Ext.fx.Animator', config);
|
|
}
|
|
config = Ext.apply(me, config);
|
|
if (me.from === undefined) {
|
|
me.from = {};
|
|
}
|
|
me.propHandlers = {};
|
|
me.config = config;
|
|
me.target = Ext.fx.Manager.createTarget(me.target);
|
|
me.easingFn = Ext.fx.Easing[me.easing];
|
|
me.target.dynamic = me.dynamic;
|
|
|
|
|
|
if (!me.easingFn) {
|
|
me.easingFn = String(me.easing).match(me.bezierRE);
|
|
if (me.easingFn && me.easingFn.length == 5) {
|
|
curve = me.easingFn;
|
|
me.easingFn = Ext.fx.CubicBezier.cubicBezier(+curve[1], +curve[2], +curve[3], +curve[4]);
|
|
}
|
|
}
|
|
me.id = Ext.id(null, 'ext-anim-');
|
|
Ext.fx.Manager.addAnim(me);
|
|
me.addEvents(
|
|
|
|
'beforeanimate',
|
|
|
|
'afteranimate',
|
|
|
|
'lastframe'
|
|
);
|
|
me.mixins.observable.constructor.call(me, config);
|
|
if (config.callback) {
|
|
me.on('afteranimate', config.callback, config.scope);
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
setAttr: function(attr, value) {
|
|
return Ext.fx.Manager.items.get(this.id).setAttr(this.target, attr, value);
|
|
},
|
|
|
|
|
|
initAttrs: function() {
|
|
var me = this,
|
|
from = me.from,
|
|
to = me.to,
|
|
initialFrom = me.initialFrom || {},
|
|
out = {},
|
|
start, end, propHandler, attr;
|
|
|
|
for (attr in to) {
|
|
if (to.hasOwnProperty(attr)) {
|
|
start = me.target.getAttr(attr, from[attr]);
|
|
end = to[attr];
|
|
|
|
if (!Ext.fx.PropertyHandler[attr]) {
|
|
if (Ext.isObject(end)) {
|
|
propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.object;
|
|
} else {
|
|
propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler.defaultHandler;
|
|
}
|
|
}
|
|
|
|
else {
|
|
propHandler = me.propHandlers[attr] = Ext.fx.PropertyHandler[attr];
|
|
}
|
|
out[attr] = propHandler.get(start, end, me.damper, initialFrom[attr], attr);
|
|
}
|
|
}
|
|
me.currentAttrs = out;
|
|
},
|
|
|
|
|
|
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;
|
|
if (!me.paused && !me.currentAttrs) {
|
|
me.initAttrs();
|
|
}
|
|
me.running = true;
|
|
}
|
|
},
|
|
|
|
|
|
runAnim: function(elapsedTime) {
|
|
var me = this,
|
|
attrs = me.currentAttrs,
|
|
duration = me.duration,
|
|
easingFn = me.easingFn,
|
|
propHandlers = me.propHandlers,
|
|
ret = {},
|
|
easing, values, attr, lastFrame;
|
|
|
|
if (elapsedTime >= 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);
|
|
}
|
|
}
|
|
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);
|
|
}
|
|
},
|
|
|
|
|
|
end: function() {
|
|
var me = this;
|
|
me.startTime = 0;
|
|
me.paused = false;
|
|
me.running = false;
|
|
Ext.fx.Manager.removeAnim(me);
|
|
me.fireEvent('afteranimate', me, me.startTime);
|
|
}
|
|
});
|
|
|
|
Ext.enableFx = true;
|
|
|
|
|
|
|
|
|
|
|
|
Ext.define('Ext.dd.DragDrop', {
|
|
requires: ['Ext.dd.DragDropManager'],
|
|
|
|
|
|
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;
|
|
if(cd == document.body){
|
|
c = { x: s.left, y: s.top, width: Ext.Element.getViewWidth(), height: Ext.Element.getViewHeight()};
|
|
}else{
|
|
var xy = ce.getXY();
|
|
c = {x : xy[0], y: xy[1], width: cd.clientWidth, height: cd.clientHeight};
|
|
}
|
|
|
|
|
|
var 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();
|
|
|
|
if (!this.DDMInstance.verifyEl(el)) {
|
|
return;
|
|
}
|
|
|
|
var dx = diffX || 0;
|
|
var dy = diffY || 0;
|
|
|
|
var 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() {
|
|
Ext.EventManager.un(this.id, "mousedown", this.handleMouseDown, this);
|
|
this._domRef = null;
|
|
this.DDMInstance._remove(this);
|
|
},
|
|
|
|
destroy : function(){
|
|
this.unreg();
|
|
},
|
|
|
|
|
|
isLocked: function() {
|
|
return (this.DDMInstance.isLocked() || this.locked);
|
|
},
|
|
|
|
|
|
handleMouseDown: function(e, oDD){
|
|
if (this.primaryButtonOnly && e.button != 0) {
|
|
return;
|
|
}
|
|
|
|
if (this.isLocked()) {
|
|
return;
|
|
}
|
|
|
|
this.DDMInstance.refreshCache(this.groups);
|
|
|
|
var pt = e.getPoint();
|
|
if (!this.hasOuterHandles && !this.DDMInstance.isOverTarget(pt, this) ) {
|
|
} else {
|
|
if (this.clickValidator(e)) {
|
|
|
|
this.setStartPosition();
|
|
this.b4MouseDown(e);
|
|
this.onMouseDown(e);
|
|
|
|
this.DDMInstance.handleMouseDown(e, this);
|
|
|
|
this.DDMInstance.stopEvent(e);
|
|
} else {
|
|
|
|
|
|
}
|
|
}
|
|
},
|
|
|
|
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<len; ++i) {
|
|
if (this.invalidHandleClasses[i] == cssClass) {
|
|
delete this.invalidHandleClasses[i];
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
isValidHandleChild: function(node) {
|
|
|
|
var valid = true;
|
|
|
|
var nodeName;
|
|
try {
|
|
nodeName = node.nodeName.toUpperCase();
|
|
} catch(e) {
|
|
nodeName = node.nodeName;
|
|
}
|
|
valid = valid && !this.invalidHandleTypes[nodeName];
|
|
valid = valid && !this.invalidHandleIds[node.id];
|
|
|
|
for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
|
|
valid = !Ext.fly(node).hasCls(this.invalidHandleClasses[i]);
|
|
}
|
|
|
|
|
|
return valid;
|
|
|
|
},
|
|
|
|
|
|
setXTicks: function(iStartX, iTickSize) {
|
|
this.xTicks = [];
|
|
this.xTickSize = iTickSize;
|
|
|
|
var tickMap = {};
|
|
|
|
for (var i = this.initPageX; 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 = {};
|
|
|
|
for (var 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;
|
|
var 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 {
|
|
for (var i=0, len=tickArray.length; i<len; ++i) {
|
|
var next = i + 1;
|
|
if (tickArray[next] && tickArray[next] >= val) {
|
|
var diff1 = val - tickArray[i];
|
|
var 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',
|
|
requires: ['Ext.dd.DragDropManager'],
|
|
|
|
|
|
constructor: function(id, sGroup, config) {
|
|
if (id) {
|
|
this.init(id, sGroup, config);
|
|
}
|
|
},
|
|
|
|
|
|
scroll: true,
|
|
|
|
|
|
autoOffset: function(iPageX, iPageY) {
|
|
var x = iPageX - this.startPageX;
|
|
var 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;
|
|
|
|
if (!this.deltaSetXY) {
|
|
vpSize = this.cachedViewportSize = { width: EL.getDocumentWidth(), height: EL.getDocumentHeight() };
|
|
var 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);
|
|
var newLeft = fly.getLeft(true);
|
|
var newTop = fly.getTop(true);
|
|
this.deltaSetXY = [newLeft - oCoord.x, newTop - oCoord.y];
|
|
} else {
|
|
vpSize = this.cachedViewportSize;
|
|
fly.setLeftTop(
|
|
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();
|
|
|
|
|
|
var clientW = Ext.Element.getViewWidth();
|
|
|
|
|
|
var st = this.DDMInstance.getScrollTop();
|
|
|
|
|
|
var sl = this.DDMInstance.getScrollLeft();
|
|
|
|
|
|
var bot = h + y;
|
|
|
|
|
|
var right = w + x;
|
|
|
|
|
|
|
|
|
|
var toBot = (clientH + st - y - this.deltaY);
|
|
|
|
|
|
var toRight = (clientW + sl - x - this.deltaX);
|
|
|
|
|
|
|
|
|
|
var thresh = 40;
|
|
|
|
|
|
|
|
|
|
var 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;
|
|
var 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);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
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;
|
|
var body = document.body;
|
|
|
|
if (!body || !body.firstChild) {
|
|
setTimeout( function() { self.createFrame(); }, 50 );
|
|
return;
|
|
}
|
|
|
|
var div = this.getDragEl();
|
|
|
|
if (!div) {
|
|
div = document.createElement("div");
|
|
div.id = this.dragElId;
|
|
var 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();
|
|
var dragEl = this.getDragEl();
|
|
var 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();
|
|
var 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();
|
|
var 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.DragSource', {
|
|
extend: 'Ext.dd.DDProxy',
|
|
requires: [
|
|
'Ext.dd.StatusProxy',
|
|
'Ext.dd.DragDropManager'
|
|
],
|
|
|
|
|
|
|
|
|
|
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 = Ext.create('Ext.dd.StatusProxy', {
|
|
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);
|
|
this.cachedTarget = target;
|
|
if (this.beforeDragEnter(target, e, id) !== false) {
|
|
if (target.isNotifyTarget) {
|
|
var 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;
|
|
},
|
|
|
|
|
|
alignElWithMouse: function() {
|
|
this.callParent(arguments);
|
|
this.proxy.sync();
|
|
},
|
|
|
|
|
|
onDragOver: function(e, id) {
|
|
var target = this.cachedTarget || Ext.dd.DragDropManager.getDDById(id);
|
|
if (this.beforeDragOver(target, e, id) !== false) {
|
|
if(target.isNotifyTarget){
|
|
var 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) {
|
|
this.beforeInvalidDrop(target, e, id);
|
|
if (this.cachedTarget) {
|
|
if(this.cachedTarget.isNotifyTarget){
|
|
this.cachedTarget.notifyOut(this, e, this.dragData);
|
|
}
|
|
this.cacheTarget = null;
|
|
}
|
|
this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
|
|
|
|
if (this.afterInvalidDrop) {
|
|
|
|
this.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,
|
|
|
|
|
|
startDrag: function(x, y) {
|
|
this.proxy.reset();
|
|
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.DD', {
|
|
extend: 'Ext.dd.DragSource',
|
|
requires: ['Ext.panel.Proxy'],
|
|
|
|
constructor : function(panel, cfg){
|
|
this.panel = panel;
|
|
this.dragData = {panel: panel};
|
|
this.proxy = Ext.create('Ext.panel.Proxy', panel, cfg);
|
|
|
|
this.callParent([panel.el, cfg]);
|
|
|
|
Ext.defer(function() {
|
|
var header = panel.header,
|
|
el = panel.body;
|
|
|
|
if(header){
|
|
this.setHandleElId(header.id);
|
|
el = header.el;
|
|
}
|
|
el.setStyle('cursor', 'move');
|
|
this.scroll = false;
|
|
}, 200, this);
|
|
},
|
|
|
|
showFrame: Ext.emptyFn,
|
|
startDrag: Ext.emptyFn,
|
|
b4StartDrag: function(x, y) {
|
|
this.proxy.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){
|
|
return this.proxy.ghost.el.dom;
|
|
},
|
|
endDrag : function(e){
|
|
this.proxy.hide();
|
|
this.panel.saveState();
|
|
},
|
|
|
|
autoOffset : function(x, y) {
|
|
x -= this.startPageX;
|
|
y -= this.startPageY;
|
|
this.setDelta(x, y);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.component.Dock', {
|
|
|
|
|
|
|
|
alias: ['layout.dock'],
|
|
|
|
extend: 'Ext.layout.component.AbstractDock'
|
|
|
|
|
|
|
|
});
|
|
|
|
Ext.define('Ext.panel.Panel', {
|
|
extend: 'Ext.panel.AbstractPanel',
|
|
requires: [
|
|
'Ext.panel.Header',
|
|
'Ext.fx.Anim',
|
|
'Ext.util.KeyMap',
|
|
'Ext.panel.DD',
|
|
'Ext.XTemplate',
|
|
'Ext.layout.component.Dock',
|
|
'Ext.util.Memento'
|
|
],
|
|
alias: 'widget.panel',
|
|
alternateClassName: 'Ext.Panel',
|
|
|
|
|
|
collapsedCls: 'collapsed',
|
|
|
|
|
|
animCollapse: Ext.enableFx,
|
|
|
|
|
|
minButtonWidth: 75,
|
|
|
|
|
|
collapsed: false,
|
|
|
|
|
|
collapseFirst: true,
|
|
|
|
|
|
hideCollapseTool: false,
|
|
|
|
|
|
titleCollapse: false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
floatable: true,
|
|
|
|
|
|
|
|
|
|
collapsible: false,
|
|
|
|
|
|
|
|
|
|
closable: false,
|
|
|
|
|
|
closeAction: 'destroy',
|
|
|
|
|
|
|
|
|
|
preventHeader: false,
|
|
|
|
|
|
headerPosition: 'top',
|
|
|
|
|
|
frame: false,
|
|
|
|
|
|
frameHeader: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
cls;
|
|
|
|
me.addEvents(
|
|
|
|
|
|
'beforeclose',
|
|
|
|
|
|
"beforeexpand",
|
|
|
|
|
|
"beforecollapse",
|
|
|
|
|
|
"expand",
|
|
|
|
|
|
"collapse",
|
|
|
|
|
|
'titlechange',
|
|
|
|
|
|
'iconchange'
|
|
);
|
|
|
|
|
|
this.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;
|
|
},
|
|
|
|
setBorder: function(border) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
beforeDestroy: function() {
|
|
Ext.destroy(
|
|
this.ghostPanel,
|
|
this.dd
|
|
);
|
|
this.callParent();
|
|
},
|
|
|
|
initAria: function() {
|
|
this.callParent();
|
|
this.initHeaderAria();
|
|
},
|
|
|
|
initHeaderAria: function() {
|
|
var me = this,
|
|
el = me.el,
|
|
header = me.header;
|
|
if (el && header) {
|
|
el.dom.setAttribute('aria-labelledby', header.titleCmp.id);
|
|
}
|
|
},
|
|
|
|
getHeader: function() {
|
|
return this.header;
|
|
},
|
|
|
|
|
|
setTitle: function(newTitle) {
|
|
var me = this,
|
|
oldTitle = this.title;
|
|
|
|
me.title = newTitle;
|
|
if (me.header) {
|
|
me.header.setTitle(newTitle);
|
|
} else {
|
|
me.updateHeader();
|
|
}
|
|
|
|
if (me.reExpander) {
|
|
me.reExpander.setTitle(newTitle);
|
|
}
|
|
me.fireEvent('titlechange', me, newTitle, oldTitle);
|
|
},
|
|
|
|
|
|
setIconCls: function(newIconCls) {
|
|
var me = this,
|
|
oldIconCls = me.iconCls;
|
|
|
|
me.iconCls = newIconCls;
|
|
var header = me.header;
|
|
if (header) {
|
|
header.setIconCls(newIconCls);
|
|
}
|
|
me.fireEvent('iconchange', me, newIconCls, oldIconCls);
|
|
},
|
|
|
|
bridgeToolbars: function() {
|
|
var me = this,
|
|
docked = [],
|
|
fbar,
|
|
fbarDefaults,
|
|
minButtonWidth = me.minButtonWidth;
|
|
|
|
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 || {};
|
|
if ((!config.xtype || config.xtype === 'button' || (config.isComponent && config.isXType('button'))) &&
|
|
!('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;
|
|
}
|
|
},
|
|
|
|
|
|
initTools: function() {
|
|
var me = this;
|
|
|
|
me.tools = me.tools ? Ext.Array.clone(me.tools) : [];
|
|
|
|
|
|
|
|
if (me.collapsible && !(me.hideCollapseTool || me.header === false)) {
|
|
me.collapseDirection = me.collapseDirection || me.headerPosition || 'top';
|
|
me.collapseTool = me.expandTool = me.createComponent({
|
|
xtype: 'tool',
|
|
type: 'collapse-' + me.collapseDirection,
|
|
expandType: me.getOppositeDirection(me.collapseDirection),
|
|
handler: me.toggleCollapse,
|
|
scope: me
|
|
});
|
|
|
|
|
|
if (me.collapseFirst) {
|
|
me.tools.unshift(me.collapseTool);
|
|
}
|
|
}
|
|
|
|
|
|
me.addTools();
|
|
|
|
|
|
if (me.closable) {
|
|
me.addClsWithUI('closable');
|
|
me.addTool({
|
|
type: 'close',
|
|
handler: Ext.Function.bind(me.close, this, [])
|
|
});
|
|
}
|
|
|
|
|
|
if (me.collapseTool && !me.collapseFirst) {
|
|
me.tools.push(me.collapseTool);
|
|
}
|
|
},
|
|
|
|
|
|
addTools: Ext.emptyFn,
|
|
|
|
|
|
close: function() {
|
|
if (this.fireEvent('beforeclose', this) !== false) {
|
|
this.doClose();
|
|
}
|
|
},
|
|
|
|
|
|
doClose: function() {
|
|
this.fireEvent('close', this);
|
|
this[this.closeAction]();
|
|
},
|
|
|
|
onRender: function(ct, position) {
|
|
var me = this,
|
|
topContainer;
|
|
|
|
|
|
|
|
me.initTools();
|
|
|
|
|
|
me.updateHeader();
|
|
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
afterRender: function() {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
|
|
|
|
if (me.collapsed) {
|
|
me.collapsed = false;
|
|
me.collapse(null, false, true);
|
|
}
|
|
},
|
|
|
|
|
|
updateHeader: function(force) {
|
|
var me = this,
|
|
header = me.header,
|
|
title = me.title,
|
|
tools = me.tools;
|
|
|
|
if (!me.preventHeader && (force || title || (tools && tools.length))) {
|
|
if (!header) {
|
|
header = me.header = Ext.create('Ext.panel.Header', {
|
|
title : title,
|
|
orientation : (me.headerPosition == 'left' || me.headerPosition == 'right') ? 'vertical' : 'horizontal',
|
|
dock : me.headerPosition || 'top',
|
|
textCls : me.headerTextCls,
|
|
iconCls : me.iconCls,
|
|
baseCls : me.baseCls + '-header',
|
|
tools : tools,
|
|
ui : me.ui,
|
|
indicateDrag: me.draggable,
|
|
border : me.border,
|
|
frame : me.frame && me.frameHeader,
|
|
ignoreParentFrame : me.frame || me.overlapHeader,
|
|
ignoreBorderManagement: me.frame || me.ignoreHeaderBorderManagement,
|
|
listeners : me.collapsible && me.titleCollapse ? {
|
|
click: me.toggleCollapse,
|
|
scope: me
|
|
} : null
|
|
});
|
|
me.addDocked(header, 0);
|
|
|
|
|
|
|
|
me.tools = header.tools;
|
|
}
|
|
header.show();
|
|
me.initHeaderAria();
|
|
} else if (header) {
|
|
header.hide();
|
|
}
|
|
},
|
|
|
|
|
|
setUI: function(ui) {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (me.header) {
|
|
me.header.setUI(ui);
|
|
}
|
|
},
|
|
|
|
|
|
getContentTarget: function() {
|
|
return this.body;
|
|
},
|
|
|
|
getTargetEl: function() {
|
|
return this.body || this.frameBody || this.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;
|
|
if (me.collapsed && me.placeholder) {
|
|
me.placeholder.hide();
|
|
} else {
|
|
me.callParent(arguments);
|
|
}
|
|
},
|
|
|
|
|
|
onShow: function(){
|
|
var me = this;
|
|
if (me.collapsed && me.placeholder) {
|
|
|
|
me.hidden = true;
|
|
me.placeholder.show();
|
|
} else {
|
|
me.callParent(arguments);
|
|
}
|
|
},
|
|
|
|
addTool: function(tool) {
|
|
var me = this,
|
|
header = me.header;
|
|
|
|
if (Ext.isArray(tool)) {
|
|
Ext.each(tool, me.addTool, me);
|
|
return;
|
|
}
|
|
me.tools.push(tool);
|
|
if (header) {
|
|
header.addTool(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;
|
|
}
|
|
},
|
|
|
|
|
|
collapse: function(direction, animate, internal) {
|
|
var me = this,
|
|
c = Ext.Component,
|
|
height = me.getHeight(),
|
|
width = me.getWidth(),
|
|
frameInfo,
|
|
newSize = 0,
|
|
dockedItems = me.dockedItems.items,
|
|
dockedItemCount = dockedItems.length,
|
|
i = 0,
|
|
comp,
|
|
pos,
|
|
anim = {
|
|
from: {
|
|
height: height,
|
|
width: width
|
|
},
|
|
to: {
|
|
height: height,
|
|
width: width
|
|
},
|
|
listeners: {
|
|
afteranimate: me.afterCollapse,
|
|
scope: me
|
|
},
|
|
duration: Ext.Number.from(animate, Ext.fx.Anim.prototype.duration)
|
|
},
|
|
reExpander,
|
|
reExpanderOrientation,
|
|
reExpanderDock,
|
|
getDimension,
|
|
collapseDimension;
|
|
|
|
if (!direction) {
|
|
direction = me.collapseDirection;
|
|
}
|
|
|
|
|
|
if (internal) {
|
|
animate = false;
|
|
} else if (me.collapsed || me.fireEvent('beforecollapse', me, direction, animate) === false) {
|
|
return false;
|
|
}
|
|
|
|
reExpanderDock = direction;
|
|
me.expandDirection = me.getOppositeDirection(direction);
|
|
|
|
|
|
me.hiddenDocked = [];
|
|
|
|
switch (direction) {
|
|
case c.DIRECTION_TOP:
|
|
case c.DIRECTION_BOTTOM:
|
|
reExpanderOrientation = 'horizontal';
|
|
collapseDimension = 'height';
|
|
getDimension = 'getHeight';
|
|
|
|
|
|
|
|
for (; i < dockedItemCount; i++) {
|
|
comp = dockedItems[i];
|
|
if (comp.isVisible()) {
|
|
if (comp.isXType('header', true) && (!comp.dock || comp.dock == 'top' || comp.dock == 'bottom')) {
|
|
reExpander = comp;
|
|
} else {
|
|
me.hiddenDocked.push(comp);
|
|
}
|
|
} else if (comp === me.reExpander) {
|
|
reExpander = comp;
|
|
}
|
|
}
|
|
|
|
if (direction == Ext.Component.DIRECTION_BOTTOM) {
|
|
pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
|
|
anim.from.top = pos;
|
|
}
|
|
break;
|
|
|
|
case c.DIRECTION_LEFT:
|
|
case c.DIRECTION_RIGHT:
|
|
reExpanderOrientation = 'vertical';
|
|
collapseDimension = 'width';
|
|
getDimension = 'getWidth';
|
|
|
|
|
|
|
|
for (; i < dockedItemCount; i++) {
|
|
comp = dockedItems[i];
|
|
if (comp.isVisible()) {
|
|
if (comp.isHeader && (comp.dock == 'left' || comp.dock == 'right')) {
|
|
reExpander = comp;
|
|
} else {
|
|
me.hiddenDocked.push(comp);
|
|
}
|
|
} else if (comp === me.reExpander) {
|
|
reExpander = comp;
|
|
}
|
|
}
|
|
|
|
if (direction == Ext.Component.DIRECTION_RIGHT) {
|
|
pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
|
|
anim.from.left = pos;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
throw('Panel collapse must be passed a valid Component collapse direction');
|
|
}
|
|
|
|
|
|
if (animate && me.collapseTool) {
|
|
me.collapseTool.disable();
|
|
}
|
|
|
|
|
|
me.addClsWithUI(me.collapsedCls);
|
|
|
|
|
|
|
|
|
|
|
|
if (reExpander && reExpander.rendered) {
|
|
|
|
|
|
reExpander.addClsWithUI(me.collapsedCls);
|
|
reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
|
|
if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
|
|
reExpander.addClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
|
|
}
|
|
|
|
frameInfo = reExpander.getFrameInfo();
|
|
|
|
|
|
newSize = reExpander[getDimension]() + (frameInfo ? frameInfo[direction] : 0);
|
|
|
|
|
|
reExpander.removeClsWithUI(me.collapsedCls);
|
|
reExpander.removeClsWithUI(me.collapsedCls + '-' + reExpander.dock);
|
|
if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
|
|
reExpander.removeClsWithUI(me.collapsedCls + '-border-' + reExpander.dock);
|
|
}
|
|
}
|
|
|
|
else {
|
|
reExpander = {
|
|
hideMode: 'offsets',
|
|
temporary: true,
|
|
title: me.title,
|
|
orientation: reExpanderOrientation,
|
|
dock: reExpanderDock,
|
|
textCls: me.headerTextCls,
|
|
iconCls: me.iconCls,
|
|
baseCls: me.baseCls + '-header',
|
|
ui: me.ui,
|
|
frame: me.frame && me.frameHeader,
|
|
ignoreParentFrame: me.frame || me.overlapHeader,
|
|
indicateDrag: me.draggable,
|
|
cls: me.baseCls + '-collapsed-placeholder ' + ' ' + Ext.baseCSSPrefix + 'docked ' + me.baseCls + '-' + me.ui + '-collapsed',
|
|
renderTo: me.el
|
|
};
|
|
if (!me.hideCollapseTool) {
|
|
reExpander[(reExpander.orientation == 'horizontal') ? 'tools' : 'items'] = [{
|
|
xtype: 'tool',
|
|
type: 'expand-' + me.expandDirection,
|
|
handler: me.toggleCollapse,
|
|
scope: me
|
|
}];
|
|
}
|
|
|
|
|
|
|
|
reExpander = me.reExpander = Ext.create('Ext.panel.Header', reExpander);
|
|
newSize = reExpander[getDimension]() + ((reExpander.frame) ? reExpander.frameSize[direction] : 0);
|
|
reExpander.hide();
|
|
|
|
|
|
me.insertDocked(0, reExpander);
|
|
}
|
|
|
|
me.reExpander = reExpander;
|
|
me.reExpander.addClsWithUI(me.collapsedCls);
|
|
me.reExpander.addClsWithUI(me.collapsedCls + '-' + reExpander.dock);
|
|
if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
|
|
me.reExpander.addClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
|
|
}
|
|
|
|
|
|
if (direction == Ext.Component.DIRECTION_RIGHT) {
|
|
anim.to.left = pos + (width - newSize);
|
|
} else if (direction == Ext.Component.DIRECTION_BOTTOM) {
|
|
anim.to.top = pos + (height - newSize);
|
|
}
|
|
|
|
|
|
anim.to[collapseDimension] = newSize;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!me.collapseMemento) {
|
|
me.collapseMemento = new Ext.util.Memento(me);
|
|
}
|
|
me.collapseMemento.capture(['width', 'height', 'minWidth', 'minHeight', 'layoutManagedHeight', 'layoutManagedWidth']);
|
|
|
|
|
|
me.savedFlex = me.flex;
|
|
me.minWidth = 0;
|
|
me.minHeight = 0;
|
|
delete me.flex;
|
|
me.suspendLayout = true;
|
|
|
|
if (animate) {
|
|
me.animate(anim);
|
|
} else {
|
|
me.setSize(anim.to.width, anim.to.height);
|
|
if (Ext.isDefined(anim.to.left) || Ext.isDefined(anim.to.top)) {
|
|
me.setPosition(anim.to.left, anim.to.top);
|
|
}
|
|
me.afterCollapse(false, internal);
|
|
}
|
|
return me;
|
|
},
|
|
|
|
afterCollapse: function(animated, internal) {
|
|
var me = this,
|
|
i = 0,
|
|
l = me.hiddenDocked.length;
|
|
|
|
me.collapseMemento.restore(['minWidth', 'minHeight']);
|
|
|
|
|
|
|
|
|
|
if (Ext.Component.VERTICAL_DIRECTION_Re.test(me.expandDirection)) {
|
|
me.layoutManagedHeight = 2;
|
|
me.collapseMemento.restore('width', false);
|
|
} else {
|
|
me.layoutManagedWidth = 2;
|
|
me.collapseMemento.restore('height', false);
|
|
}
|
|
|
|
|
|
|
|
me.saveScrollTop = me.body.dom.scrollTop;
|
|
me.body.setStyle('display', 'none');
|
|
|
|
for (; i < l; i++) {
|
|
me.hiddenDocked[i].hide();
|
|
}
|
|
if (me.reExpander) {
|
|
me.reExpander.updateFrame();
|
|
me.reExpander.show();
|
|
}
|
|
me.collapsed = true;
|
|
me.suspendLayout = false;
|
|
|
|
if (!internal) {
|
|
if (me.ownerCt) {
|
|
|
|
|
|
if (animated) {
|
|
me.ownerCt.layout.layout();
|
|
}
|
|
} else if (me.reExpander.temporary) {
|
|
me.doComponentLayout();
|
|
}
|
|
}
|
|
|
|
if (me.resizer) {
|
|
me.resizer.disable();
|
|
}
|
|
|
|
|
|
if (me.collapseTool) {
|
|
me.collapseTool.setType('expand-' + me.expandDirection);
|
|
}
|
|
if (!internal) {
|
|
me.fireEvent('collapse', me);
|
|
}
|
|
|
|
|
|
if (animated && me.collapseTool) {
|
|
me.collapseTool.enable();
|
|
}
|
|
},
|
|
|
|
|
|
expand: function(animate) {
|
|
var me = this;
|
|
if (!me.collapsed || me.fireEvent('beforeexpand', me, animate) === false) {
|
|
return false;
|
|
}
|
|
|
|
var i = 0,
|
|
l = me.hiddenDocked.length,
|
|
direction = me.expandDirection,
|
|
height = me.getHeight(),
|
|
width = me.getWidth(),
|
|
pos, anim;
|
|
|
|
|
|
if (animate && me.collapseTool) {
|
|
me.collapseTool.disable();
|
|
}
|
|
|
|
|
|
|
|
for (; i < l; i++) {
|
|
me.hiddenDocked[i].hidden = false;
|
|
me.hiddenDocked[i].el.show();
|
|
}
|
|
if (me.reExpander) {
|
|
if (me.reExpander.temporary) {
|
|
me.reExpander.hide();
|
|
} else {
|
|
me.reExpander.removeClsWithUI(me.collapsedCls);
|
|
me.reExpander.removeClsWithUI(me.collapsedCls + '-' + me.reExpander.dock);
|
|
if (me.border && (!me.frame || (me.frame && Ext.supports.CSS3BorderRadius))) {
|
|
me.reExpander.removeClsWithUI(me.collapsedCls + '-border-' + me.reExpander.dock);
|
|
}
|
|
me.reExpander.updateFrame();
|
|
}
|
|
}
|
|
|
|
|
|
if (me.collapseTool) {
|
|
me.collapseTool.setType('collapse-' + me.collapseDirection);
|
|
}
|
|
|
|
|
|
me.body.setStyle('display', '');
|
|
me.body.dom.scrollTop = me.saveScrollTop;
|
|
|
|
|
|
me.collapsed = false;
|
|
|
|
|
|
me.removeClsWithUI(me.collapsedCls);
|
|
|
|
|
|
|
|
|
|
anim = {
|
|
to: {
|
|
},
|
|
from: {
|
|
height: height,
|
|
width: width
|
|
},
|
|
listeners: {
|
|
afteranimate: me.afterExpand,
|
|
scope: me
|
|
}
|
|
};
|
|
|
|
if ((direction == Ext.Component.DIRECTION_TOP) || (direction == Ext.Component.DIRECTION_BOTTOM)) {
|
|
|
|
|
|
|
|
me.collapseMemento.restore('height', false);
|
|
|
|
|
|
if (me.height === undefined) {
|
|
me.setCalculatedSize(me.width, null);
|
|
anim.to.height = me.getHeight();
|
|
|
|
|
|
me.setCalculatedSize(me.width, anim.from.height);
|
|
}
|
|
|
|
|
|
else if (me.savedFlex) {
|
|
me.flex = me.savedFlex;
|
|
anim.to.height = me.ownerCt.layout.calculateChildBox(me).height;
|
|
delete me.flex;
|
|
}
|
|
|
|
else {
|
|
anim.to.height = me.height;
|
|
}
|
|
|
|
|
|
if (direction == Ext.Component.DIRECTION_TOP) {
|
|
pos = me.getPosition()[1] - Ext.fly(me.el.dom.offsetParent).getRegion().top;
|
|
anim.from.top = pos;
|
|
anim.to.top = pos - (anim.to.height - height);
|
|
}
|
|
} else if ((direction == Ext.Component.DIRECTION_LEFT) || (direction == Ext.Component.DIRECTION_RIGHT)) {
|
|
|
|
|
|
|
|
me.collapseMemento.restore('width', false);
|
|
|
|
|
|
if (me.width === undefined) {
|
|
me.setCalculatedSize(null, me.height);
|
|
anim.to.width = me.getWidth();
|
|
|
|
|
|
me.setCalculatedSize(anim.from.width, me.height);
|
|
}
|
|
|
|
|
|
else if (me.savedFlex) {
|
|
me.flex = me.savedFlex;
|
|
anim.to.width = me.ownerCt.layout.calculateChildBox(me).width;
|
|
delete me.flex;
|
|
}
|
|
|
|
else {
|
|
anim.to.width = me.width;
|
|
}
|
|
|
|
|
|
if (direction == Ext.Component.DIRECTION_LEFT) {
|
|
pos = me.getPosition()[0] - Ext.fly(me.el.dom.offsetParent).getRegion().left;
|
|
anim.from.left = pos;
|
|
anim.to.left = pos - (anim.to.width - width);
|
|
}
|
|
}
|
|
|
|
if (animate) {
|
|
me.animate(anim);
|
|
} else {
|
|
me.setCalculatedSize(anim.to.width, anim.to.height);
|
|
if (anim.to.x) {
|
|
me.setLeft(anim.to.x);
|
|
}
|
|
if (anim.to.y) {
|
|
me.setTop(anim.to.y);
|
|
}
|
|
me.afterExpand(false);
|
|
}
|
|
|
|
return me;
|
|
},
|
|
|
|
afterExpand: function(animated) {
|
|
var me = this;
|
|
|
|
|
|
if (me.savedFlex) {
|
|
me.flex = me.savedFlex;
|
|
delete me.savedFlex;
|
|
delete me.width;
|
|
delete me.height;
|
|
}
|
|
|
|
|
|
if (me.collapseMemento) {
|
|
me.collapseMemento.restoreAll();
|
|
}
|
|
|
|
if (animated && me.ownerCt) {
|
|
|
|
|
|
Ext.defer(me.ownerCt.doLayout, Ext.isIE6 ? 1 : 0, me);
|
|
}
|
|
|
|
if (me.resizer) {
|
|
me.resizer.enable();
|
|
}
|
|
|
|
me.fireEvent('expand', me);
|
|
|
|
|
|
if (animated && me.collapseTool) {
|
|
me.collapseTool.enable();
|
|
}
|
|
},
|
|
|
|
|
|
toggleCollapse: function() {
|
|
if (this.collapsed) {
|
|
this.expand(this.animCollapse);
|
|
} else {
|
|
this.collapse(this.collapseDirection, this.animCollapse);
|
|
}
|
|
return this;
|
|
},
|
|
|
|
|
|
getKeyMap : function(){
|
|
if(!this.keyMap){
|
|
this.keyMap = Ext.create('Ext.util.KeyMap', this.el, this.keys);
|
|
}
|
|
return this.keyMap;
|
|
},
|
|
|
|
|
|
initDraggable : function(){
|
|
|
|
this.dd = Ext.create('Ext.panel.DD', this, Ext.isBoolean(this.draggable) ? null : this.draggable);
|
|
},
|
|
|
|
|
|
ghostTools : function() {
|
|
var tools = [],
|
|
headerTools = this.header.query('tool[hidden=false]');
|
|
|
|
if (headerTools.length) {
|
|
Ext.each(headerTools, function(tool) {
|
|
|
|
|
|
|
|
|
|
tools.push({
|
|
type: tool.type
|
|
});
|
|
});
|
|
} else {
|
|
tools = [{
|
|
type: 'placeholder'
|
|
}];
|
|
}
|
|
return tools;
|
|
},
|
|
|
|
|
|
ghost: function(cls) {
|
|
var me = this,
|
|
ghostPanel = me.ghostPanel,
|
|
box = me.getBox(),
|
|
header;
|
|
|
|
if (!ghostPanel) {
|
|
ghostPanel = Ext.create('Ext.panel.Panel', {
|
|
renderTo: me.floating ? me.el.dom.parentNode : document.body,
|
|
floating: {
|
|
shadow: false
|
|
},
|
|
frame: Ext.supports.CSS3BorderRadius ? me.frame : false,
|
|
overlapHeader: me.overlapHeader,
|
|
headerPosition: me.headerPosition,
|
|
baseCls: me.baseCls,
|
|
cls: me.baseCls + '-ghost ' + (cls ||'')
|
|
});
|
|
me.ghostPanel = ghostPanel;
|
|
}
|
|
ghostPanel.floatParent = me.floatParent;
|
|
if (me.floating) {
|
|
ghostPanel.setZIndex(Ext.Number.from(me.el.getStyle('zIndex'), 0));
|
|
} else {
|
|
ghostPanel.toFront();
|
|
}
|
|
header = ghostPanel.header;
|
|
|
|
if (header) {
|
|
header.suspendLayout = true;
|
|
Ext.Array.forEach(header.query('tool'), function(tool){
|
|
header.remove(tool);
|
|
});
|
|
header.suspendLayout = false;
|
|
}
|
|
ghostPanel.addTool(me.ghostTools());
|
|
ghostPanel.setTitle(me.title);
|
|
ghostPanel.setIconCls(me.iconCls);
|
|
|
|
ghostPanel.el.show();
|
|
ghostPanel.setPosition(box.x, box.y);
|
|
ghostPanel.setSize(box.width, box.height);
|
|
me.el.hide();
|
|
if (me.floatingItems) {
|
|
me.floatingItems.hide();
|
|
}
|
|
return ghostPanel;
|
|
},
|
|
|
|
|
|
unghost: function(show, matchPosition) {
|
|
var me = this;
|
|
if (!me.ghostPanel) {
|
|
return;
|
|
}
|
|
if (show !== false) {
|
|
me.el.show();
|
|
if (matchPosition !== false) {
|
|
me.setPosition(me.ghostPanel.getPosition());
|
|
}
|
|
if (me.floatingItems) {
|
|
me.floatingItems.show();
|
|
}
|
|
Ext.defer(me.focus, 10, me);
|
|
}
|
|
me.ghostPanel.el.hide();
|
|
},
|
|
|
|
initResizable: function(resizable) {
|
|
if (this.collapsed) {
|
|
resizable.disabled = true;
|
|
}
|
|
this.callParent([resizable]);
|
|
}
|
|
}, function(){
|
|
this.prototype.animCollapse = Ext.enableFx;
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.layout.component.Tip', {
|
|
|
|
|
|
|
|
alias: ['layout.tip'],
|
|
|
|
extend: 'Ext.layout.component.Dock',
|
|
|
|
|
|
|
|
type: 'tip',
|
|
|
|
onLayout: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
el = owner.el,
|
|
minWidth,
|
|
maxWidth,
|
|
naturalWidth,
|
|
constrainedWidth,
|
|
xy = el.getXY();
|
|
|
|
|
|
el.setXY([-9999,-9999]);
|
|
|
|
|
|
this.callParent(arguments);
|
|
|
|
|
|
if (!Ext.isNumber(width)) {
|
|
minWidth = owner.minWidth;
|
|
maxWidth = owner.maxWidth;
|
|
|
|
if (Ext.isStrict && (Ext.isIE6 || Ext.isIE7)) {
|
|
constrainedWidth = me.doAutoWidth();
|
|
} else {
|
|
naturalWidth = el.getWidth();
|
|
}
|
|
if (naturalWidth < minWidth) {
|
|
constrainedWidth = minWidth;
|
|
}
|
|
else if (naturalWidth > maxWidth) {
|
|
constrainedWidth = maxWidth;
|
|
}
|
|
if (constrainedWidth) {
|
|
this.callParent([constrainedWidth, height]);
|
|
}
|
|
}
|
|
|
|
|
|
el.setXY(xy);
|
|
},
|
|
|
|
doAutoWidth: function(){
|
|
var me = this,
|
|
owner = me.owner,
|
|
body = owner.body,
|
|
width = body.getTextWidth();
|
|
|
|
if (owner.header) {
|
|
width = Math.max(width, owner.header.getWidth());
|
|
}
|
|
if (!Ext.isDefined(me.frameWidth)) {
|
|
me.frameWidth = owner.el.getWidth() - body.getWidth();
|
|
}
|
|
width += me.frameWidth + body.getPadding('lr');
|
|
return width;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.tip.Tip', {
|
|
extend: 'Ext.panel.Panel',
|
|
requires: [ 'Ext.layout.component.Tip' ],
|
|
alternateClassName: 'Ext.Tip',
|
|
|
|
|
|
|
|
minWidth : 40,
|
|
|
|
maxWidth : 300,
|
|
|
|
shadow : "sides",
|
|
|
|
|
|
defaultAlign : "tl-bl?",
|
|
|
|
constrainPosition : true,
|
|
|
|
|
|
frame: false,
|
|
|
|
|
|
autoRender: true,
|
|
hidden: true,
|
|
baseCls: Ext.baseCSSPrefix + 'tip',
|
|
floating: {
|
|
shadow: true,
|
|
shim: true,
|
|
constrain: true
|
|
},
|
|
focusOnToFront: false,
|
|
componentLayout: 'tip',
|
|
|
|
|
|
closeAction: 'hide',
|
|
|
|
ariaRole: 'tooltip',
|
|
|
|
initComponent: function() {
|
|
var me = this;
|
|
|
|
me.floating = Ext.apply({}, {shadow: me.shadow}, 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);
|
|
}
|
|
},
|
|
|
|
|
|
showBy : function(el, pos) {
|
|
this.showAt(this.el.getAlignToXY(el, pos || this.defaultAlign));
|
|
},
|
|
|
|
|
|
initDraggable : function(){
|
|
var me = this;
|
|
me.draggable = {
|
|
el: me.getDragEl(),
|
|
delegate: me.header.el,
|
|
constrain: me,
|
|
constrainTo: me.el.getScopeParent()
|
|
};
|
|
|
|
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',
|
|
|
|
|
|
|
|
|
|
showDelay: 500,
|
|
|
|
hideDelay: 200,
|
|
|
|
dismissDelay: 5000,
|
|
|
|
|
|
trackMouse: false,
|
|
|
|
|
|
anchorToTarget: true,
|
|
|
|
anchorOffset: 0,
|
|
|
|
|
|
|
|
targetCounter: 0,
|
|
quickShowInterval: 250,
|
|
|
|
|
|
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({
|
|
cls: Ext.baseCSSPrefix + 'tip-anchor ' + me.anchorCls
|
|
});
|
|
},
|
|
|
|
|
|
afterRender: function() {
|
|
var me = this,
|
|
zIndex;
|
|
|
|
me.callParent(arguments);
|
|
zIndex = parseInt(me.el.getZIndex(), 10) || 0;
|
|
me.anchorEl.setStyle('z-index', zIndex + 1).setVisibilityMode(Ext.Element.DISPLAY);
|
|
},
|
|
|
|
|
|
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.getScopeParent());
|
|
}
|
|
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;
|
|
if (me.delegate) {
|
|
me.anchorTarget = me.triggerElement;
|
|
}
|
|
if (me.anchor) {
|
|
me.targetCounter++;
|
|
var offsets = me.getOffsets(),
|
|
xy = (me.anchorToTarget && !me.trackMouse) ? me.el.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,
|
|
t;
|
|
|
|
if (me.disabled || e.within(me.target.dom, true)) {
|
|
return;
|
|
}
|
|
t = e.getTarget(me.delegate);
|
|
if (t) {
|
|
me.triggerElement = t;
|
|
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.show, me.showDelay, me);
|
|
}
|
|
}
|
|
else if (!me.hidden && me.autoHide !== false) {
|
|
me.show();
|
|
}
|
|
},
|
|
|
|
|
|
onTargetOut: function(e) {
|
|
var me = this;
|
|
if (me.disabled || e.within(me.target.dom, true)) {
|
|
return;
|
|
}
|
|
me.clearTimer('show');
|
|
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;
|
|
}
|
|
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();
|
|
|
|
|
|
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);
|
|
}
|
|
|
|
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();
|
|
}
|
|
},
|
|
|
|
|
|
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);
|
|
},
|
|
|
|
|
|
setPagePosition: function(x, y) {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
if (me.anchor) {
|
|
me.syncAnchor();
|
|
}
|
|
},
|
|
|
|
|
|
clearTimer: function(name) {
|
|
name = name + 'Timer';
|
|
clearTimeout(this[name]);
|
|
delete this[name];
|
|
},
|
|
|
|
|
|
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.autoHide !== true && !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',
|
|
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"
|
|
},
|
|
|
|
|
|
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(),
|
|
elTarget,
|
|
cfg,
|
|
ns,
|
|
tipConfig,
|
|
autoHide;
|
|
|
|
if (me.disabled) {
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
me.targetXY = e.getXY();
|
|
|
|
if(!target || target.nodeType !== 1 || target == document || target == document.body){
|
|
return;
|
|
}
|
|
|
|
if (me.activeTarget && ((target == me.activeTarget.el) || Ext.fly(me.activeTarget.el).contains(target))) {
|
|
me.clearTimer('hide');
|
|
me.show();
|
|
return;
|
|
}
|
|
|
|
if (target) {
|
|
Ext.Object.each(me.targets, function(key, value) {
|
|
var targetEl = Ext.fly(value.target);
|
|
if (targetEl && (targetEl.dom === target || targetEl.contains(target))) {
|
|
elTarget = targetEl.dom;
|
|
return false;
|
|
}
|
|
});
|
|
if (elTarget) {
|
|
me.activeTarget = me.targets[elTarget.id];
|
|
me.activeTarget.el = target;
|
|
me.anchor = me.activeTarget.anchor;
|
|
if (me.anchor) {
|
|
me.anchorTarget = target;
|
|
}
|
|
me.delayShow();
|
|
return;
|
|
}
|
|
}
|
|
|
|
elTarget = Ext.get(target);
|
|
cfg = me.tagConfig;
|
|
ns = cfg.namespace;
|
|
tipConfig = me.getTipCfg(e);
|
|
|
|
if (tipConfig) {
|
|
|
|
|
|
|
|
if (tipConfig.target) {
|
|
target = tipConfig.target;
|
|
elTarget = Ext.get(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)
|
|
|
|
};
|
|
me.anchor = elTarget.getAttribute(ns + cfg.anchor);
|
|
if (me.anchor) {
|
|
me.anchorTarget = target;
|
|
}
|
|
me.delayShow();
|
|
}
|
|
},
|
|
|
|
|
|
onTargetOut : function(e){
|
|
var me = this;
|
|
|
|
|
|
if (me.activeTarget && e.within(me.activeTarget.el) && !me.getTipCfg(e)) {
|
|
return;
|
|
}
|
|
|
|
me.clearTimer('show');
|
|
if (me.autoHide !== false) {
|
|
me.delayHide();
|
|
}
|
|
},
|
|
|
|
|
|
showAt : function(xy){
|
|
var me = this,
|
|
target = me.activeTarget;
|
|
|
|
if (target) {
|
|
if (!me.rendered) {
|
|
me.render(Ext.getBody());
|
|
me.activeTarget = target;
|
|
}
|
|
if (target.title) {
|
|
me.setTitle(target.title || '');
|
|
me.header.show();
|
|
} else {
|
|
me.header.hide();
|
|
}
|
|
me.body.update(target.text);
|
|
me.autoHide = target.autoHide;
|
|
me.dismissDelay = target.dismissDelay || me.dismissDelay;
|
|
if (me.lastCls) {
|
|
me.el.removeCls(me.lastCls);
|
|
delete me.lastCls;
|
|
}
|
|
if (target.cls) {
|
|
me.el.addCls(target.cls);
|
|
me.lastCls = target.cls;
|
|
}
|
|
|
|
me.setWidth(target.width);
|
|
|
|
if (me.anchor) {
|
|
me.constrainPosition = false;
|
|
} else if (target.align) {
|
|
xy = me.el.getAlignToXY(target.el, target.align);
|
|
me.constrainPosition = false;
|
|
}else{
|
|
me.constrainPosition = true;
|
|
}
|
|
}
|
|
me.callParent([xy]);
|
|
},
|
|
|
|
|
|
hide: function(){
|
|
delete this.activeTarget;
|
|
this.callParent();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.tip.QuickTipManager', function() {
|
|
var tip,
|
|
disabled = false;
|
|
|
|
return {
|
|
requires: ['Ext.tip.QuickTip'],
|
|
singleton: true,
|
|
alternateClassName: 'Ext.QuickTips',
|
|
|
|
|
|
init : function (autoRender, config) {
|
|
if (!tip) {
|
|
if (!Ext.isReady) {
|
|
Ext.onReady(function(){
|
|
Ext.tip.QuickTipManager.init(autoRender);
|
|
});
|
|
return;
|
|
}
|
|
|
|
var tipConfig = Ext.apply({ disabled: disabled }, 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;
|
|
|
|
}
|
|
|
|
tip = Ext.create(className || 'Ext.tip.QuickTip', tipConfig);
|
|
}
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
if (tip) {
|
|
var undef;
|
|
tip.destroy();
|
|
tip = undef;
|
|
}
|
|
},
|
|
|
|
|
|
ddDisable : function(){
|
|
|
|
if(tip && !disabled){
|
|
tip.disable();
|
|
}
|
|
},
|
|
|
|
|
|
ddEnable : function(){
|
|
|
|
if(tip && !disabled){
|
|
tip.enable();
|
|
}
|
|
},
|
|
|
|
|
|
enable : function(){
|
|
if(tip){
|
|
tip.enable();
|
|
}
|
|
disabled = false;
|
|
},
|
|
|
|
|
|
disable : function(){
|
|
if(tip){
|
|
tip.disable();
|
|
}
|
|
disabled = true;
|
|
},
|
|
|
|
|
|
isEnabled : function(){
|
|
return tip !== undefined && !tip.disabled;
|
|
},
|
|
|
|
|
|
getQuickTip : function(){
|
|
return tip;
|
|
},
|
|
|
|
|
|
register : function(){
|
|
tip.register.apply(tip, arguments);
|
|
},
|
|
|
|
|
|
unregister : function(){
|
|
tip.unregister.apply(tip, arguments);
|
|
},
|
|
|
|
|
|
tips : function(){
|
|
tip.register.apply(tip, arguments);
|
|
}
|
|
};
|
|
}());
|
|
|
|
Ext.define('Ext.app.Application', {
|
|
extend: 'Ext.app.Controller',
|
|
|
|
requires: [
|
|
'Ext.ModelManager',
|
|
'Ext.data.Model',
|
|
'Ext.data.StoreManager',
|
|
'Ext.tip.QuickTipManager',
|
|
'Ext.ComponentManager',
|
|
'Ext.app.EventBus'
|
|
],
|
|
|
|
|
|
|
|
|
|
scope: undefined,
|
|
|
|
|
|
enableQuickTips: true,
|
|
|
|
|
|
|
|
|
|
appFolder: 'app',
|
|
|
|
|
|
autoCreateViewport: false,
|
|
|
|
|
|
constructor: function(config) {
|
|
config = config || {};
|
|
Ext.apply(this, config);
|
|
|
|
var requires = config.requires || [];
|
|
|
|
Ext.Loader.setPath(this.name, this.appFolder);
|
|
|
|
if (this.paths) {
|
|
Ext.Object.each(this.paths, function(key, value) {
|
|
Ext.Loader.setPath(key, value);
|
|
});
|
|
}
|
|
|
|
this.callParent(arguments);
|
|
|
|
this.eventbus = Ext.create('Ext.app.EventBus');
|
|
|
|
var controllers = Ext.Array.from(this.controllers),
|
|
ln = controllers && controllers.length,
|
|
i, controller;
|
|
|
|
this.controllers = Ext.create('Ext.util.MixedCollection');
|
|
|
|
if (this.autoCreateViewport) {
|
|
requires.push(this.getModuleClassName('Viewport', 'view'));
|
|
}
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
requires.push(this.getModuleClassName(controllers[i], 'controller'));
|
|
}
|
|
|
|
Ext.require(requires);
|
|
|
|
Ext.onReady(function() {
|
|
for (i = 0; i < ln; i++) {
|
|
controller = this.getController(controllers[i]);
|
|
controller.init(this);
|
|
}
|
|
|
|
this.onBeforeLaunch.call(this);
|
|
}, this);
|
|
},
|
|
|
|
control: function(selectors, listeners, controller) {
|
|
this.eventbus.control(selectors, listeners, controller);
|
|
},
|
|
|
|
|
|
launch: Ext.emptyFn,
|
|
|
|
|
|
onBeforeLaunch: function() {
|
|
if (this.enableQuickTips) {
|
|
Ext.tip.QuickTipManager.init();
|
|
}
|
|
|
|
if (this.autoCreateViewport) {
|
|
this.getView('Viewport').create();
|
|
}
|
|
|
|
this.launch.call(this.scope || this);
|
|
this.launched = true;
|
|
this.fireEvent('launch', this);
|
|
|
|
this.controllers.each(function(controller) {
|
|
controller.onLaunch(this);
|
|
}, this);
|
|
},
|
|
|
|
getModuleClassName: function(name, type) {
|
|
var namespace = Ext.Loader.getPrefix(name);
|
|
|
|
if (namespace.length > 0 && namespace !== name) {
|
|
return name;
|
|
}
|
|
|
|
return this.name + '.' + type + '.' + name;
|
|
},
|
|
|
|
getController: function(name) {
|
|
var controller = this.controllers.get(name);
|
|
|
|
if (!controller) {
|
|
controller = Ext.create(this.getModuleClassName(name, 'controller'), {
|
|
application: this,
|
|
id: name
|
|
});
|
|
|
|
this.controllers.add(controller);
|
|
}
|
|
|
|
return controller;
|
|
},
|
|
|
|
getStore: function(name) {
|
|
var store = Ext.StoreManager.get(name);
|
|
|
|
if (!store) {
|
|
store = Ext.create(this.getModuleClassName(name, 'store'), {
|
|
storeId: name
|
|
});
|
|
}
|
|
|
|
return store;
|
|
},
|
|
|
|
getModel: function(model) {
|
|
model = this.getModuleClassName(model, 'model');
|
|
|
|
return Ext.ModelManager.getModel(model);
|
|
},
|
|
|
|
getView: function(view) {
|
|
view = this.getModuleClassName(view, 'view');
|
|
|
|
return Ext.ClassManager.get(view);
|
|
}
|
|
});
|
|
|
|
|
|
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.store,
|
|
len = store.getCount(),
|
|
ratio = items.length / len,
|
|
previouslyPlacedCallouts = [],
|
|
i,
|
|
count,
|
|
j,
|
|
p;
|
|
|
|
for (i = 0, count = 0; i < len; i++) {
|
|
for (j = 0; j < ratio; j++) {
|
|
var item = items[count],
|
|
label = group[count],
|
|
storeItem = store.getAt(i),
|
|
display;
|
|
|
|
display = 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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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.styles,
|
|
width = styles.width,
|
|
height = styles.height,
|
|
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 = Ext.create('widget.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'
|
|
},
|
|
|
|
|
|
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) {
|
|
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(),
|
|
item;
|
|
|
|
if (surface) {
|
|
while (me.getCount() > 0) {
|
|
item = me.first();
|
|
me.remove(item);
|
|
surface.remove(item);
|
|
}
|
|
}
|
|
me.clearListeners();
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.layout.component.Auto', {
|
|
|
|
|
|
|
|
alias: 'layout.autocomponent',
|
|
|
|
extend: 'Ext.layout.component.Component',
|
|
|
|
|
|
|
|
type: 'autocomponent',
|
|
|
|
onLayout : function(width, height) {
|
|
this.setTargetSize(width, height);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.chart.theme.Theme', {
|
|
|
|
|
|
|
|
requires: ['Ext.draw.Color'],
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
function() {
|
|
|
|
|
|
(function() {
|
|
Ext.chart.theme = function(config, base) {
|
|
config = config || {};
|
|
var i = 0, 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);
|
|
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);
|
|
};
|
|
})();
|
|
});
|
|
|
|
|
|
Ext.define('Ext.chart.Mask', {
|
|
require: ['Ext.chart.MaskLayer'],
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
me.addEvents('select');
|
|
|
|
if (config) {
|
|
Ext.apply(me, config);
|
|
}
|
|
if (me.mask) {
|
|
me.on('afterrender', function() {
|
|
|
|
var comp = Ext.create('Ext.chart.MaskLayer', {
|
|
renderTo: me.el
|
|
});
|
|
comp.el.on({
|
|
'mousemove': function(e) {
|
|
me.onMouseMove(e);
|
|
},
|
|
'mouseup': function(e) {
|
|
me.resized(e);
|
|
}
|
|
});
|
|
|
|
var resizeHandler = Ext.create('Ext.resizer.Resizer', {
|
|
el: comp.el,
|
|
handles: 'all',
|
|
pinned: true
|
|
});
|
|
resizeHandler.on({
|
|
'resize': function(e) {
|
|
me.resized(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.7,
|
|
hidden: true,
|
|
stroke: '#444'
|
|
});
|
|
}, me, { single: true });
|
|
}
|
|
},
|
|
|
|
resized: function(e) {
|
|
var me = this,
|
|
bbox = me.bbox || me.chartBBox,
|
|
x = bbox.x,
|
|
y = bbox.y,
|
|
width = bbox.width,
|
|
height = bbox.height,
|
|
box = me.mask.getBox(true),
|
|
max = Math.max,
|
|
min = Math.min,
|
|
staticX = box.x - x,
|
|
staticY = box.y - y;
|
|
|
|
staticX = max(staticX, x);
|
|
staticY = max(staticY, y);
|
|
staticX = min(staticX, width);
|
|
staticY = min(staticY, height);
|
|
box.x = staticX;
|
|
box.y = staticY;
|
|
me.fireEvent('select', me, box);
|
|
},
|
|
|
|
onMouseUp: function(e) {
|
|
var me = this,
|
|
bbox = me.bbox || me.chartBBox,
|
|
sel = me.maskSelection;
|
|
me.maskMouseDown = false;
|
|
me.mouseDown = false;
|
|
if (me.mouseMoved) {
|
|
me.onMouseMove(e);
|
|
me.mouseMoved = false;
|
|
me.fireEvent('select', me, {
|
|
x: sel.x - bbox.x,
|
|
y: sel.y - bbox.y,
|
|
width: sel.width,
|
|
height: sel.height
|
|
});
|
|
}
|
|
},
|
|
|
|
onMouseDown: function(e) {
|
|
var me = this;
|
|
me.mouseDown = true;
|
|
me.mouseMoved = false;
|
|
me.maskMouseDown = {
|
|
x: e.getPageX() - me.el.getX(),
|
|
y: e.getPageY() - me.el.getY()
|
|
};
|
|
},
|
|
|
|
onMouseMove: 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),
|
|
posX = e.getPageX(),
|
|
posY = e.getPageY(),
|
|
staticX = posX - me.el.getX(),
|
|
staticY = posY - me.el.getY(),
|
|
maskMouseDown = me.maskMouseDown,
|
|
path;
|
|
|
|
me.mouseMoved = me.mouseDown;
|
|
staticX = max(staticX, x);
|
|
staticY = max(staticY, y);
|
|
staticX = min(staticX, width);
|
|
staticY = min(staticY, height);
|
|
if (maskMouseDown && me.mouseDown) {
|
|
if (mask == 'horizontal') {
|
|
staticY = y;
|
|
maskMouseDown.y = height;
|
|
posY = me.el.getY() + bbox.height + me.insetPadding;
|
|
}
|
|
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,
|
|
y: height > 0 ? staticY : staticY + height,
|
|
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,
|
|
fill: me.maskMouseDown ? me.maskSprite.stroke : false,
|
|
'stroke-width': mask === true ? 1 : 3,
|
|
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', {
|
|
|
|
constructor: function() {
|
|
this.originalStore = this.store;
|
|
},
|
|
|
|
|
|
setZoom: function(zoomConfig) {
|
|
var me = this,
|
|
axes = me.axes,
|
|
bbox = me.chartBBox,
|
|
xScale = 1 / bbox.width,
|
|
yScale = 1 / bbox.height,
|
|
zoomer = {
|
|
x : zoomConfig.x * xScale,
|
|
y : zoomConfig.y * yScale,
|
|
width : zoomConfig.width * xScale,
|
|
height : zoomConfig.height * yScale
|
|
};
|
|
axes.each(function(axis) {
|
|
var ends = axis.calcEnds();
|
|
if (axis.position == 'bottom' || axis.position == 'top') {
|
|
var from = (ends.to - ends.from) * zoomer.x + ends.from,
|
|
to = (ends.to - ends.from) * zoomer.width + from;
|
|
axis.minimum = from;
|
|
axis.maximum = to;
|
|
} else {
|
|
var to = (ends.to - ends.from) * (1 - zoomer.y) + ends.from,
|
|
from = to - (ends.to - ends.from) * zoomer.height;
|
|
axis.minimum = from;
|
|
axis.maximum = to;
|
|
}
|
|
});
|
|
me.redraw(false);
|
|
},
|
|
|
|
|
|
restoreZoom: function() {
|
|
this.store = this.substore = this.originalStore;
|
|
this.redraw(true);
|
|
}
|
|
|
|
});
|
|
|
|
|
|
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.draw.Surface', {
|
|
|
|
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
requires: ['Ext.draw.CompositeSprite'],
|
|
uses: ['Ext.draw.engine.Svg', 'Ext.draw.engine.Vml'],
|
|
|
|
separatorRe: /[, ]+/,
|
|
|
|
statics: {
|
|
|
|
create: function(config, enginePriority) {
|
|
enginePriority = enginePriority || ['Svg', 'Vml'];
|
|
|
|
var i = 0,
|
|
len = enginePriority.length,
|
|
surfaceClass;
|
|
|
|
for (; i < len; i++) {
|
|
if (Ext.supports[enginePriority[i]]) {
|
|
return Ext.create('Ext.draw.engine.' + enginePriority[i], config);
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
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: "#000",
|
|
"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'
|
|
);
|
|
|
|
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() {
|
|
var gradients = this.gradients;
|
|
if (gradients) {
|
|
Ext.each(gradients, this.addGradient, this);
|
|
}
|
|
},
|
|
|
|
|
|
initItems: function() {
|
|
var items = this.items;
|
|
this.items = Ext.create('Ext.draw.CompositeSprite');
|
|
this.groups = Ext.create('Ext.draw.CompositeSprite');
|
|
if (items) {
|
|
this.add(items);
|
|
}
|
|
},
|
|
|
|
|
|
initBackground: function(config) {
|
|
var me = this,
|
|
width = me.width,
|
|
height = me.height,
|
|
gradientId, gradient, backgroundSprite;
|
|
if (config) {
|
|
if (config.gradient) {
|
|
gradient = config.gradient;
|
|
gradientId = gradient.id;
|
|
me.addGradient(gradient);
|
|
me.background = me.add({
|
|
type: 'rect',
|
|
x: 0,
|
|
y: 0,
|
|
width: width,
|
|
height: height,
|
|
fill: 'url(#' + gradientId + ')'
|
|
});
|
|
} else if (config.fill) {
|
|
me.background = me.add({
|
|
type: 'rect',
|
|
x: 0,
|
|
y: 0,
|
|
width: width,
|
|
height: height,
|
|
fill: config.fill
|
|
});
|
|
} else if (config.image) {
|
|
me.background = me.add({
|
|
type: 'image',
|
|
x: 0,
|
|
y: 0,
|
|
width: width,
|
|
height: height,
|
|
src: config.image
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
setSize: function(w, h) {
|
|
if (this.background) {
|
|
this.background.setAttributes({
|
|
width: w,
|
|
height: h,
|
|
hidden: false
|
|
}, true);
|
|
}
|
|
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);
|
|
},
|
|
|
|
|
|
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,
|
|
index;
|
|
|
|
var hasMultipleArgs = args.length > 1;
|
|
if (hasMultipleArgs || Ext.isArray(args[0])) {
|
|
var items = hasMultipleArgs ? args : args[0],
|
|
results = [],
|
|
i, ln, item;
|
|
|
|
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);
|
|
this.groups.each(function(item) {
|
|
item.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,
|
|
height = me.height,
|
|
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;
|
|
|
|
if (viewBoxWidth * relativeHeight < width) {
|
|
viewBoxX -= (width - viewBoxWidth * relativeHeight) / 2 / relativeHeight;
|
|
}
|
|
if (viewBoxHeight * relativeWidth < height) {
|
|
viewBoxY -= (height - viewBoxHeight * relativeWidth) / 2 / relativeWidth;
|
|
}
|
|
|
|
size = 1 / Math.min(viewBoxWidth, relativeHeight);
|
|
|
|
me.viewBoxShift = {
|
|
dx: -viewBoxX,
|
|
dy: -viewBoxY,
|
|
scale: size
|
|
};
|
|
}
|
|
},
|
|
|
|
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) {
|
|
sprite.bbox.transform = 0;
|
|
this.transform(sprite);
|
|
|
|
var me = this,
|
|
dirty = false,
|
|
attr = sprite.attr;
|
|
|
|
if (attr.translation.x != null || attr.translation.y != null) {
|
|
me.translate(sprite);
|
|
dirty = true;
|
|
}
|
|
if (attr.scaling.x != null || attr.scaling.y != null) {
|
|
me.scale(sprite);
|
|
dirty = true;
|
|
}
|
|
if (attr.rotation.degrees != null) {
|
|
me.rotate(sprite);
|
|
dirty = true;
|
|
}
|
|
if (dirty) {
|
|
sprite.bbox.transform = 0;
|
|
this.transform(sprite);
|
|
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);
|
|
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);
|
|
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, a.y, a.width, a.height, a.r);
|
|
},
|
|
|
|
|
|
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 = Ext.create('Ext.draw.CompositeSprite', {
|
|
surface: this
|
|
});
|
|
group.id = id || Ext.id(null, 'ext-surface-group-');
|
|
this.groups.add(group);
|
|
}
|
|
return group;
|
|
},
|
|
|
|
|
|
getGroup: function(id) {
|
|
if (typeof id == "string") {
|
|
var 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,
|
|
|
|
//@private Creates an item and appends it to the surface. Called
|
|
|
|
|
|
createItem: Ext.emptyFn,
|
|
|
|
|
|
getId: function() {
|
|
return this.id || (this.id = Ext.id(null, 'ext-surface-'));
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
delete this.domRef;
|
|
this.removeAll();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.component.Draw', {
|
|
|
|
|
|
|
|
alias: 'layout.draw',
|
|
|
|
extend: 'Ext.layout.component.Auto',
|
|
|
|
|
|
|
|
type: 'draw',
|
|
|
|
onLayout : function(width, height) {
|
|
this.owner.surface.setSize(width, height);
|
|
this.callParent(arguments);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.draw.Component', {
|
|
|
|
|
|
|
|
alias: 'widget.draw',
|
|
|
|
extend: 'Ext.Component',
|
|
|
|
requires: [
|
|
'Ext.draw.Surface',
|
|
'Ext.layout.component.Draw'
|
|
],
|
|
|
|
|
|
|
|
|
|
enginePriority: ['Svg', 'Vml'],
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'surface',
|
|
|
|
componentLayout: 'draw',
|
|
|
|
|
|
viewBox: true,
|
|
|
|
|
|
autoSize: false,
|
|
|
|
|
|
initComponent: function() {
|
|
this.callParent(arguments);
|
|
|
|
this.addEvents(
|
|
'mousedown',
|
|
'mouseup',
|
|
'mousemove',
|
|
'mouseenter',
|
|
'mouseleave',
|
|
'click'
|
|
);
|
|
},
|
|
|
|
|
|
onRender: function() {
|
|
var me = this,
|
|
viewBox = me.viewBox,
|
|
autoSize = me.autoSize,
|
|
bbox, items, width, height, x, y;
|
|
me.callParent(arguments);
|
|
|
|
if (me.createSurface() !== false) {
|
|
items = me.surface.items;
|
|
|
|
if (viewBox || autoSize) {
|
|
bbox = items.getBBox();
|
|
width = bbox.width;
|
|
height = bbox.height;
|
|
x = bbox.x;
|
|
y = bbox.y;
|
|
if (me.viewBox) {
|
|
me.surface.setViewBox(x, y, width, height);
|
|
}
|
|
else {
|
|
|
|
me.autoSizeSurface();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
//@private
|
|
|
|
autoSizeSurface: function() {
|
|
var me = this,
|
|
items = me.surface.items,
|
|
bbox = items.getBBox(),
|
|
width = bbox.width,
|
|
height = bbox.height;
|
|
items.setAttributes({
|
|
translate: {
|
|
x: -bbox.x,
|
|
|
|
y: -bbox.y + (+Ext.isOpera)
|
|
}
|
|
}, true);
|
|
if (me.rendered) {
|
|
me.setSize(width, height);
|
|
me.surface.setSize(width, height);
|
|
}
|
|
else {
|
|
me.surface.setSize(width, height);
|
|
}
|
|
me.el.setSize(width, height);
|
|
},
|
|
|
|
|
|
createSurface: function() {
|
|
var surface = Ext.draw.Surface.create(Ext.apply({}, {
|
|
width: this.width,
|
|
height: this.height,
|
|
renderTo: this.el
|
|
}, this.initialConfig));
|
|
if (!surface) {
|
|
|
|
return false;
|
|
}
|
|
this.surface = surface;
|
|
|
|
|
|
function refire(eventName) {
|
|
return function(e) {
|
|
this.fireEvent(eventName, e);
|
|
};
|
|
}
|
|
|
|
surface.on({
|
|
scope: this,
|
|
mouseup: refire('mouseup'),
|
|
mousedown: refire('mousedown'),
|
|
mousemove: refire('mousemove'),
|
|
mouseenter: refire('mouseenter'),
|
|
mouseleave: refire('mouseleave'),
|
|
click: refire('click')
|
|
});
|
|
},
|
|
|
|
|
|
|
|
onDestroy: function() {
|
|
var surface = this.surface;
|
|
if (surface) {
|
|
surface.destroy();
|
|
}
|
|
this.callParent(arguments);
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.chart.LegendItem', {
|
|
|
|
|
|
|
|
extend: 'Ext.draw.CompositeSprite',
|
|
|
|
requires: ['Ext.chart.Shape'],
|
|
|
|
|
|
|
|
|
|
x: 0,
|
|
y: 0,
|
|
zIndex: 500,
|
|
|
|
constructor: function(config) {
|
|
this.callParent(arguments);
|
|
this.createLegend(config);
|
|
},
|
|
|
|
|
|
createLegend: function(config) {
|
|
var me = this,
|
|
index = config.yFieldIndex,
|
|
series = me.series,
|
|
seriesType = series.type,
|
|
idx = me.yFieldIndex,
|
|
legend = me.legend,
|
|
surface = me.surface,
|
|
refX = legend.x + me.x,
|
|
refY = legend.y + me.y,
|
|
bbox, z = me.zIndex,
|
|
markerConfig, label, mask,
|
|
radius, toggle = false,
|
|
seriesStyle = Ext.apply(series.seriesStyle, series.style);
|
|
|
|
function getSeriesProp(name) {
|
|
var val = series[name];
|
|
return (Ext.isArray(val) ? val[idx] : val);
|
|
}
|
|
|
|
label = me.add('label', surface.add({
|
|
type: 'text',
|
|
x: 20,
|
|
y: 0,
|
|
zIndex: z || 0,
|
|
font: legend.labelFont,
|
|
text: getSeriesProp('title') || getSeriesProp('yField')
|
|
}));
|
|
|
|
|
|
if (seriesType === 'line' || seriesType === 'scatter') {
|
|
if(seriesType === 'line') {
|
|
me.add('line', surface.add({
|
|
type: 'path',
|
|
path: 'M0.5,0.5L16.5,0.5',
|
|
zIndex: z,
|
|
"stroke-width": series.lineWidth,
|
|
"stroke-linejoin": "round",
|
|
"stroke-dasharray": series.dash,
|
|
stroke: seriesStyle.stroke || '#000',
|
|
style: {
|
|
cursor: 'pointer'
|
|
}
|
|
}));
|
|
}
|
|
if (series.showMarkers || seriesType === 'scatter') {
|
|
markerConfig = Ext.apply(series.markerStyle, series.markerConfig || {});
|
|
me.add('marker', Ext.chart.Shape[markerConfig.type](surface, {
|
|
fill: markerConfig.fill,
|
|
x: 8.5,
|
|
y: 0.5,
|
|
zIndex: z,
|
|
radius: markerConfig.radius || markerConfig.size,
|
|
style: {
|
|
cursor: 'pointer'
|
|
}
|
|
}));
|
|
}
|
|
}
|
|
|
|
else {
|
|
me.add('box', surface.add({
|
|
type: 'rect',
|
|
zIndex: z,
|
|
x: 0,
|
|
y: 0,
|
|
width: 12,
|
|
height: 12,
|
|
fill: series.getLegendColor(index),
|
|
style: {
|
|
cursor: 'pointer'
|
|
}
|
|
}));
|
|
}
|
|
|
|
me.setAttributes({
|
|
hidden: false
|
|
}, true);
|
|
|
|
bbox = me.getBBox();
|
|
|
|
mask = me.add('mask', surface.add({
|
|
type: 'rect',
|
|
x: bbox.x,
|
|
y: bbox.y,
|
|
width: bbox.width || 20,
|
|
height: bbox.height || 20,
|
|
zIndex: (z || 0) + 1000,
|
|
fill: '#f00',
|
|
opacity: 0,
|
|
style: {
|
|
'cursor': 'pointer'
|
|
}
|
|
}));
|
|
|
|
|
|
me.on('mouseover', function() {
|
|
label.setStyle({
|
|
'font-weight': 'bold'
|
|
});
|
|
mask.setStyle({
|
|
'cursor': 'pointer'
|
|
});
|
|
series._index = index;
|
|
series.highlightItem();
|
|
}, me);
|
|
|
|
me.on('mouseout', function() {
|
|
label.setStyle({
|
|
'font-weight': 'normal'
|
|
});
|
|
series._index = index;
|
|
series.unHighlightItem();
|
|
}, me);
|
|
|
|
if (!series.visibleInLegend(index)) {
|
|
toggle = true;
|
|
label.setAttributes({
|
|
opacity: 0.5
|
|
}, true);
|
|
}
|
|
|
|
me.on('mousedown', function() {
|
|
if (!toggle) {
|
|
series.hideAll();
|
|
label.setAttributes({
|
|
opacity: 0.5
|
|
}, true);
|
|
} else {
|
|
series.showAll();
|
|
label.setAttributes({
|
|
opacity: 1
|
|
}, true);
|
|
}
|
|
toggle = !toggle;
|
|
}, me);
|
|
me.updatePosition({x:0, y:0});
|
|
},
|
|
|
|
|
|
updatePosition: function(relativeTo) {
|
|
var me = this,
|
|
items = me.items,
|
|
ln = items.length,
|
|
i = 0,
|
|
item;
|
|
if (!relativeTo) {
|
|
relativeTo = me.legend;
|
|
}
|
|
for (; i < ln; i++) {
|
|
item = items[i];
|
|
switch (item.type) {
|
|
case 'text':
|
|
item.setAttributes({
|
|
x: 20 + relativeTo.x + me.x,
|
|
y: relativeTo.y + me.y
|
|
}, true);
|
|
break;
|
|
case 'rect':
|
|
item.setAttributes({
|
|
translate: {
|
|
x: relativeTo.x + me.x,
|
|
y: relativeTo.y + me.y - 6
|
|
}
|
|
}, true);
|
|
break;
|
|
default:
|
|
item.setAttributes({
|
|
translate: {
|
|
x: relativeTo.x + me.x,
|
|
y: relativeTo.y + me.y
|
|
}
|
|
}, true);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.chart.Legend', {
|
|
|
|
|
|
|
|
requires: ['Ext.chart.LegendItem'],
|
|
|
|
|
|
|
|
|
|
visible: true,
|
|
|
|
|
|
position: 'bottom',
|
|
|
|
|
|
x: 0,
|
|
|
|
|
|
y: 0,
|
|
|
|
|
|
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;
|
|
me.createBox();
|
|
me.createItems();
|
|
if (!me.created && me.isDisplayed()) {
|
|
me.created = true;
|
|
|
|
|
|
me.chart.series.each(function(series) {
|
|
series.on('titlechange', function() {
|
|
me.create();
|
|
me.updatePosition();
|
|
});
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
isDisplayed: function() {
|
|
return this.visible && this.chart.series.findIndex('showInLegend', true) !== -1;
|
|
},
|
|
|
|
|
|
createItems: function() {
|
|
var me = this,
|
|
chart = me.chart,
|
|
surface = chart.surface,
|
|
items = me.items,
|
|
padding = me.padding,
|
|
itemSpacing = me.itemSpacing,
|
|
spacingOffset = 2,
|
|
maxWidth = 0,
|
|
maxHeight = 0,
|
|
totalWidth = 0,
|
|
totalHeight = 0,
|
|
vertical = me.isVertical,
|
|
math = Math,
|
|
mfloor = math.floor,
|
|
mmax = math.max,
|
|
index = 0,
|
|
i = 0,
|
|
len = items ? items.length : 0,
|
|
x, y, spacing, item, bbox, height, width;
|
|
|
|
|
|
if (len) {
|
|
for (; i < len; i++) {
|
|
items[i].destroy();
|
|
}
|
|
}
|
|
|
|
items.length = [];
|
|
|
|
|
|
chart.series.each(function(series, i) {
|
|
if (series.showInLegend) {
|
|
Ext.each([].concat(series.yField), function(field, j) {
|
|
item = Ext.create('Ext.chart.LegendItem', {
|
|
legend: this,
|
|
series: series,
|
|
surface: chart.surface,
|
|
yFieldIndex: j
|
|
});
|
|
bbox = item.getBBox();
|
|
|
|
|
|
width = bbox.width;
|
|
height = bbox.height;
|
|
|
|
if (i + j === 0) {
|
|
spacing = vertical ? padding + height / 2 : padding;
|
|
}
|
|
else {
|
|
spacing = itemSpacing / (vertical ? 2 : 1);
|
|
}
|
|
|
|
item.x = mfloor(vertical ? padding : totalWidth + spacing);
|
|
item.y = mfloor(vertical ? totalHeight + spacing : padding + height / 2);
|
|
|
|
|
|
totalWidth += width + spacing;
|
|
totalHeight += height + spacing;
|
|
maxWidth = mmax(maxWidth, width);
|
|
maxHeight = mmax(maxHeight, height);
|
|
|
|
items.push(item);
|
|
}, this);
|
|
}
|
|
}, me);
|
|
|
|
|
|
me.width = mfloor((vertical ? maxWidth : totalWidth) + padding * 2);
|
|
if (vertical && items.length === 1) {
|
|
spacingOffset = 1;
|
|
}
|
|
me.height = mfloor((vertical ? totalHeight - spacingOffset * spacing : maxHeight) + (padding * 2));
|
|
me.itemHeight = maxHeight;
|
|
},
|
|
|
|
|
|
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,
|
|
height: me.height
|
|
};
|
|
},
|
|
|
|
|
|
createBox: function() {
|
|
var me = this,
|
|
box;
|
|
|
|
if (me.boxSprite) {
|
|
me.boxSprite.destroy();
|
|
}
|
|
|
|
box = me.boxSprite = me.chart.surface.add(Ext.apply({
|
|
type: 'rect',
|
|
stroke: me.boxStroke,
|
|
"stroke-width": me.boxStrokeWidth,
|
|
fill: me.boxFill,
|
|
zIndex: me.boxZIndex
|
|
}, me.getBBox()));
|
|
|
|
box.redraw();
|
|
},
|
|
|
|
|
|
updatePosition: function() {
|
|
var me = this,
|
|
x, y,
|
|
legendWidth = me.width,
|
|
legendHeight = me.height,
|
|
padding = me.padding,
|
|
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;
|
|
|
|
if (me.isDisplayed()) {
|
|
|
|
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;
|
|
}
|
|
me.x = x;
|
|
me.y = y;
|
|
|
|
|
|
Ext.each(me.items, function(item) {
|
|
item.updatePosition();
|
|
});
|
|
|
|
me.boxSprite.setAttributes(me.getBBox(), true);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.chart.Chart', {
|
|
|
|
|
|
|
|
alias: 'widget.chart',
|
|
|
|
extend: 'Ext.draw.Component',
|
|
|
|
mixins: {
|
|
themeManager: 'Ext.chart.theme.Theme',
|
|
mask: 'Ext.chart.Mask',
|
|
navigation: 'Ext.chart.Navigation'
|
|
},
|
|
|
|
requires: [
|
|
'Ext.util.MixedCollection',
|
|
'Ext.data.StoreManager',
|
|
'Ext.chart.Legend',
|
|
'Ext.util.DelayedTask'
|
|
],
|
|
|
|
|
|
|
|
|
|
viewBox: false,
|
|
|
|
|
|
|
|
|
|
animate: false,
|
|
|
|
|
|
legend: false,
|
|
|
|
|
|
insetPadding: 10,
|
|
|
|
|
|
enginePriority: ['Svg', 'Vml'],
|
|
|
|
|
|
background: false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.mask.constructor.call(me, config);
|
|
me.mixins.navigation.constructor.call(me, config);
|
|
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',
|
|
'itemdoubleclick',
|
|
'itemdragstart',
|
|
'itemdrag',
|
|
'itemdragend',
|
|
|
|
'beforerefresh',
|
|
|
|
'refresh'
|
|
);
|
|
Ext.applyIf(me, {
|
|
zoom: {
|
|
width: 1,
|
|
height: 1,
|
|
x: 0,
|
|
y: 0
|
|
}
|
|
});
|
|
me.maxGutter = [0, 0];
|
|
me.store = Ext.data.StoreManager.lookup(me.store);
|
|
axes = me.axes;
|
|
me.axes = Ext.create('Ext.util.MixedCollection', false, function(a) { return a.position; });
|
|
if (axes) {
|
|
me.axes.addAll(axes);
|
|
}
|
|
series = me.series;
|
|
me.series = Ext.create('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 = Ext.create('Ext.chart.Legend', Ext.applyIf({chart:me}, me.legend));
|
|
}
|
|
|
|
me.on({
|
|
mousemove: me.onMouseMove,
|
|
mouseleave: me.onMouseLeave,
|
|
mousedown: me.onMouseDown,
|
|
mouseup: me.onMouseUp,
|
|
scope: me
|
|
});
|
|
},
|
|
|
|
|
|
afterComponentLayout: function(width, height) {
|
|
var me = this;
|
|
if (Ext.isNumber(width) && Ext.isNumber(height)) {
|
|
me.curWidth = width;
|
|
me.curHeight = height;
|
|
me.redraw(true);
|
|
}
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
redraw: function(resize) {
|
|
var me = this,
|
|
chartBBox = me.chartBBox = {
|
|
x: 0,
|
|
y: 0,
|
|
height: me.curHeight,
|
|
width: me.curWidth
|
|
},
|
|
legend = me.legend;
|
|
me.surface.setSize(chartBBox.width, chartBBox.height);
|
|
|
|
me.series.each(me.initializeSeries, me);
|
|
me.axes.each(me.initializeAxis, me);
|
|
|
|
|
|
me.axes.each(function(axis) {
|
|
axis.processView();
|
|
});
|
|
me.axes.each(function(axis) {
|
|
axis.drawAxis(true);
|
|
});
|
|
|
|
|
|
if (legend !== false) {
|
|
legend.create();
|
|
}
|
|
|
|
|
|
me.alignAxes();
|
|
|
|
|
|
if (me.legend !== false) {
|
|
legend.updatePosition();
|
|
}
|
|
|
|
|
|
me.getMaxGutter();
|
|
|
|
|
|
me.resizing = !!resize;
|
|
|
|
me.axes.each(me.drawAxis, me);
|
|
me.series.each(me.drawCharts, me);
|
|
me.resizing = false;
|
|
},
|
|
|
|
|
|
afterRender: function() {
|
|
var ref,
|
|
me = this;
|
|
this.callParent();
|
|
|
|
if (me.categoryNames) {
|
|
me.setCategoryNames(me.categoryNames);
|
|
}
|
|
|
|
if (me.tipRenderer) {
|
|
ref = me.getFunctionRef(me.tipRenderer);
|
|
me.setTipRenderer(ref.fn, ref.scope);
|
|
}
|
|
me.bindStore(me.store, true);
|
|
me.refresh();
|
|
},
|
|
|
|
|
|
getEventXY: function(e) {
|
|
var me = this,
|
|
box = this.surface.getRegion(),
|
|
pageXY = e.getXY(),
|
|
x = pageXY[0] - box.left,
|
|
y = pageXY[1] - box.top;
|
|
return [x, y];
|
|
},
|
|
|
|
|
|
onClick: function(e) {
|
|
var me = this,
|
|
position = me.getEventXY(e),
|
|
item;
|
|
|
|
|
|
|
|
me.series.each(function(series) {
|
|
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('itemclick', item);
|
|
}
|
|
}
|
|
}
|
|
}, me);
|
|
},
|
|
|
|
|
|
onMouseDown: function(e) {
|
|
var me = this,
|
|
position = me.getEventXY(e),
|
|
item;
|
|
|
|
if (me.mask) {
|
|
me.mixins.mask.onMouseDown.call(me, e);
|
|
}
|
|
|
|
|
|
me.series.each(function(series) {
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}, me);
|
|
},
|
|
|
|
|
|
onMouseUp: function(e) {
|
|
var me = this,
|
|
position = me.getEventXY(e),
|
|
item;
|
|
|
|
if (me.mask) {
|
|
me.mixins.mask.onMouseUp.call(me, e);
|
|
}
|
|
|
|
|
|
me.series.each(function(series) {
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}, me);
|
|
},
|
|
|
|
|
|
onMouseMove: function(e) {
|
|
var me = this,
|
|
position = me.getEventXY(e),
|
|
item, last, storeItem, storeField;
|
|
|
|
if (me.mask) {
|
|
me.mixins.mask.onMouseMove.call(me, e);
|
|
}
|
|
|
|
|
|
me.series.each(function(series) {
|
|
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;
|
|
}
|
|
}
|
|
}, me);
|
|
},
|
|
|
|
|
|
onMouseLeave: function(e) {
|
|
var me = this;
|
|
if (me.mask) {
|
|
me.mixins.mask.onMouseLeave.call(me, e);
|
|
}
|
|
me.series.each(function(series) {
|
|
delete series._lastItemForPoint;
|
|
});
|
|
},
|
|
|
|
|
|
delayRefresh: function() {
|
|
var me = this;
|
|
if (!me.refreshTask) {
|
|
me.refreshTask = Ext.create('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.fireEvent('beforerefresh', me) !== false) {
|
|
me.redraw();
|
|
me.fireEvent('refresh', me);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
bindStore: function(store, initial) {
|
|
var me = this;
|
|
if (!initial && me.store) {
|
|
if (store !== me.store && me.store.autoDestroy) {
|
|
me.store.destroyStore();
|
|
}
|
|
else {
|
|
me.store.un('datachanged', me.refresh, me);
|
|
me.store.un('add', me.delayRefresh, me);
|
|
me.store.un('remove', me.delayRefresh, me);
|
|
me.store.un('update', me.delayRefresh, me);
|
|
me.store.un('clear', me.refresh, me);
|
|
}
|
|
}
|
|
if (store) {
|
|
store = Ext.data.StoreManager.lookup(store);
|
|
store.on({
|
|
scope: me,
|
|
datachanged: me.refresh,
|
|
add: me.delayRefresh,
|
|
remove: me.delayRefresh,
|
|
update: me.delayRefresh,
|
|
clear: me.refresh
|
|
});
|
|
}
|
|
me.store = store;
|
|
if (store && !initial) {
|
|
me.refresh();
|
|
}
|
|
},
|
|
|
|
|
|
initializeAxis: function(axis) {
|
|
var me = this,
|
|
chartBBox = me.chartBBox,
|
|
w = chartBBox.width,
|
|
h = chartBBox.height,
|
|
x = chartBBox.x,
|
|
y = chartBBox.y,
|
|
themeAttrs = me.themeAttrs,
|
|
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 = me.axes.replace(Ext.createByAlias('axis.' + axis.type.toLowerCase(), config));
|
|
}
|
|
else {
|
|
Ext.apply(axis, config);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
alignAxes: function() {
|
|
var me = this,
|
|
axes = me.axes,
|
|
legend = me.legend,
|
|
edges = ['top', 'right', 'bottom', 'left'],
|
|
chartBBox,
|
|
insetPadding = me.insetPadding,
|
|
insets = {
|
|
top: insetPadding,
|
|
right: insetPadding,
|
|
bottom: insetPadding,
|
|
left: insetPadding
|
|
};
|
|
|
|
function getAxis(edge) {
|
|
var i = axes.findIndex('position', edge);
|
|
return (i < 0) ? null : axes.getAt(i);
|
|
}
|
|
|
|
|
|
Ext.each(edges, function(edge) {
|
|
var isVertical = (edge === 'left' || edge === 'right'),
|
|
axis = getAxis(edge),
|
|
bbox;
|
|
|
|
|
|
if (legend !== false) {
|
|
if (legend.position === edge) {
|
|
bbox = legend.getBBox();
|
|
insets[edge] += (isVertical ? bbox.width : bbox.height) + insets[edge];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (axis && axis.bbox) {
|
|
bbox = axis.bbox;
|
|
insets[edge] += (isVertical ? bbox.width : bbox.height);
|
|
}
|
|
});
|
|
|
|
chartBBox = {
|
|
x: insets.left,
|
|
y: insets.top,
|
|
width: me.curWidth - insets.left - insets.right,
|
|
height: me.curHeight - insets.top - insets.bottom
|
|
};
|
|
me.chartBBox = chartBBox;
|
|
|
|
|
|
|
|
axes.each(function(axis) {
|
|
var 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) {
|
|
var me = this,
|
|
themeAttrs = me.themeAttrs,
|
|
seriesObj, markerObj, seriesThemes, st,
|
|
markerThemes, colorArrayStyle = [],
|
|
i = 0, l,
|
|
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[idx % seriesThemes.length]);
|
|
config.seriesLabelStyle = Ext.apply({}, themeAttrs.seriesLabel);
|
|
config.markerStyle = Ext.apply(markerObj, markerThemes[idx % 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;
|
|
}
|
|
if (series instanceof Ext.chart.series.Series) {
|
|
Ext.apply(series, config);
|
|
} else {
|
|
Ext.applyIf(config, series);
|
|
series = me.series.replace(Ext.createByAlias('series.' + series.type.toLowerCase(), config));
|
|
}
|
|
if (series.initialize) {
|
|
series.initialize();
|
|
}
|
|
},
|
|
|
|
|
|
getMaxGutter: function() {
|
|
var me = this,
|
|
maxGutter = [0, 0];
|
|
me.series.each(function(s) {
|
|
var gutter = s.getGutters && s.getGutters() || [0, 0];
|
|
maxGutter[0] = Math.max(maxGutter[0], gutter[0]);
|
|
maxGutter[1] = Math.max(maxGutter[1], gutter[1]);
|
|
});
|
|
me.maxGutter = maxGutter;
|
|
},
|
|
|
|
|
|
drawAxis: function(axis) {
|
|
axis.drawAxis();
|
|
},
|
|
|
|
|
|
drawCharts: function(series) {
|
|
series.triggerafterrender = false;
|
|
series.drawSeries();
|
|
if (!this.animate) {
|
|
series.fireEvent('afterrender');
|
|
}
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
Ext.destroy(this.surface);
|
|
this.bindStore(null);
|
|
this.callParent(arguments);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.chart.Highlight', {
|
|
|
|
|
|
|
|
requires: ['Ext.fx.Anim'],
|
|
|
|
|
|
|
|
|
|
highlight: false,
|
|
|
|
highlightCfg : null,
|
|
|
|
constructor: function(config) {
|
|
if (config.highlight) {
|
|
if (config.highlight !== true) {
|
|
this.highlightCfg = Ext.apply({}, config.highlight);
|
|
}
|
|
else {
|
|
this.highlightCfg = {
|
|
fill: '#fdd',
|
|
radius: 20,
|
|
lineWidth: 5,
|
|
stroke: '#f55'
|
|
};
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
highlightItem: function(item) {
|
|
if (!item) {
|
|
return;
|
|
}
|
|
|
|
var me = this,
|
|
sprite = item.sprite,
|
|
opts = me.highlightCfg,
|
|
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 = Ext.create('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 = me.highlightCfg,
|
|
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(obj[p], sprite._defaults[p]);
|
|
}
|
|
else {
|
|
obj[p] = sprite._defaults[p];
|
|
}
|
|
}
|
|
if (animate) {
|
|
|
|
sprite._endStyle = obj;
|
|
sprite._anim = Ext.create('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', {
|
|
|
|
|
|
|
|
requires: ['Ext.draw.Color'],
|
|
|
|
|
|
|
|
|
|
|
|
//@private a regex to parse url type colors.
|
|
|
|
colorStringRe: /url\s*\(\s*#([^\/)]+)\s*\)/,
|
|
|
|
//@private the mixin constructor. Used internally by Series.
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
me.label = Ext.applyIf(me.label || {},
|
|
{
|
|
display: "none",
|
|
color: "#000",
|
|
field: "name",
|
|
minMargin: 50,
|
|
font: "11px Helvetica, sans-serif",
|
|
orientation: "horizontal",
|
|
renderer: function(v) {
|
|
return v;
|
|
}
|
|
});
|
|
|
|
if (me.label.display !== 'none') {
|
|
me.labelsGroup = me.chart.surface.getGroup(me.seriesId + '-labels');
|
|
}
|
|
},
|
|
|
|
//@private a method to render all labels in the labelGroup
|
|
|
|
renderLabels: function() {
|
|
var me = this,
|
|
chart = me.chart,
|
|
gradients = chart.gradients,
|
|
items = me.items,
|
|
animate = chart.animate,
|
|
config = me.label,
|
|
display = config.display,
|
|
color = config.color,
|
|
field = [].concat(config.field),
|
|
group = me.labelsGroup,
|
|
groupLength = (group || 0) && group.length,
|
|
store = me.chart.store,
|
|
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;
|
|
|
|
if (display == 'none') {
|
|
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] && ratio > 1) {
|
|
if(field[j]){
|
|
hides.push(groupIndex);
|
|
}
|
|
index++;
|
|
|
|
}
|
|
|
|
if (!item && label) {
|
|
label.hide(true);
|
|
groupIndex++;
|
|
}
|
|
|
|
if (item && field[j]) {
|
|
if (!label) {
|
|
label = me.onCreateLabel(storeItem, item, i, display, j, index);
|
|
}
|
|
me.onPlaceLabel(label, storeItem, item, i, display, animate, j, index);
|
|
groupIndex++;
|
|
|
|
|
|
if (config.contrast && item.sprite) {
|
|
sprite = item.sprite;
|
|
|
|
if (sprite._endStyle) {
|
|
colorString = sprite._endStyle.fill;
|
|
}
|
|
else if (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.color || label.attr.fill).getHSL();
|
|
labelColor[2] = spriteBrightness > 0.5 ? 0.2 : 0.8;
|
|
label.setAttributes({
|
|
fill: String(Color.fromHSL.apply({}, labelColor))
|
|
}, true);
|
|
}
|
|
|
|
}
|
|
count++;
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
me.hideLabels(hides);
|
|
},
|
|
hideLabels: function(hides){
|
|
var labelsGroup = this.labelsGroup,
|
|
hlen = hides.length;
|
|
while(hlen--)
|
|
labelsGroup.getAt(hides[hlen]).hide(true);
|
|
}
|
|
});
|
|
Ext.define('Ext.chart.MaskLayer', {
|
|
extend: 'Ext.Component',
|
|
|
|
constructor: function(config) {
|
|
config = Ext.apply(config || {}, {
|
|
style: 'position:absolute;background-color:#888;cursor:move;opacity:0.6;border:1px solid #222;'
|
|
});
|
|
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.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', {
|
|
|
|
|
|
|
|
requires: ['Ext.tip.ToolTip', 'Ext.chart.TipSurface'],
|
|
|
|
|
|
|
|
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: false
|
|
});
|
|
me.tooltip = Ext.create('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 = Ext.create('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;
|
|
if (!me.tooltip) {
|
|
return;
|
|
}
|
|
clearTimeout(me.tipTimeout);
|
|
var tooltip = me.tooltip,
|
|
spriteTip = me.spriteTip,
|
|
tipConfig = me.tipConfig,
|
|
trackMouse = tooltip.trackMouse,
|
|
sprite, surface, surfaceExt, pos, x, y;
|
|
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.show();
|
|
tooltip.trackMouse = trackMouse;
|
|
},
|
|
|
|
hideTip: function(item) {
|
|
var tooltip = this.tooltip;
|
|
if (!tooltip) {
|
|
return;
|
|
}
|
|
clearTimeout(this.tipTimeout);
|
|
this.tipTimeout = setTimeout(function() {
|
|
tooltip.hide();
|
|
}, 0);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.chart.axis.Abstract', {
|
|
|
|
|
|
|
|
requires: ['Ext.chart.Chart'],
|
|
|
|
|
|
|
|
|
|
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 = [].concat(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',
|
|
|
|
requires: ['Ext.draw.Draw'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//@private force min/max values from store
|
|
|
|
forceMinMax: false,
|
|
|
|
|
|
dashSize: 3,
|
|
|
|
|
|
position: 'bottom',
|
|
|
|
|
|
skipFirst: false,
|
|
|
|
|
|
length: 0,
|
|
|
|
|
|
width: 0,
|
|
|
|
majorTickSteps: false,
|
|
|
|
|
|
applyData: Ext.emptyFn,
|
|
|
|
getRange: function () {
|
|
var me = this,
|
|
store = me.chart.getChartStore(),
|
|
fields = me.fields,
|
|
ln = fields.length,
|
|
math = Math,
|
|
mmax = math.max,
|
|
mmin = math.min,
|
|
aggregate = false,
|
|
min = isNaN(me.minimum) ? Infinity : me.minimum,
|
|
max = isNaN(me.maximum) ? -Infinity : me.maximum,
|
|
total = 0, i, l, value, values, rec,
|
|
excludes = [],
|
|
series = me.chart.series.items;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0, l = series.length; !aggregate && i < l; i++) {
|
|
aggregate = aggregate || series[i].stacked;
|
|
excludes = series[i].__excludes || excludes;
|
|
}
|
|
store.each(function(record) {
|
|
if (aggregate) {
|
|
if (!isFinite(min)) {
|
|
min = 0;
|
|
}
|
|
for (values = [0, 0], i = 0; i < ln; i++) {
|
|
if (excludes[i]) {
|
|
continue;
|
|
}
|
|
rec = record.get(fields[i]);
|
|
values[+(rec > 0)] += math.abs(rec);
|
|
}
|
|
max = mmax(max, -values[0], +values[1]);
|
|
min = mmin(min, -values[0], +values[1]);
|
|
}
|
|
else {
|
|
for (i = 0; i < ln; i++) {
|
|
if (excludes[i]) {
|
|
continue;
|
|
}
|
|
value = record.get(fields[i]);
|
|
max = mmax(max, +value);
|
|
min = mmin(min, +value);
|
|
}
|
|
}
|
|
});
|
|
if (!isFinite(max)) {
|
|
max = me.prevMax || 0;
|
|
}
|
|
if (!isFinite(min)) {
|
|
min = me.prevMin || 0;
|
|
}
|
|
|
|
if (min != max && (max != Math.floor(max))) {
|
|
max = Math.floor(max) + 1;
|
|
}
|
|
|
|
if (!isNaN(me.minimum)) {
|
|
min = me.minimum;
|
|
}
|
|
|
|
if (!isNaN(me.maximum)) {
|
|
max = me.maximum;
|
|
}
|
|
|
|
return {min: min, max: max};
|
|
},
|
|
|
|
|
|
calcEnds: function() {
|
|
var me = this,
|
|
fields = me.fields,
|
|
range = me.getRange(),
|
|
min = range.min,
|
|
max = range.max,
|
|
outfrom, outto, out;
|
|
|
|
out = Ext.draw.Draw.snapEnds(min, max, me.majorTickSteps !== false ? (me.majorTickSteps +1) : me.steps);
|
|
outfrom = out.from;
|
|
outto = out.to;
|
|
if (me.forceMinMax) {
|
|
if (!isNaN(max)) {
|
|
out.to = max;
|
|
}
|
|
if (!isNaN(min)) {
|
|
out.from = min;
|
|
}
|
|
}
|
|
if (!isNaN(me.maximum)) {
|
|
|
|
|
|
out.to = me.maximum;
|
|
}
|
|
if (!isNaN(me.minimum)) {
|
|
|
|
|
|
out.from = me.minimum;
|
|
}
|
|
|
|
|
|
out.step = (out.to - out.from) / (outto - outfrom) * out.step;
|
|
|
|
if (me.adjustMaximumByMajorUnit) {
|
|
out.to += out.step;
|
|
}
|
|
if (me.adjustMinimumByMajorUnit) {
|
|
out.from -= out.step;
|
|
}
|
|
me.prevMin = min == max? 0 : min;
|
|
me.prevMax = max;
|
|
return out;
|
|
},
|
|
|
|
|
|
drawAxis: function (init) {
|
|
var me = this,
|
|
i, j,
|
|
x = me.x,
|
|
y = me.y,
|
|
gutterX = me.chart.maxGutter[0],
|
|
gutterY = me.chart.maxGutter[1],
|
|
dashSize = me.dashSize,
|
|
subDashesX = me.minorTickSteps || 0,
|
|
subDashesY = me.minorTickSteps || 0,
|
|
length = me.length,
|
|
position = me.position,
|
|
inflections = [],
|
|
calcLabels = false,
|
|
stepCalcs = me.applyData(),
|
|
step = stepCalcs.step,
|
|
steps = stepCalcs.steps,
|
|
from = stepCalcs.from,
|
|
to = stepCalcs.to,
|
|
trueLength,
|
|
currentX,
|
|
currentY,
|
|
path,
|
|
prev,
|
|
dashesX,
|
|
dashesY,
|
|
delta;
|
|
|
|
|
|
|
|
|
|
if (me.hidden || isNaN(step) || (from == to)) {
|
|
return;
|
|
}
|
|
|
|
me.from = stepCalcs.from;
|
|
me.to = stepCalcs.to;
|
|
if (position == 'left' || position == 'right') {
|
|
currentX = Math.floor(x) + 0.5;
|
|
path = ["M", currentX, y, "l", 0, -length];
|
|
trueLength = length - (gutterY * 2);
|
|
}
|
|
else {
|
|
currentY = Math.floor(y) + 0.5;
|
|
path = ["M", x, currentY, "l", length, 0];
|
|
trueLength = length - (gutterX * 2);
|
|
}
|
|
|
|
delta = trueLength / (steps || 1);
|
|
dashesX = Math.max(subDashesX +1, 0);
|
|
dashesY = Math.max(subDashesY +1, 0);
|
|
if (me.type == 'Numeric' || me.type == 'Time') {
|
|
calcLabels = true;
|
|
me.labels = [stepCalcs.from];
|
|
}
|
|
if (position == 'right' || position == 'left') {
|
|
currentY = y - gutterY;
|
|
currentX = x - ((position == 'left') * dashSize * 2);
|
|
while (currentY >= y - gutterY - trueLength) {
|
|
path.push("M", currentX, Math.floor(currentY) + 0.5, "l", dashSize * 2 + 1, 0);
|
|
if (currentY != y - gutterY) {
|
|
for (i = 1; i < dashesY; i++) {
|
|
path.push("M", currentX + dashSize, Math.floor(currentY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
|
|
}
|
|
}
|
|
inflections.push([ Math.floor(x), Math.floor(currentY) ]);
|
|
currentY -= delta;
|
|
if (calcLabels) {
|
|
me.labels.push(me.labels[me.labels.length -1] + step);
|
|
}
|
|
if (delta === 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (Math.round(currentY + delta - (y - gutterY - trueLength))) {
|
|
path.push("M", currentX, Math.floor(y - length + gutterY) + 0.5, "l", dashSize * 2 + 1, 0);
|
|
for (i = 1; i < dashesY; i++) {
|
|
path.push("M", currentX + dashSize, Math.floor(y - length + gutterY + delta * i / dashesY) + 0.5, "l", dashSize + 1, 0);
|
|
}
|
|
inflections.push([ Math.floor(x), Math.floor(currentY) ]);
|
|
if (calcLabels) {
|
|
me.labels.push(me.labels[me.labels.length -1] + step);
|
|
}
|
|
}
|
|
} else {
|
|
currentX = x + gutterX;
|
|
currentY = y - ((position == 'top') * dashSize * 2);
|
|
while (currentX <= x + gutterX + trueLength) {
|
|
path.push("M", Math.floor(currentX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
|
|
if (currentX != x + gutterX) {
|
|
for (i = 1; i < dashesX; i++) {
|
|
path.push("M", Math.floor(currentX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
|
|
}
|
|
}
|
|
inflections.push([ Math.floor(currentX), Math.floor(y) ]);
|
|
currentX += delta;
|
|
if (calcLabels) {
|
|
me.labels.push(me.labels[me.labels.length -1] + step);
|
|
}
|
|
if (delta === 0) {
|
|
break;
|
|
}
|
|
}
|
|
if (Math.round(currentX - delta - (x + gutterX + trueLength))) {
|
|
path.push("M", Math.floor(x + length - gutterX) + 0.5, currentY, "l", 0, dashSize * 2 + 1);
|
|
for (i = 1; i < dashesX; i++) {
|
|
path.push("M", Math.floor(x + length - gutterX - delta * i / dashesX) + 0.5, currentY, "l", 0, dashSize + 1);
|
|
}
|
|
inflections.push([ Math.floor(currentX), Math.floor(y) ]);
|
|
if (calcLabels) {
|
|
me.labels.push(me.labels[me.labels.length -1] + step);
|
|
}
|
|
}
|
|
}
|
|
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,
|
|
gutter = me.chart.maxGutter,
|
|
width = me.width - 2,
|
|
vert = false,
|
|
point, prevPoint,
|
|
i = 1,
|
|
path = [], styles, lineWidth, dlineWidth,
|
|
oddPath = [], evenPath = [];
|
|
|
|
if ((gutter[1] !== 0 && (position == 'left' || position == 'right')) ||
|
|
(gutter[0] !== 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);
|
|
}
|
|
}
|
|
},
|
|
|
|
//@private
|
|
|
|
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,
|
|
position = me.position,
|
|
inflections = me.inflections,
|
|
ln = inflections.length,
|
|
labels = me.labels,
|
|
labelGroup = me.labelGroup,
|
|
maxHeight = 0,
|
|
ratio,
|
|
gutterY = me.chart.maxGutter[1],
|
|
ubbox, bbox, point, prevX, prevLabel,
|
|
projectedWidth = 0,
|
|
textLabel, attr, textRight, text,
|
|
label, 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];
|
|
text = me.label.renderer(labels[i]);
|
|
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 (me.chart.maxGutter[0] == 0) {
|
|
if (i == 0 && axes.findIndex('position', 'left') == -1) {
|
|
x = point[0];
|
|
}
|
|
else if (i == last && axes.findIndex('position', 'right') == -1) {
|
|
x = point[0] - bbox.width;
|
|
}
|
|
}
|
|
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))) {
|
|
textLabel.hide(true);
|
|
continue;
|
|
}
|
|
|
|
prevLabel = textLabel;
|
|
}
|
|
|
|
return maxHeight;
|
|
},
|
|
|
|
drawVerticalLabels: function() {
|
|
var me = this,
|
|
inflections = me.inflections,
|
|
position = me.position,
|
|
ln = inflections.length,
|
|
labels = me.labels,
|
|
maxWidth = 0,
|
|
max = Math.max,
|
|
floor = Math.floor,
|
|
ceil = Math.ceil,
|
|
axes = me.chart.axes,
|
|
gutterY = me.chart.maxGutter[1],
|
|
ubbox, bbox, point, prevLabel,
|
|
projectedWidth = 0,
|
|
textLabel, attr, textRight, text,
|
|
label, last, x, y, i;
|
|
|
|
last = ln;
|
|
for (i = 0; i < last; 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 (gutterY < bbox.height / 2) {
|
|
if (i == last - 1 && axes.findIndex('position', 'top') == -1) {
|
|
y = me.y - me.length + ceil(bbox.height / 2);
|
|
}
|
|
else if (i == 0 && axes.findIndex('position', 'bottom') == -1) {
|
|
y = me.y - 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)) {
|
|
textLabel.hide(true);
|
|
continue;
|
|
}
|
|
prevLabel = textLabel;
|
|
}
|
|
|
|
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);
|
|
}
|
|
},
|
|
|
|
|
|
elipsis: function(sprite, text, desiredWidth, minWidth, center) {
|
|
var bbox,
|
|
x;
|
|
|
|
if (desiredWidth < minWidth) {
|
|
sprite.hide(true);
|
|
return false;
|
|
}
|
|
while (text.length > 4) {
|
|
text = text.substr(0, text.length - 4) + "...";
|
|
sprite.setAttributes({
|
|
text: text
|
|
}, true);
|
|
bbox = sprite.getBBox();
|
|
if (bbox.width < desiredWidth) {
|
|
if (typeof center == 'number') {
|
|
sprite.setAttributes({
|
|
x: Math.floor(center - (bbox.width / 2))
|
|
}, true);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
return true;
|
|
},
|
|
|
|
|
|
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',
|
|
|
|
|
|
|
|
|
|
categoryNames: null,
|
|
|
|
|
|
calculateCategoryCount: false,
|
|
|
|
|
|
setLabels: function() {
|
|
var store = this.chart.store,
|
|
fields = this.fields,
|
|
ln = fields.length,
|
|
i;
|
|
|
|
this.labels = [];
|
|
store.each(function(record) {
|
|
for (i = 0; i < ln; i++) {
|
|
this.labels.push(record.get(fields[i]));
|
|
}
|
|
}, this);
|
|
},
|
|
|
|
|
|
applyData: function() {
|
|
this.callParent();
|
|
this.setLabels();
|
|
var count = this.chart.store.getCount();
|
|
return {
|
|
from: 0,
|
|
to: count,
|
|
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({
|
|
type: 'text',
|
|
zIndex: 2
|
|
});
|
|
}
|
|
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 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 + 2 * margin,
|
|
round = Math.round,
|
|
labelArray = [], label,
|
|
maxValue = this.maximum || 0,
|
|
steps = this.steps, i = 0,
|
|
adjY,
|
|
pi = Math.PI,
|
|
cos = Math.cos,
|
|
sin = Math.sin,
|
|
labelConf = this.label,
|
|
renderer = labelConf.renderer || function(v) { return v; };
|
|
|
|
if (!this.labelArray) {
|
|
|
|
for (i = 0; i <= steps; i++) {
|
|
|
|
adjY = (i === 0 || i === steps) ? 7 : 0;
|
|
label = surface.add({
|
|
type: 'text',
|
|
text: renderer(round(i / steps * maxValue)),
|
|
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;
|
|
labelArray[i].setAttributes({
|
|
text: renderer(round(i / steps * maxValue)),
|
|
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',
|
|
|
|
alias: 'axis.numeric',
|
|
|
|
constructor: function(config) {
|
|
var me = this,
|
|
hasLabel = !!(config.label && config.label.renderer),
|
|
label;
|
|
|
|
me.callParent([config]);
|
|
label = me.label;
|
|
if (me.roundToDecimal === false) {
|
|
return;
|
|
}
|
|
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.floor(v * val) / val;
|
|
},
|
|
|
|
|
|
minimum: NaN,
|
|
|
|
|
|
maximum: NaN,
|
|
|
|
|
|
decimals: 2,
|
|
|
|
|
|
scale: "linear",
|
|
|
|
|
|
position: 'left',
|
|
|
|
|
|
adjustMaximumByMajorUnit: false,
|
|
|
|
|
|
adjustMinimumByMajorUnit: false,
|
|
|
|
|
|
applyData: function() {
|
|
this.callParent();
|
|
return this.calcEnds();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.chart.axis.Radial', {
|
|
|
|
|
|
|
|
extend: 'Ext.chart.axis.Abstract',
|
|
|
|
|
|
|
|
position: 'radial',
|
|
|
|
alias: 'axis.radial',
|
|
|
|
drawAxis: function(init) {
|
|
var chart = this.chart,
|
|
surface = chart.surface,
|
|
bbox = chart.chartBBox,
|
|
store = chart.store,
|
|
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);
|
|
}
|
|
|
|
store.each(function(rec, 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);
|
|
}
|
|
|
|
store.each(function(rec, 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,
|
|
surface = chart.surface,
|
|
bbox = chart.chartBBox,
|
|
store = chart.store,
|
|
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;
|
|
}
|
|
|
|
|
|
chart.series.each(function(series) {
|
|
fields.push(series.yField);
|
|
xField = series.xField;
|
|
});
|
|
|
|
|
|
store.each(function(record, i) {
|
|
if (aggregate) {
|
|
for (i = 0, nfields = fields.length; i < nfields; i++) {
|
|
maxValue = max(+record.get(fields[i]), maxValue);
|
|
}
|
|
}
|
|
categories.push(record.get(xField));
|
|
});
|
|
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;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.data.AbstractStore', {
|
|
requires: ['Ext.util.MixedCollection', 'Ext.data.Operation', 'Ext.util.Filter'],
|
|
|
|
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;
|
|
}
|
|
},
|
|
|
|
remoteSort : false,
|
|
remoteFilter: false,
|
|
|
|
|
|
|
|
|
|
autoLoad: false,
|
|
|
|
|
|
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;
|
|
|
|
me.addEvents(
|
|
|
|
'add',
|
|
|
|
|
|
'remove',
|
|
|
|
|
|
'update',
|
|
|
|
|
|
'datachanged',
|
|
|
|
|
|
'beforeload',
|
|
|
|
|
|
'load',
|
|
|
|
|
|
'write',
|
|
|
|
|
|
'beforesync',
|
|
|
|
'clear'
|
|
);
|
|
|
|
Ext.apply(me, config);
|
|
|
|
|
|
|
|
me.removed = [];
|
|
|
|
me.mixins.observable.constructor.apply(me, arguments);
|
|
me.model = Ext.ModelManager.getModel(me.model);
|
|
|
|
|
|
Ext.applyIf(me, {
|
|
modelDefaults: {}
|
|
});
|
|
|
|
|
|
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 = Ext.create('Ext.util.MixedCollection');
|
|
me.filters.addAll(filters);
|
|
},
|
|
|
|
|
|
setProxy: function(proxy) {
|
|
var me = this;
|
|
|
|
if (proxy instanceof Ext.data.proxy.Proxy) {
|
|
proxy.setModel(me.model);
|
|
} else {
|
|
if (Ext.isString(proxy)) {
|
|
proxy = {
|
|
type: proxy
|
|
};
|
|
}
|
|
Ext.applyIf(proxy, {
|
|
model: me.model
|
|
});
|
|
|
|
proxy = Ext.createByAlias('proxy.' + proxy.type, proxy);
|
|
}
|
|
|
|
me.proxy = proxy;
|
|
|
|
return me.proxy;
|
|
},
|
|
|
|
|
|
getProxy: function() {
|
|
return this.proxy;
|
|
},
|
|
|
|
|
|
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 = Ext.create('Ext.data.Operation', options);
|
|
|
|
me.proxy.create(operation, me.onProxyWrite, me);
|
|
|
|
return instance;
|
|
},
|
|
|
|
read: function() {
|
|
return this.load.apply(this, arguments);
|
|
},
|
|
|
|
onProxyRead: Ext.emptyFn,
|
|
|
|
update: function(options) {
|
|
var me = this,
|
|
operation;
|
|
options = options || {};
|
|
|
|
Ext.applyIf(options, {
|
|
action : 'update',
|
|
records: me.getUpdatedRecords()
|
|
});
|
|
|
|
operation = Ext.create('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);
|
|
}
|
|
|
|
Ext.callback(operation.callback, operation.scope || me, [records, operation, success]);
|
|
},
|
|
|
|
|
|
|
|
destroy: function(options) {
|
|
var me = this,
|
|
operation;
|
|
|
|
options = options || {};
|
|
|
|
Ext.applyIf(options, {
|
|
action : 'destroy',
|
|
records: me.getRemovedRecords()
|
|
});
|
|
|
|
operation = Ext.create('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);
|
|
},
|
|
|
|
onBatchException: function(batch, operation) {
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
filterNew: function(item) {
|
|
|
|
return item.phantom === true && item.isValid();
|
|
},
|
|
|
|
|
|
getNewRecords: function() {
|
|
return [];
|
|
},
|
|
|
|
|
|
getUpdatedRecords: function() {
|
|
return [];
|
|
},
|
|
|
|
|
|
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() {
|
|
var me = this,
|
|
options = {},
|
|
toCreate = me.getNewRecords(),
|
|
toUpdate = me.getUpdatedRecords(),
|
|
toDestroy = me.getRemovedRecords(),
|
|
needsSync = false;
|
|
|
|
if (toCreate.length > 0) {
|
|
options.create = toCreate;
|
|
needsSync = true;
|
|
}
|
|
|
|
if (toUpdate.length > 0) {
|
|
options.update = toUpdate;
|
|
needsSync = true;
|
|
}
|
|
|
|
if (toDestroy.length > 0) {
|
|
options.destroy = toDestroy;
|
|
needsSync = true;
|
|
}
|
|
|
|
if (needsSync && me.fireEvent('beforesync', options) !== false) {
|
|
me.proxy.batch(options, me.getBatchListeners());
|
|
}
|
|
},
|
|
|
|
|
|
|
|
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;
|
|
|
|
options = options || {};
|
|
|
|
Ext.applyIf(options, {
|
|
action : 'read',
|
|
filters: me.filters.items,
|
|
sorters: me.getSorters()
|
|
});
|
|
|
|
operation = Ext.create('Ext.data.Operation', options);
|
|
|
|
if (me.fireEvent('beforeload', me, operation) !== false) {
|
|
me.loading = true;
|
|
me.proxy.read(operation, me.onProxyLoad, me);
|
|
}
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
afterEdit : function(record) {
|
|
var me = this;
|
|
|
|
if (me.autoSync) {
|
|
me.sync();
|
|
}
|
|
|
|
me.fireEvent('update', me, record, Ext.data.Model.EDIT);
|
|
},
|
|
|
|
|
|
afterReject : function(record) {
|
|
this.fireEvent('update', this, record, Ext.data.Model.REJECT);
|
|
},
|
|
|
|
|
|
afterCommit : function(record) {
|
|
this.fireEvent('update', this, record, Ext.data.Model.COMMIT);
|
|
},
|
|
|
|
clearData: Ext.emptyFn,
|
|
|
|
destroyStore: function() {
|
|
var me = this;
|
|
|
|
if (!me.isDestroyed) {
|
|
if (me.storeId) {
|
|
Ext.data.StoreManager.unregister(me);
|
|
}
|
|
me.clearData();
|
|
me.data = null;
|
|
me.tree = null;
|
|
|
|
me.reader = me.writer = null;
|
|
me.clearListeners();
|
|
me.isDestroyed = true;
|
|
|
|
if (me.implicitModel) {
|
|
Ext.destroy(me.model);
|
|
}
|
|
}
|
|
},
|
|
|
|
doSort: function(sorterFn) {
|
|
var me = this;
|
|
if (me.remoteSort) {
|
|
|
|
me.load();
|
|
} else {
|
|
me.data.sortBy(sorterFn);
|
|
me.fireEvent('datachanged', me);
|
|
}
|
|
},
|
|
|
|
getCount: Ext.emptyFn,
|
|
|
|
getById: Ext.emptyFn,
|
|
|
|
|
|
removeAll: Ext.emptyFn,
|
|
|
|
|
|
|
|
|
|
isLoading: function() {
|
|
return !!this.loading;
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.util.Grouper', {
|
|
|
|
|
|
|
|
extend: 'Ext.util.Sorter',
|
|
|
|
|
|
|
|
|
|
getGroupString: function(instance) {
|
|
return instance.get(this.property);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.data.Store', {
|
|
extend: 'Ext.data.AbstractStore',
|
|
|
|
alias: 'store.store',
|
|
|
|
requires: ['Ext.data.StoreManager', 'Ext.ModelManager', 'Ext.data.Model', 'Ext.util.Grouper'],
|
|
uses: ['Ext.data.proxy.Memory'],
|
|
|
|
|
|
remoteSort: false,
|
|
|
|
|
|
remoteFilter: false,
|
|
|
|
|
|
remoteGroup : false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
groupField: undefined,
|
|
|
|
|
|
groupDir: "ASC",
|
|
|
|
|
|
pageSize: 25,
|
|
|
|
|
|
currentPage: 1,
|
|
|
|
|
|
clearOnPageLoad: true,
|
|
|
|
|
|
loading: false,
|
|
|
|
|
|
sortOnFilter: true,
|
|
|
|
|
|
buffered: false,
|
|
|
|
|
|
purgePageCount: 5,
|
|
|
|
isStore: true,
|
|
|
|
onClassExtended: function(cls, data) {
|
|
var model = data.model;
|
|
|
|
if (typeof model == 'string') {
|
|
var onBeforeClassCreated = data.onBeforeClassCreated;
|
|
|
|
data.onBeforeClassCreated = function(cls, data) {
|
|
var me = this;
|
|
|
|
Ext.require(model, function() {
|
|
onBeforeClassCreated.call(me, cls, data);
|
|
});
|
|
};
|
|
}
|
|
},
|
|
|
|
|
|
constructor: function(config) {
|
|
|
|
config = Ext.Object.merge({}, config);
|
|
|
|
var me = this,
|
|
groupers = config.groupers || me.groupers,
|
|
groupField = config.groupField || me.groupField,
|
|
proxy,
|
|
data;
|
|
|
|
if (config.buffered || me.buffered) {
|
|
me.prefetchData = Ext.create('Ext.util.MixedCollection', false, function(record) {
|
|
return record.index;
|
|
});
|
|
me.pendingRequests = [];
|
|
me.pagesRequested = [];
|
|
|
|
me.sortOnLoad = false;
|
|
me.filterOnLoad = false;
|
|
}
|
|
|
|
me.addEvents(
|
|
|
|
'beforeprefetch',
|
|
|
|
'groupchange',
|
|
|
|
'prefetch'
|
|
);
|
|
data = config.data || me.data;
|
|
|
|
|
|
me.data = Ext.create('Ext.util.MixedCollection', false, function(record) {
|
|
return record.internalId;
|
|
});
|
|
|
|
if (data) {
|
|
me.inlineData = data;
|
|
delete config.data;
|
|
}
|
|
|
|
if (!groupers && groupField) {
|
|
groupers = [{
|
|
property : groupField,
|
|
direction: config.groupDir || me.groupDir
|
|
}];
|
|
}
|
|
delete config.groupers;
|
|
|
|
|
|
me.groupers = Ext.create('Ext.util.MixedCollection');
|
|
me.groupers.addAll(me.decodeGroupers(groupers));
|
|
|
|
this.callParent([config]);
|
|
|
|
|
|
if (me.groupers.items.length) {
|
|
me.sort(me.groupers.items, 'prepend', false);
|
|
}
|
|
|
|
proxy = me.proxy;
|
|
data = me.inlineData;
|
|
|
|
if (data) {
|
|
if (proxy instanceof Ext.data.proxy.Memory) {
|
|
proxy.data = data;
|
|
me.read();
|
|
} else {
|
|
me.add.apply(me, data);
|
|
}
|
|
|
|
me.sort();
|
|
delete me.inlineData;
|
|
} else if (me.autoLoad) {
|
|
Ext.defer(me.load, 10, 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;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
config = groupers[i];
|
|
|
|
if (!(config instanceof Grouper)) {
|
|
if (Ext.isString(config)) {
|
|
config = {
|
|
property: config
|
|
};
|
|
}
|
|
|
|
Ext.applyIf(config, {
|
|
root : 'data',
|
|
direction: "ASC"
|
|
});
|
|
|
|
|
|
if (config.fn) {
|
|
config.sorterFn = config.fn;
|
|
}
|
|
|
|
|
|
if (typeof config == 'function') {
|
|
config = {
|
|
sorterFn: config
|
|
};
|
|
}
|
|
|
|
groupers[i] = new Grouper(config);
|
|
}
|
|
}
|
|
|
|
return groupers;
|
|
},
|
|
|
|
|
|
group: function(groupers, direction) {
|
|
var me = this,
|
|
hasNew = false,
|
|
grouper,
|
|
newGroupers;
|
|
|
|
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
|
|
};
|
|
newGroupers = [grouper];
|
|
} else if (direction === undefined) {
|
|
grouper.toggle();
|
|
} else {
|
|
grouper.setDirection(direction);
|
|
}
|
|
}
|
|
|
|
if (newGroupers && newGroupers.length) {
|
|
hasNew = true;
|
|
newGroupers = me.decodeGroupers(newGroupers);
|
|
me.groupers.clear();
|
|
me.groupers.addAll(newGroupers);
|
|
}
|
|
|
|
if (me.remoteGroup) {
|
|
me.load({
|
|
scope: me,
|
|
callback: me.fireGroupChange
|
|
});
|
|
} else {
|
|
|
|
me.sort(null, null, null, hasNew);
|
|
me.fireGroupChange();
|
|
}
|
|
},
|
|
|
|
|
|
clearGrouping: function(){
|
|
var me = this;
|
|
|
|
me.groupers.each(function(grouper){
|
|
me.sorters.remove(grouper);
|
|
});
|
|
me.groupers.clear();
|
|
if (me.remoteGroup) {
|
|
me.load({
|
|
scope: me,
|
|
callback: me.fireGroupChange
|
|
});
|
|
} else {
|
|
me.sort();
|
|
me.fireEvent('groupchange', me, me.groupers);
|
|
}
|
|
},
|
|
|
|
|
|
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 instance.get(group.property);
|
|
}
|
|
return '';
|
|
},
|
|
|
|
insert: function(index, records) {
|
|
var me = this,
|
|
sync = false,
|
|
i,
|
|
record,
|
|
len;
|
|
|
|
records = [].concat(records);
|
|
for (i = 0, len = records.length; i < len; i++) {
|
|
record = me.createModel(records[i]);
|
|
record.set(me.modelDefaults);
|
|
|
|
records[i] = record;
|
|
|
|
me.data.insert(index + i, record);
|
|
record.join(me);
|
|
|
|
sync = sync || record.phantom === true;
|
|
}
|
|
|
|
if (me.snapshot) {
|
|
me.snapshot.addAll(records);
|
|
}
|
|
|
|
me.fireEvent('add', me, records, index);
|
|
me.fireEvent('datachanged', me);
|
|
if (me.autoSync && sync) {
|
|
me.sync();
|
|
}
|
|
},
|
|
|
|
|
|
add: function(records) {
|
|
|
|
if (!Ext.isArray(records)) {
|
|
records = Array.prototype.slice.apply(arguments);
|
|
}
|
|
|
|
var me = this,
|
|
i = 0,
|
|
length = records.length,
|
|
record;
|
|
|
|
for (; i < length; i++) {
|
|
record = me.createModel(records[i]);
|
|
|
|
records[i] = record;
|
|
}
|
|
|
|
me.insert(me.data.length, records);
|
|
|
|
return records;
|
|
},
|
|
|
|
|
|
createModel: function(record) {
|
|
if (!record.isModel) {
|
|
record = Ext.ModelManager.create(record, this.model);
|
|
}
|
|
|
|
return record;
|
|
},
|
|
|
|
|
|
each: function(fn, scope) {
|
|
this.data.each(fn, scope);
|
|
},
|
|
|
|
|
|
remove: function(records, isMove) {
|
|
if (!Ext.isArray(records)) {
|
|
records = [records];
|
|
}
|
|
|
|
|
|
isMove = isMove === true;
|
|
var me = this,
|
|
sync = false,
|
|
i = 0,
|
|
length = records.length,
|
|
isPhantom,
|
|
index,
|
|
record;
|
|
|
|
for (; i < length; i++) {
|
|
record = records[i];
|
|
index = me.data.indexOf(record);
|
|
|
|
if (me.snapshot) {
|
|
me.snapshot.remove(record);
|
|
}
|
|
|
|
if (index > -1) {
|
|
isPhantom = record.phantom === true;
|
|
if (!isMove && !isPhantom) {
|
|
|
|
me.removed.push(record);
|
|
}
|
|
|
|
record.unjoin(me);
|
|
me.data.remove(record);
|
|
sync = sync || !isPhantom;
|
|
|
|
me.fireEvent('remove', me, record, index);
|
|
}
|
|
}
|
|
|
|
me.fireEvent('datachanged', me);
|
|
if (!isMove && me.autoSync && sync) {
|
|
me.sync();
|
|
}
|
|
},
|
|
|
|
|
|
removeAt: function(index) {
|
|
var record = this.getAt(index);
|
|
|
|
if (record) {
|
|
this.remove(record);
|
|
}
|
|
},
|
|
|
|
|
|
load: function(options) {
|
|
var me = this;
|
|
|
|
options = options || {};
|
|
|
|
if (Ext.isFunction(options)) {
|
|
options = {
|
|
callback: options
|
|
};
|
|
}
|
|
|
|
Ext.applyIf(options, {
|
|
groupers: me.groupers.items,
|
|
page: me.currentPage,
|
|
start: (me.currentPage - 1) * me.pageSize,
|
|
limit: me.pageSize,
|
|
addRecords: false
|
|
});
|
|
|
|
return me.callParent([options]);
|
|
},
|
|
|
|
|
|
onProxyLoad: function(operation) {
|
|
var me = this,
|
|
resultSet = operation.getResultSet(),
|
|
records = operation.getRecords(),
|
|
successful = operation.wasSuccessful();
|
|
|
|
if (resultSet) {
|
|
me.totalCount = resultSet.total;
|
|
}
|
|
|
|
if (successful) {
|
|
me.loadRecords(records, operation);
|
|
}
|
|
|
|
me.loading = false;
|
|
me.fireEvent('load', me, records, successful);
|
|
|
|
|
|
|
|
me.fireEvent('read', me, records, operation.wasSuccessful());
|
|
|
|
|
|
Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
|
|
},
|
|
|
|
|
|
onCreateRecords: function(records, operation, success) {
|
|
if (success) {
|
|
var i = 0,
|
|
data = this.data,
|
|
snapshot = this.snapshot,
|
|
length = records.length,
|
|
originalRecords = operation.records,
|
|
record,
|
|
original,
|
|
index;
|
|
|
|
|
|
for (; i < length; ++i) {
|
|
record = records[i];
|
|
original = originalRecords[i];
|
|
if (original) {
|
|
index = data.indexOf(original);
|
|
if (index > -1) {
|
|
data.removeAt(index);
|
|
data.insert(index, record);
|
|
}
|
|
if (snapshot) {
|
|
index = snapshot.indexOf(original);
|
|
if (index > -1) {
|
|
snapshot.removeAt(index);
|
|
snapshot.insert(index, record);
|
|
}
|
|
}
|
|
record.phantom = false;
|
|
record.join(this);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onUpdateRecords: function(records, operation, success){
|
|
if (success) {
|
|
var i = 0,
|
|
length = records.length,
|
|
data = this.data,
|
|
snapshot = this.snapshot,
|
|
record;
|
|
|
|
for (; i < length; ++i) {
|
|
record = records[i];
|
|
data.replace(record);
|
|
if (snapshot) {
|
|
snapshot.replace(record);
|
|
}
|
|
record.join(this);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onDestroyRecords: function(records, operation, success){
|
|
if (success) {
|
|
var me = this,
|
|
i = 0,
|
|
length = records.length,
|
|
data = me.data,
|
|
snapshot = me.snapshot,
|
|
record;
|
|
|
|
for (; i < length; ++i) {
|
|
record = records[i];
|
|
record.unjoin(me);
|
|
data.remove(record);
|
|
if (snapshot) {
|
|
snapshot.remove(record);
|
|
}
|
|
}
|
|
me.removed = [];
|
|
}
|
|
},
|
|
|
|
|
|
getNewRecords: function() {
|
|
return this.data.filterBy(this.filterNew).items;
|
|
},
|
|
|
|
|
|
getUpdatedRecords: function() {
|
|
return 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 = 0,
|
|
doLocalSort = me.sortOnFilter && !me.remoteSort,
|
|
length = decoded.length;
|
|
|
|
for (; i < length; i++) {
|
|
me.filters.replace(decoded[i]);
|
|
}
|
|
|
|
if (me.remoteFilter) {
|
|
|
|
me.load();
|
|
} else {
|
|
|
|
if (me.filters.getCount()) {
|
|
me.snapshot = me.snapshot || me.data.clone();
|
|
me.data = me.data.filter(me.filters.items);
|
|
|
|
if (doLocalSort) {
|
|
me.sort();
|
|
}
|
|
|
|
if (!doLocalSort || me.sorters.length < 1) {
|
|
me.fireEvent('datachanged', me);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
clearFilter: function(suppressEvent) {
|
|
var me = this;
|
|
|
|
me.filters.clear();
|
|
|
|
if (me.remoteFilter) {
|
|
me.load();
|
|
} else if (me.isFiltered()) {
|
|
me.data = me.snapshot.clone();
|
|
delete me.snapshot;
|
|
|
|
if (suppressEvent !== true) {
|
|
me.fireEvent('datachanged', me);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
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);
|
|
},
|
|
|
|
|
|
queryBy: function(fn, scope) {
|
|
var me = this,
|
|
data = me.snapshot || me.data;
|
|
return data.filterBy(fn, scope || me);
|
|
},
|
|
|
|
|
|
loadData: function(data, append) {
|
|
var model = this.model,
|
|
length = data.length,
|
|
newData = [],
|
|
i,
|
|
record;
|
|
|
|
|
|
for (i = 0; i < length; i++) {
|
|
record = data[i];
|
|
|
|
if (!(record instanceof Ext.data.Model)) {
|
|
record = Ext.ModelManager.create(record, model);
|
|
}
|
|
newData.push(record);
|
|
}
|
|
|
|
this.loadRecords(newData, {addRecords: append});
|
|
},
|
|
|
|
|
|
|
|
loadRawData : function(data, append) {
|
|
var me = this,
|
|
result = me.proxy.reader.read(data),
|
|
records = result.records;
|
|
|
|
if (result.success) {
|
|
me.loadRecords(records, { addRecords: append });
|
|
me.fireEvent('load', me, records, true);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
loadRecords: function(records, options) {
|
|
var me = this,
|
|
i = 0,
|
|
length = records.length;
|
|
|
|
options = options || {};
|
|
|
|
|
|
if (!options.addRecords) {
|
|
delete me.snapshot;
|
|
me.clearData();
|
|
}
|
|
|
|
me.data.addAll(records);
|
|
|
|
|
|
for (; i < length; i++) {
|
|
if (options.start !== undefined) {
|
|
records[i].index = options.start + i;
|
|
|
|
}
|
|
records[i].join(me);
|
|
}
|
|
|
|
|
|
me.suspendEvents();
|
|
|
|
if (me.filterOnLoad && !me.remoteFilter) {
|
|
me.filter();
|
|
}
|
|
|
|
if (me.sortOnLoad && !me.remoteSort) {
|
|
me.sort();
|
|
}
|
|
|
|
me.resumeEvents();
|
|
me.fireEvent('datachanged', me, records);
|
|
},
|
|
|
|
|
|
|
|
loadPage: function(page, options) {
|
|
var me = this;
|
|
options = Ext.apply({}, options);
|
|
|
|
me.currentPage = page;
|
|
|
|
me.read(Ext.applyIf(options, {
|
|
page: page,
|
|
start: (page - 1) * me.pageSize,
|
|
limit: me.pageSize,
|
|
addRecords: !me.clearOnPageLoad
|
|
}));
|
|
},
|
|
|
|
|
|
nextPage: function(options) {
|
|
this.loadPage(this.currentPage + 1, options);
|
|
},
|
|
|
|
|
|
previousPage: function(options) {
|
|
this.loadPage(this.currentPage - 1, options);
|
|
},
|
|
|
|
|
|
clearData: function() {
|
|
var me = this;
|
|
me.data.each(function(record) {
|
|
record.unjoin(me);
|
|
});
|
|
|
|
me.data.clear();
|
|
},
|
|
|
|
|
|
|
|
prefetch: function(options) {
|
|
var me = this,
|
|
operation,
|
|
requestId = me.getRequestId();
|
|
|
|
options = options || {};
|
|
|
|
Ext.applyIf(options, {
|
|
action : 'read',
|
|
filters: me.filters.items,
|
|
sorters: me.sorters.items,
|
|
requestId: requestId
|
|
});
|
|
me.pendingRequests.push(requestId);
|
|
|
|
operation = Ext.create('Ext.data.Operation', options);
|
|
|
|
|
|
|
|
|
|
|
|
if (me.fireEvent('beforeprefetch', me, operation) !== false) {
|
|
me.loading = true;
|
|
me.proxy.read(operation, me.onProxyPrefetch, me);
|
|
}
|
|
|
|
return me;
|
|
},
|
|
|
|
|
|
prefetchPage: function(page, options) {
|
|
var me = this,
|
|
pageSize = me.pageSize,
|
|
start = (page - 1) * me.pageSize,
|
|
end = start + pageSize;
|
|
|
|
|
|
if (Ext.Array.indexOf(me.pagesRequested, page) === -1 && !me.rangeSatisfied(start, end)) {
|
|
options = options || {};
|
|
me.pagesRequested.push(page);
|
|
Ext.applyIf(options, {
|
|
page : page,
|
|
start: start,
|
|
limit: pageSize,
|
|
callback: me.onWaitForGuarantee,
|
|
scope: me
|
|
});
|
|
|
|
me.prefetch(options);
|
|
}
|
|
|
|
},
|
|
|
|
|
|
getRequestId: function() {
|
|
this.requestSeed = this.requestSeed || 1;
|
|
return this.requestSeed++;
|
|
},
|
|
|
|
|
|
onProxyPrefetch: function(operation) {
|
|
var me = this,
|
|
resultSet = operation.getResultSet(),
|
|
records = operation.getRecords(),
|
|
|
|
successful = operation.wasSuccessful();
|
|
|
|
if (resultSet) {
|
|
me.totalCount = resultSet.total;
|
|
me.fireEvent('totalcountchange', me.totalCount);
|
|
}
|
|
|
|
if (successful) {
|
|
me.cacheRecords(records, operation);
|
|
}
|
|
Ext.Array.remove(me.pendingRequests, operation.requestId);
|
|
if (operation.page) {
|
|
Ext.Array.remove(me.pagesRequested, operation.page);
|
|
}
|
|
|
|
me.loading = false;
|
|
me.fireEvent('prefetch', me, records, successful, operation);
|
|
|
|
|
|
if (operation.blocking) {
|
|
me.fireEvent('load', me, records, successful);
|
|
}
|
|
|
|
|
|
Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
|
|
},
|
|
|
|
|
|
cacheRecords: function(records, operation) {
|
|
var me = this,
|
|
i = 0,
|
|
length = records.length,
|
|
start = operation ? operation.start : 0;
|
|
|
|
if (!Ext.isDefined(me.totalCount)) {
|
|
me.totalCount = records.length;
|
|
me.fireEvent('totalcountchange', me.totalCount);
|
|
}
|
|
|
|
for (; i < length; i++) {
|
|
|
|
records[i].index = start + i;
|
|
}
|
|
|
|
me.prefetchData.addAll(records);
|
|
if (me.purgePageCount) {
|
|
me.purgeRecords();
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
purgeRecords: function() {
|
|
var me = this,
|
|
prefetchCount = me.prefetchData.getCount(),
|
|
purgeCount = me.purgePageCount * me.pageSize,
|
|
numRecordsToPurge = prefetchCount - purgeCount - 1,
|
|
i = 0;
|
|
|
|
for (; i <= numRecordsToPurge; i++) {
|
|
me.prefetchData.removeAt(0);
|
|
}
|
|
},
|
|
|
|
|
|
rangeSatisfied: function(start, end) {
|
|
var me = this,
|
|
i = start,
|
|
satisfied = true;
|
|
|
|
for (; i < end; i++) {
|
|
if (!me.prefetchData.getByKey(i)) {
|
|
satisfied = false;
|
|
break;
|
|
}
|
|
}
|
|
return satisfied;
|
|
},
|
|
|
|
|
|
getPageFromRecordIndex: function(index) {
|
|
return Math.floor(index / this.pageSize) + 1;
|
|
},
|
|
|
|
|
|
onGuaranteedRange: function() {
|
|
var me = this,
|
|
totalCount = me.getTotalCount(),
|
|
start = me.requestStart,
|
|
end = ((totalCount - 1) < me.requestEnd) ? totalCount - 1 : me.requestEnd,
|
|
range = [],
|
|
record,
|
|
i = start;
|
|
|
|
end = Math.max(0, end);
|
|
|
|
|
|
if (start !== me.guaranteedStart && end !== me.guaranteedEnd) {
|
|
me.guaranteedStart = start;
|
|
me.guaranteedEnd = end;
|
|
|
|
for (; i <= end; i++) {
|
|
record = me.prefetchData.getByKey(i);
|
|
if (record) {
|
|
range.push(record);
|
|
}
|
|
}
|
|
me.fireEvent('guaranteedrange', range, start, end);
|
|
if (me.cb) {
|
|
me.cb.call(me.scope || me, range);
|
|
}
|
|
}
|
|
|
|
me.unmask();
|
|
},
|
|
|
|
|
|
mask: function() {
|
|
this.masked = true;
|
|
this.fireEvent('beforeload');
|
|
},
|
|
|
|
|
|
unmask: function() {
|
|
if (this.masked) {
|
|
this.fireEvent('load');
|
|
}
|
|
},
|
|
|
|
|
|
hasPendingRequests: function() {
|
|
return this.pendingRequests.length;
|
|
},
|
|
|
|
|
|
|
|
onWaitForGuarantee: function() {
|
|
if (!this.hasPendingRequests()) {
|
|
this.onGuaranteedRange();
|
|
}
|
|
},
|
|
|
|
|
|
guaranteeRange: function(start, end, cb, scope) {
|
|
|
|
end = (end > this.totalCount) ? this.totalCount - 1 : end;
|
|
|
|
var me = this,
|
|
i = start,
|
|
prefetchData = me.prefetchData,
|
|
range = [],
|
|
startLoaded = !!prefetchData.getByKey(start),
|
|
endLoaded = !!prefetchData.getByKey(end),
|
|
startPage = me.getPageFromRecordIndex(start),
|
|
endPage = me.getPageFromRecordIndex(end);
|
|
|
|
me.cb = cb;
|
|
me.scope = scope;
|
|
|
|
me.requestStart = start;
|
|
me.requestEnd = end;
|
|
|
|
if (!startLoaded || !endLoaded) {
|
|
|
|
if (startPage === endPage) {
|
|
me.mask();
|
|
me.prefetchPage(startPage, {
|
|
|
|
callback: me.onWaitForGuarantee,
|
|
scope: me
|
|
});
|
|
|
|
} else {
|
|
me.mask();
|
|
me.prefetchPage(startPage, {
|
|
|
|
callback: me.onWaitForGuarantee,
|
|
scope: me
|
|
});
|
|
me.prefetchPage(endPage, {
|
|
|
|
callback: me.onWaitForGuarantee,
|
|
scope: me
|
|
});
|
|
}
|
|
|
|
} else {
|
|
me.onGuaranteedRange();
|
|
}
|
|
},
|
|
|
|
|
|
|
|
sort: function() {
|
|
var me = this,
|
|
prefetchData = me.prefetchData,
|
|
sorters,
|
|
start,
|
|
end,
|
|
range;
|
|
|
|
if (me.buffered) {
|
|
if (me.remoteSort) {
|
|
prefetchData.clear();
|
|
me.callParent(arguments);
|
|
} else {
|
|
sorters = me.getSorters();
|
|
start = me.guaranteedStart;
|
|
end = me.guaranteedEnd;
|
|
|
|
if (sorters.length) {
|
|
prefetchData.sort(sorters);
|
|
range = prefetchData.getRange();
|
|
prefetchData.clear();
|
|
me.cacheRecords(range);
|
|
delete me.guaranteedStart;
|
|
delete me.guaranteedEnd;
|
|
me.guaranteeRange(start, end);
|
|
}
|
|
me.callParent(arguments);
|
|
}
|
|
} else {
|
|
me.callParent(arguments);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
doSort: function(sorterFn) {
|
|
var me = this;
|
|
if (me.remoteSort) {
|
|
|
|
me.load();
|
|
} else {
|
|
me.data.sortBy(sorterFn);
|
|
if (!me.buffered) {
|
|
var range = me.getRange(),
|
|
ln = range.length,
|
|
i = 0;
|
|
for (; i < ln; i++) {
|
|
range[i].index = i;
|
|
}
|
|
}
|
|
me.fireEvent('datachanged', 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 = this.data.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.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.length || 0;
|
|
},
|
|
|
|
|
|
getTotalCount: function() {
|
|
return this.totalCount;
|
|
},
|
|
|
|
|
|
getAt: function(index) {
|
|
return this.data.getAt(index);
|
|
},
|
|
|
|
|
|
getRange: function(start, end) {
|
|
return this.data.getRange(start, end);
|
|
},
|
|
|
|
|
|
getById: function(id) {
|
|
return (this.snapshot || this.data).findBy(function(record) {
|
|
return record.getId() === id;
|
|
});
|
|
},
|
|
|
|
|
|
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));
|
|
},
|
|
|
|
|
|
removeAll: function(silent) {
|
|
var me = this;
|
|
|
|
me.clearData();
|
|
if (me.snapshot) {
|
|
me.snapshot.clear();
|
|
}
|
|
if (silent !== true) {
|
|
me.fireEvent('clear', me);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
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(),
|
|
i = 0,
|
|
len = groups.length,
|
|
out = {},
|
|
group;
|
|
|
|
for (; i < len; ++i) {
|
|
group = groups[i];
|
|
out[group.name] = fn.apply(scope || this, [group.children].concat(args));
|
|
}
|
|
return out;
|
|
} else {
|
|
return fn.apply(scope || this, [this.data.items].concat(args));
|
|
}
|
|
}
|
|
}, function() {
|
|
|
|
|
|
|
|
Ext.regStore('ext-empty-store', {fields: [], proxy: 'proxy'});
|
|
});
|
|
|
|
|
|
Ext.define('Ext.data.JsonStore', {
|
|
extend: 'Ext.data.Store',
|
|
alias: 'store.json',
|
|
|
|
|
|
constructor: function(config) {
|
|
config = config || {};
|
|
|
|
Ext.applyIf(config, {
|
|
proxy: {
|
|
type : 'ajax',
|
|
reader: 'json',
|
|
writer: 'json'
|
|
}
|
|
});
|
|
|
|
this.callParent([config]);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.chart.axis.Time', {
|
|
|
|
|
|
|
|
extend: 'Ext.chart.axis.Numeric',
|
|
|
|
alternateClassName: 'Ext.chart.TimeAxis',
|
|
|
|
alias: 'axis.time',
|
|
|
|
requires: ['Ext.data.Store', 'Ext.data.JsonStore'],
|
|
|
|
|
|
|
|
|
|
dateFormat: false,
|
|
|
|
|
|
fromDate: false,
|
|
|
|
|
|
toDate: false,
|
|
|
|
|
|
step: [Ext.Date.DAY, 1],
|
|
|
|
|
|
constrain: false,
|
|
|
|
|
|
roundToDecimal: 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);
|
|
};
|
|
}
|
|
}
|
|
},
|
|
|
|
doConstrain: function () {
|
|
var me = this,
|
|
store = me.chart.store,
|
|
data = [],
|
|
series = me.chart.series.items,
|
|
math = Math,
|
|
mmax = math.max,
|
|
mmin = math.min,
|
|
fields = me.fields,
|
|
ln = fields.length,
|
|
range = me.getRange(),
|
|
min = range.min, max = range.max, i, l, excludes = [],
|
|
value, values, rec, data = [];
|
|
for (i = 0, l = series.length; i < l; i++) {
|
|
excludes[i] = series[i].__excludes;
|
|
}
|
|
store.each(function(record) {
|
|
for (i = 0; i < ln; i++) {
|
|
if (excludes[i]) {
|
|
continue;
|
|
}
|
|
value = record.get(fields[i]);
|
|
if (+value < +min) return;
|
|
if (+value > +max) return;
|
|
}
|
|
data.push(record);
|
|
})
|
|
me.chart.substore = Ext.create('Ext.data.JsonStore', { model: store.model, data: data });
|
|
},
|
|
|
|
|
|
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;
|
|
}
|
|
range.step = (range.to - range.from) / range.steps;
|
|
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,
|
|
|
|
//@private triggerdrawlistener flag
|
|
|
|
triggerAfterDraw: false,
|
|
|
|
|
|
|
|
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,
|
|
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
|
|
});
|
|
},
|
|
|
|
|
|
eachRecord: function(fn, scope) {
|
|
var chart = this.chart;
|
|
(chart.substore || chart.store).each(fn, scope);
|
|
},
|
|
|
|
|
|
getRecordCount: function() {
|
|
var chart = this.chart,
|
|
store = chart.substore || chart.store;
|
|
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,
|
|
gutterX = noGutter ? 0 : chart.maxGutter[0],
|
|
gutterY = noGutter ? 0 : chart.maxGutter[1],
|
|
clipBox, bbox;
|
|
|
|
clipBox = {
|
|
x: chartBBox.x,
|
|
y: chartBBox.y,
|
|
width: chartBBox.width,
|
|
height: chartBBox.height
|
|
};
|
|
me.clipBox = clipBox;
|
|
|
|
bbox = {
|
|
x: (clipBox.x + gutterX) - (chart.zoom.x * chart.zoom.width),
|
|
y: (clipBox.y + gutterY) - (chart.zoom.y * chart.zoom.height),
|
|
width: (clipBox.width - (gutterX * 2)) * chart.zoom.width,
|
|
height: (clipBox.height - (gutterY * 2)) * chart.zoom.height
|
|
};
|
|
me.bbox = bbox;
|
|
},
|
|
|
|
|
|
onAnimate: function(sprite, attr) {
|
|
var me = this;
|
|
sprite.stopAnimation();
|
|
if (me.triggerAfterDraw) {
|
|
return sprite.animate(Ext.applyIf(attr, me.chart.animate));
|
|
} else {
|
|
me.triggerAfterDraw = true;
|
|
return sprite.animate(Ext.apply(Ext.applyIf(attr, me.chart.animate), {
|
|
listeners: {
|
|
'afteranimate': function() {
|
|
me.triggerAfterDraw = false;
|
|
me.fireEvent('afterrender');
|
|
}
|
|
}
|
|
}));
|
|
}
|
|
},
|
|
|
|
|
|
getGutters: function() {
|
|
return [0, 0];
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
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;
|
|
}
|
|
return stroke;
|
|
}
|
|
return '#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 = [],
|
|
combinations = me.combinations;
|
|
|
|
Ext.each([].concat(me.yField), function(yField, i) {
|
|
var title = me.title;
|
|
|
|
labels.push((Ext.isArray(title) ? title[i] : title) || yField);
|
|
});
|
|
|
|
|
|
if (combinations) {
|
|
Ext.each(combinations, function(combo) {
|
|
var 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) {
|
|
Ext.each(this.getYValueAccessors(), function(accessor, 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;
|
|
if (!accessors) {
|
|
accessors = me.yValueAccessors = [];
|
|
Ext.each([].concat(me.yField), function(yField) {
|
|
accessors.push(function(record) {
|
|
return record.get(yField);
|
|
});
|
|
});
|
|
}
|
|
return accessors;
|
|
},
|
|
|
|
|
|
getMinMaxXValues: function() {
|
|
var me = this,
|
|
min, max,
|
|
xField = me.xField;
|
|
|
|
if (me.getRecordCount() > 0) {
|
|
min = Infinity;
|
|
max = -min;
|
|
me.eachRecord(function(record) {
|
|
var xValue = record.get(xField);
|
|
if (xValue > max) {
|
|
max = xValue;
|
|
}
|
|
if (xValue < min) {
|
|
min = xValue;
|
|
}
|
|
});
|
|
} else {
|
|
min = max = 0;
|
|
}
|
|
return [min, max];
|
|
},
|
|
|
|
|
|
getMinMaxYValues: function() {
|
|
var me = this,
|
|
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 (me.getRecordCount() > 0) {
|
|
min = Infinity;
|
|
max = -min;
|
|
me.eachRecord(function(record) {
|
|
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);
|
|
}
|
|
});
|
|
} else {
|
|
min = max = 0;
|
|
}
|
|
return [min, max];
|
|
},
|
|
|
|
getAxesForXAndYFields: function() {
|
|
var me = this,
|
|
axes = me.chart.axes,
|
|
axis = [].concat(me.axis),
|
|
xAxis, yAxis;
|
|
|
|
if (Ext.Array.indexOf(axis, 'top') > -1) {
|
|
xAxis = 'top';
|
|
} else if (Ext.Array.indexOf(axis, 'bottom') > -1) {
|
|
xAxis = 'bottom';
|
|
} else {
|
|
if (axes.get('top')) {
|
|
xAxis = 'top';
|
|
} else if (axes.get('bottom')) {
|
|
xAxis = 'bottom';
|
|
}
|
|
}
|
|
|
|
if (Ext.Array.indexOf(axis, 'left') > -1) {
|
|
yAxis = 'left';
|
|
} else if (Ext.Array.indexOf(axis, 'right') > -1) {
|
|
yAxis = 'right';
|
|
} else {
|
|
if (axes.get('left')) {
|
|
yAxis = 'left';
|
|
} else if (axes.get('right')) {
|
|
yAxis = 'right';
|
|
}
|
|
}
|
|
|
|
return {
|
|
xAxis: xAxis,
|
|
yAxis: yAxis
|
|
};
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.chart.series.Area', {
|
|
|
|
|
|
|
|
extend: 'Ext.chart.series.Cartesian',
|
|
|
|
alias: 'series.area',
|
|
|
|
requires: ['Ext.chart.axis.Axis', 'Ext.draw.Color', 'Ext.fx.Anim'],
|
|
|
|
|
|
|
|
type: 'area',
|
|
|
|
|
|
stacked: true,
|
|
|
|
|
|
style: {},
|
|
|
|
constructor: function(config) {
|
|
this.callParent(arguments);
|
|
var me = this,
|
|
surface = me.chart.surface,
|
|
i, l;
|
|
Ext.apply(me, config, {
|
|
__excludes: [],
|
|
highlightCfg: {
|
|
lineWidth: 3,
|
|
stroke: '#55c',
|
|
opacity: 0.8,
|
|
color: '#f00'
|
|
}
|
|
});
|
|
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(),
|
|
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,
|
|
bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem;
|
|
|
|
me.setBBox();
|
|
bbox = me.bbox;
|
|
|
|
|
|
if (me.axis) {
|
|
axis = chart.axes.get(me.axis);
|
|
if (axis) {
|
|
out = axis.calcEnds();
|
|
minY = out.from || axis.prevMin;
|
|
maxY = mmax(out.to || axis.prevMax, 0);
|
|
}
|
|
}
|
|
|
|
if (me.yField && !Ext.isNumber(minY)) {
|
|
axis = Ext.create('Ext.chart.axis.Axis', {
|
|
chart: chart,
|
|
fields: [].concat(me.yField)
|
|
});
|
|
out = axis.calcEnds();
|
|
minY = out.from || axis.prevMin;
|
|
maxY = mmax(out.to || axis.prevMax, 0);
|
|
}
|
|
|
|
if (!Ext.isNumber(minY)) {
|
|
minY = 0;
|
|
}
|
|
if (!Ext.isNumber(maxY)) {
|
|
maxY = 0;
|
|
}
|
|
|
|
store.each(function(record, i) {
|
|
xValue = record.get(me.xField);
|
|
yValue = [];
|
|
if (typeof xValue != 'number') {
|
|
xValue = i;
|
|
}
|
|
xValues.push(xValue);
|
|
acumY = 0;
|
|
for (areaIndex = 0; areaIndex < areasLen; areaIndex++) {
|
|
areaElem = record.get(areas[areaIndex]);
|
|
if (typeof areaElem == 'number') {
|
|
minY = mmin(minY, areaElem);
|
|
yValue.push(areaElem);
|
|
acumY += areaElem;
|
|
}
|
|
}
|
|
minX = mmin(minX, xValue);
|
|
maxX = mmax(maxX, xValue);
|
|
maxY = mmax(maxY, acumY);
|
|
yValues.push(yValue);
|
|
}, me);
|
|
|
|
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,
|
|
paths = [],
|
|
i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path;
|
|
|
|
ln = bounds.xValues.length;
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
xValue = bounds.xValues[i];
|
|
yValue = bounds.yValues[i];
|
|
x = bbox.x + (xValue - bounds.minX) * bounds.xScale;
|
|
acumY = 0;
|
|
for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
|
|
|
|
if (me.__excludes[areaIndex]) {
|
|
continue;
|
|
}
|
|
if (!componentPaths[areaIndex]) {
|
|
componentPaths[areaIndex] = [];
|
|
}
|
|
areaElem = yValue[areaIndex];
|
|
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]);
|
|
}
|
|
}
|
|
|
|
|
|
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', bbox.x, 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', bbox.x, 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,
|
|
areaIndex, areaElem, paths, path, rendererAttributes;
|
|
|
|
me.unHighlightItem();
|
|
me.cleanHighlights();
|
|
|
|
if (!store || !store.getCount()) {
|
|
return;
|
|
}
|
|
|
|
paths = me.getPaths();
|
|
|
|
if (!me.areas) {
|
|
me.areas = [];
|
|
}
|
|
|
|
for (areaIndex = 0; areaIndex < paths.areasLen; areaIndex++) {
|
|
|
|
if (me.__excludes[areaIndex]) {
|
|
continue;
|
|
}
|
|
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[areaIndex % colorArrayLength],
|
|
fill: colorArrayStyle[areaIndex % 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[areaIndex % colorArrayLength],
|
|
stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % 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) {
|
|
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': 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 = item.point[0],
|
|
y = item.point[1],
|
|
bb, width, height;
|
|
|
|
label.setAttributes({
|
|
text: format(storeItem.get(field[index])),
|
|
hidden: true
|
|
}, true);
|
|
|
|
bb = label.getBBox();
|
|
width = bb.width / 2;
|
|
height = bb.height / 2;
|
|
|
|
x = x - width < bbox.x? bbox.x + width : x;
|
|
x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
|
|
y = y - height < bbox.y? bbox.y + height : y;
|
|
y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
|
|
|
|
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.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.label.getBBox(),
|
|
offsetFromViz = 30,
|
|
offsetToSide = 10,
|
|
offsetBox = 3,
|
|
boxx, boxy, boxw, boxh,
|
|
p, clipRect = me.clipRect,
|
|
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;
|
|
|
|
|
|
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,
|
|
dist = Infinity, p, pln, point;
|
|
|
|
for (p = 0, pln = pointsUp.length; p < pln; p++) {
|
|
point = [pointsUp[p][0], pointsUp[p][1]];
|
|
if (dist > abs(x - point[0])) {
|
|
dist = abs(x - point[0]);
|
|
} else {
|
|
point = pointsUp[p -1];
|
|
if (y >= point[1] && (!pointsDown.length || y <= (pointsDown[p -1][1]))) {
|
|
item.storeIndex = p -1;
|
|
item.storeField = me.yField[i];
|
|
item.storeItem = me.chart.store.getAt(p -1);
|
|
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 = Ext.create('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 = Ext.create('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;
|
|
path = points.length == 2? ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]
|
|
: ['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() {
|
|
if (!isNaN(this._index)) {
|
|
this.__excludes[this._index] = true;
|
|
this.areas[this._index].hide(true);
|
|
this.drawSeries();
|
|
}
|
|
},
|
|
|
|
|
|
showAll: function() {
|
|
if (!isNaN(this._index)) {
|
|
this.__excludes[this._index] = false;
|
|
this.areas[this._index].show(true);
|
|
this.drawSeries();
|
|
}
|
|
},
|
|
|
|
|
|
getLegendColor: function(index) {
|
|
var me = this;
|
|
return me.colorArrayStyle[index % me.colorArrayStyle.length];
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.chart.series.Area', {
|
|
|
|
|
|
|
|
extend: 'Ext.chart.series.Cartesian',
|
|
|
|
alias: 'series.area',
|
|
|
|
requires: ['Ext.chart.axis.Axis', 'Ext.draw.Color', 'Ext.fx.Anim'],
|
|
|
|
|
|
|
|
type: 'area',
|
|
|
|
|
|
stacked: true,
|
|
|
|
|
|
style: {},
|
|
|
|
constructor: function(config) {
|
|
this.callParent(arguments);
|
|
var me = this,
|
|
surface = me.chart.surface,
|
|
i, l;
|
|
Ext.apply(me, config, {
|
|
__excludes: [],
|
|
highlightCfg: {
|
|
lineWidth: 3,
|
|
stroke: '#55c',
|
|
opacity: 0.8,
|
|
color: '#f00'
|
|
}
|
|
});
|
|
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(),
|
|
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,
|
|
bbox, xScale, yScale, xValue, yValue, areaIndex, acumY, ln, sumValues, clipBox, areaElem;
|
|
|
|
me.setBBox();
|
|
bbox = me.bbox;
|
|
|
|
|
|
if (me.axis) {
|
|
axis = chart.axes.get(me.axis);
|
|
if (axis) {
|
|
out = axis.calcEnds();
|
|
minY = out.from || axis.prevMin;
|
|
maxY = mmax(out.to || axis.prevMax, 0);
|
|
}
|
|
}
|
|
|
|
if (me.yField && !Ext.isNumber(minY)) {
|
|
axis = Ext.create('Ext.chart.axis.Axis', {
|
|
chart: chart,
|
|
fields: [].concat(me.yField)
|
|
});
|
|
out = axis.calcEnds();
|
|
minY = out.from || axis.prevMin;
|
|
maxY = mmax(out.to || axis.prevMax, 0);
|
|
}
|
|
|
|
if (!Ext.isNumber(minY)) {
|
|
minY = 0;
|
|
}
|
|
if (!Ext.isNumber(maxY)) {
|
|
maxY = 0;
|
|
}
|
|
|
|
store.each(function(record, i) {
|
|
xValue = record.get(me.xField);
|
|
yValue = [];
|
|
if (typeof xValue != 'number') {
|
|
xValue = i;
|
|
}
|
|
xValues.push(xValue);
|
|
acumY = 0;
|
|
for (areaIndex = 0; areaIndex < areasLen; areaIndex++) {
|
|
areaElem = record.get(areas[areaIndex]);
|
|
if (typeof areaElem == 'number') {
|
|
minY = mmin(minY, areaElem);
|
|
yValue.push(areaElem);
|
|
acumY += areaElem;
|
|
}
|
|
}
|
|
minX = mmin(minX, xValue);
|
|
maxX = mmax(maxX, xValue);
|
|
maxY = mmax(maxY, acumY);
|
|
yValues.push(yValue);
|
|
}, me);
|
|
|
|
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,
|
|
paths = [],
|
|
i, ln, x, y, xValue, yValue, acumY, areaIndex, prevAreaIndex, areaElem, path;
|
|
|
|
ln = bounds.xValues.length;
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
xValue = bounds.xValues[i];
|
|
yValue = bounds.yValues[i];
|
|
x = bbox.x + (xValue - bounds.minX) * bounds.xScale;
|
|
acumY = 0;
|
|
for (areaIndex = 0; areaIndex < bounds.areasLen; areaIndex++) {
|
|
|
|
if (me.__excludes[areaIndex]) {
|
|
continue;
|
|
}
|
|
if (!componentPaths[areaIndex]) {
|
|
componentPaths[areaIndex] = [];
|
|
}
|
|
areaElem = yValue[areaIndex];
|
|
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]);
|
|
}
|
|
}
|
|
|
|
|
|
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', bbox.x, 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', bbox.x, 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,
|
|
areaIndex, areaElem, paths, path, rendererAttributes;
|
|
|
|
me.unHighlightItem();
|
|
me.cleanHighlights();
|
|
|
|
if (!store || !store.getCount()) {
|
|
return;
|
|
}
|
|
|
|
paths = me.getPaths();
|
|
|
|
if (!me.areas) {
|
|
me.areas = [];
|
|
}
|
|
|
|
for (areaIndex = 0; areaIndex < paths.areasLen; areaIndex++) {
|
|
|
|
if (me.__excludes[areaIndex]) {
|
|
continue;
|
|
}
|
|
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[areaIndex % colorArrayLength],
|
|
fill: colorArrayStyle[areaIndex % 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[areaIndex % colorArrayLength],
|
|
stroke: endLineStyle.stroke || colorArrayStyle[areaIndex % 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) {
|
|
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': 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 = item.point[0],
|
|
y = item.point[1],
|
|
bb, width, height;
|
|
|
|
label.setAttributes({
|
|
text: format(storeItem.get(field[index])),
|
|
hidden: true
|
|
}, true);
|
|
|
|
bb = label.getBBox();
|
|
width = bb.width / 2;
|
|
height = bb.height / 2;
|
|
|
|
x = x - width < bbox.x? bbox.x + width : x;
|
|
x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
|
|
y = y - height < bbox.y? bbox.y + height : y;
|
|
y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
|
|
|
|
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.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.label.getBBox(),
|
|
offsetFromViz = 30,
|
|
offsetToSide = 10,
|
|
offsetBox = 3,
|
|
boxx, boxy, boxw, boxh,
|
|
p, clipRect = me.clipRect,
|
|
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;
|
|
|
|
|
|
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,
|
|
dist = Infinity, p, pln, point;
|
|
|
|
for (p = 0, pln = pointsUp.length; p < pln; p++) {
|
|
point = [pointsUp[p][0], pointsUp[p][1]];
|
|
if (dist > abs(x - point[0])) {
|
|
dist = abs(x - point[0]);
|
|
} else {
|
|
point = pointsUp[p -1];
|
|
if (y >= point[1] && (!pointsDown.length || y <= (pointsDown[p -1][1]))) {
|
|
item.storeIndex = p -1;
|
|
item.storeField = me.yField[i];
|
|
item.storeItem = me.chart.store.getAt(p -1);
|
|
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 = Ext.create('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 = Ext.create('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;
|
|
path = points.length == 2? ['M', points[0][0], points[0][1], 'L', points[1][0], points[1][1]]
|
|
: ['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() {
|
|
if (!isNaN(this._index)) {
|
|
this.__excludes[this._index] = true;
|
|
this.areas[this._index].hide(true);
|
|
this.drawSeries();
|
|
}
|
|
},
|
|
|
|
|
|
showAll: function() {
|
|
if (!isNaN(this._index)) {
|
|
this.__excludes[this._index] = false;
|
|
this.areas[this._index].show(true);
|
|
this.drawSeries();
|
|
}
|
|
},
|
|
|
|
|
|
getLegendColor: function(index) {
|
|
var me = this;
|
|
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'],
|
|
|
|
requires: ['Ext.chart.axis.Axis', 'Ext.fx.Anim'],
|
|
|
|
|
|
|
|
type: 'bar',
|
|
|
|
alias: 'series.bar',
|
|
|
|
column: false,
|
|
|
|
|
|
style: {},
|
|
|
|
|
|
gutter: 38.2,
|
|
|
|
|
|
groupGutter: 38.2,
|
|
|
|
|
|
xPadding: 0,
|
|
|
|
|
|
yPadding: 10,
|
|
|
|
constructor: function(config) {
|
|
this.callParent(arguments);
|
|
var me = this,
|
|
surface = me.chart.surface,
|
|
shadow = me.chart.shadow,
|
|
i, l;
|
|
Ext.apply(me, config, {
|
|
highlightCfg: {
|
|
lineWidth: 3,
|
|
stroke: '#55c',
|
|
opacity: 0.8,
|
|
color: '#f00'
|
|
},
|
|
|
|
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));
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getBarGirth: function() {
|
|
var me = this,
|
|
store = me.chart.getChartStore(),
|
|
column = me.column,
|
|
ln = store.getCount(),
|
|
gutter = me.gutter / 100;
|
|
|
|
return (me.chart.chartBBox[column ? 'width' : 'height'] - me[column ? 'xPadding' : 'yPadding'] * 2) / (ln * (gutter + 1) - gutter);
|
|
},
|
|
|
|
|
|
getGutters: function() {
|
|
var me = this,
|
|
column = me.column,
|
|
gutter = Math.ceil(me[column ? 'xPadding' : 'yPadding'] + me.getBarGirth() / 2);
|
|
return me.column ? [gutter, 0] : [0, gutter];
|
|
},
|
|
|
|
|
|
getBounds: function() {
|
|
var me = this,
|
|
chart = me.chart,
|
|
store = chart.getChartStore(),
|
|
bars = [].concat(me.yField),
|
|
barsLen = bars.length,
|
|
groupBarsLen = barsLen,
|
|
groupGutter = me.groupGutter / 100,
|
|
column = me.column,
|
|
xPadding = me.xPadding,
|
|
yPadding = me.yPadding,
|
|
stacked = me.stacked,
|
|
barWidth = me.getBarGirth(),
|
|
math = Math,
|
|
mmax = math.max,
|
|
mabs = math.abs,
|
|
groupBarWidth, bbox, minY, maxY, axis, out,
|
|
scale, zero, total, rec, j, plus, minus;
|
|
|
|
me.setBBox(true);
|
|
bbox = me.bbox;
|
|
|
|
|
|
if (me.__excludes) {
|
|
for (j = 0, total = me.__excludes.length; j < total; j++) {
|
|
if (me.__excludes[j]) {
|
|
groupBarsLen--;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (me.axis) {
|
|
axis = chart.axes.get(me.axis);
|
|
if (axis) {
|
|
out = axis.calcEnds();
|
|
minY = out.from;
|
|
maxY = out.to;
|
|
}
|
|
}
|
|
|
|
if (me.yField && !Ext.isNumber(minY)) {
|
|
axis = Ext.create('Ext.chart.axis.Axis', {
|
|
chart: chart,
|
|
fields: [].concat(me.yField)
|
|
});
|
|
out = axis.calcEnds();
|
|
minY = out.from;
|
|
maxY = out.to;
|
|
}
|
|
|
|
if (!Ext.isNumber(minY)) {
|
|
minY = 0;
|
|
}
|
|
if (!Ext.isNumber(maxY)) {
|
|
maxY = 0;
|
|
}
|
|
scale = (column ? bbox.height - yPadding * 2 : bbox.width - xPadding * 2) / (maxY - minY);
|
|
groupBarWidth = barWidth / ((stacked ? 1 : groupBarsLen) * (groupGutter + 1) - groupGutter);
|
|
zero = (column) ? bbox.y + bbox.height - yPadding : bbox.x + xPadding;
|
|
|
|
if (stacked) {
|
|
total = [[], []];
|
|
store.each(function(record, 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 - yPadding * 2 : bbox.width - xPadding * 2) / (plus + minus);
|
|
zero = zero + minus * scale * (column ? -1 : 1);
|
|
}
|
|
else if (minY / maxY < 0) {
|
|
zero = zero - minY * scale * (column ? -1 : 1);
|
|
}
|
|
return {
|
|
bars: bars,
|
|
bbox: bbox,
|
|
barsLen: barsLen,
|
|
groupBarsLen: groupBarsLen,
|
|
barWidth: barWidth,
|
|
groupBarWidth: groupBarWidth,
|
|
scale: scale,
|
|
zero: zero,
|
|
xPadding: xPadding,
|
|
yPadding: yPadding,
|
|
signed: minY / maxY < 0,
|
|
minY: minY,
|
|
maxY: maxY
|
|
};
|
|
},
|
|
|
|
|
|
getPaths: function() {
|
|
var me = this,
|
|
chart = me.chart,
|
|
store = chart.getChartStore(),
|
|
bounds = me.bounds = me.getBounds(),
|
|
items = me.items = [],
|
|
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,
|
|
xPadding = me.xPadding,
|
|
yPadding = me.yPadding,
|
|
stacked = me.stacked,
|
|
barsLen = bounds.barsLen,
|
|
colors = me.colorArrayStyle,
|
|
colorLength = colors && colors.length || 0,
|
|
math = Math,
|
|
mmax = math.max,
|
|
mmin = math.min,
|
|
mabs = math.abs,
|
|
j, yValue, height, totalDim, totalNegDim, bottom, top, hasShadow, barAttr, attrs, counter,
|
|
shadowIndex, shadow, sprite, offset, floorY;
|
|
|
|
store.each(function(record, i, total) {
|
|
bottom = bounds.zero;
|
|
top = bounds.zero;
|
|
totalDim = 0;
|
|
totalNegDim = 0;
|
|
hasShadow = false;
|
|
for (j = 0, counter = 0; j < barsLen; j++) {
|
|
|
|
if (me.__excludes && me.__excludes[j]) {
|
|
continue;
|
|
}
|
|
yValue = record.get(bounds.bars[j]);
|
|
height = Math.round((yValue - mmax(bounds.minY, 0)) * bounds.scale);
|
|
barAttr = {
|
|
fill: colors[(barsLen > 1 ? j : 0) % colorLength]
|
|
};
|
|
if (column) {
|
|
Ext.apply(barAttr, {
|
|
height: height,
|
|
width: mmax(bounds.groupBarWidth, 0),
|
|
x: (bbox.x + xPadding + i * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked),
|
|
y: bottom - height
|
|
});
|
|
}
|
|
else {
|
|
|
|
offset = (total - 1) - i;
|
|
Ext.apply(barAttr, {
|
|
height: mmax(bounds.groupBarWidth, 0),
|
|
width: height + (bottom == bounds.zero),
|
|
x: bottom + (bottom != bounds.zero),
|
|
y: (bbox.y + yPadding + offset * bounds.barWidth * (1 + gutter) + counter * bounds.groupBarWidth * (1 + groupGutter) * !stacked + 1)
|
|
});
|
|
}
|
|
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.isIE9 && barAttr.y > floorY) {
|
|
floorY--;
|
|
}
|
|
barAttr.y = floorY;
|
|
barAttr.width = Math.floor(barAttr.width);
|
|
barAttr.height = Math.floor(barAttr.height);
|
|
items.push({
|
|
series: me,
|
|
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;
|
|
}
|
|
}, me);
|
|
},
|
|
|
|
|
|
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 = [],
|
|
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;
|
|
shadowBarAttr.height = totalDim;
|
|
}
|
|
else {
|
|
shadowBarAttr.x = zero - totalNegDim;
|
|
shadowBarAttr.width = totalDim;
|
|
}
|
|
}
|
|
if (animate) {
|
|
if (!stacked) {
|
|
rendererAttributes = me.renderer(shadow, store.getAt(j), shadowBarAttr, i, store);
|
|
me.onAnimate(shadow, { to: rendererAttributes });
|
|
}
|
|
else {
|
|
rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: true }), i, store);
|
|
shadow.setAttributes(rendererAttributes, true);
|
|
}
|
|
}
|
|
else {
|
|
rendererAttributes = me.renderer(shadow, store.getAt(j), Ext.apply(shadowBarAttr, { hidden: false }), i, store);
|
|
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,
|
|
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()) {
|
|
return;
|
|
}
|
|
|
|
|
|
delete seriesStyle.fill;
|
|
endSeriesStyle = Ext.apply(seriesStyle, this.style);
|
|
me.unHighlightItem();
|
|
me.cleanHighlights();
|
|
|
|
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, { 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 (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, j, 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,
|
|
rotate = config.orientation == 'vertical',
|
|
field = [].concat(config.field),
|
|
format = config.renderer,
|
|
text = format(storeItem.get(field[index])),
|
|
size = me.getLabelSize(text),
|
|
width = size.width,
|
|
height = size.height,
|
|
zero = opt.zero,
|
|
outside = 'outside',
|
|
insideStart = 'insideStart',
|
|
insideEnd = 'insideEnd',
|
|
offsetX = 10,
|
|
offsetY = 6,
|
|
signed = opt.signed,
|
|
x, y, finalAttr;
|
|
|
|
label.setAttributes({
|
|
text: text
|
|
});
|
|
|
|
label.isOutside = false;
|
|
if (column) {
|
|
if (display == outside) {
|
|
if (height + offsetY + attr.height > (yValue >= 0 ? zero - chartBBox.y : chartBBox.y + chartBBox.height - zero)) {
|
|
display = insideEnd;
|
|
}
|
|
} else {
|
|
if (height + offsetY > attr.height) {
|
|
display = outside;
|
|
label.isOutside = true;
|
|
}
|
|
}
|
|
x = attr.x + groupBarWidth / 2;
|
|
y = display == insideStart ?
|
|
(zero + ((height / 2 + 3) * (yValue >= 0 ? -1 : 1))) :
|
|
(yValue >= 0 ? (attr.y + ((height / 2 + 3) * (display == outside ? -1 : 1))) :
|
|
(attr.y + attr.height + ((height / 2 + 3) * (display === outside ? 1 : -1))));
|
|
}
|
|
else {
|
|
if (display == outside) {
|
|
if (width + offsetX + attr.width > (yValue >= 0 ? chartBBox.x + chartBBox.width - zero : zero - chartBBox.x)) {
|
|
display = insideEnd;
|
|
}
|
|
}
|
|
else {
|
|
if (width + offsetX > attr.width) {
|
|
display = outside;
|
|
label.isOutside = true;
|
|
}
|
|
}
|
|
x = display == insideStart ?
|
|
(zero + ((width / 2 + 5) * (yValue >= 0 ? 1 : -1))) :
|
|
(yValue >= 0 ? (attr.x + attr.width + ((width / 2 + 5) * (display === outside ? 1 : -1))) :
|
|
(attr.x + ((width / 2 + 5) * (display === outside ? -1 : 1))));
|
|
y = attr.y + groupBarWidth / 2;
|
|
}
|
|
|
|
finalAttr = {
|
|
x: x,
|
|
y: y
|
|
};
|
|
|
|
if (rotate) {
|
|
finalAttr.rotate = {
|
|
x: x,
|
|
y: y,
|
|
degrees: 270
|
|
};
|
|
}
|
|
|
|
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, { to: finalAttr });
|
|
}
|
|
else {
|
|
label.setAttributes(Ext.apply(finalAttr, {
|
|
hidden: false
|
|
}), true);
|
|
}
|
|
},
|
|
|
|
|
|
getLabelSize: function(value) {
|
|
var tester = this.testerLabel,
|
|
config = this.label,
|
|
endLabelStyle = Ext.apply({}, config, 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({
|
|
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) {
|
|
sprite.show();
|
|
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() {
|
|
var axes = this.chart.axes;
|
|
if (!isNaN(this._index)) {
|
|
if (!this.__excludes) {
|
|
this.__excludes = [];
|
|
}
|
|
this.__excludes[this._index] = true;
|
|
this.drawSeries();
|
|
axes.each(function(axis) {
|
|
axis.drawAxis();
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
showAll: function() {
|
|
var axes = this.chart.axes;
|
|
if (!isNaN(this._index)) {
|
|
if (!this.__excludes) {
|
|
this.__excludes = [];
|
|
}
|
|
this.__excludes[this._index] = false;
|
|
this.drawSeries();
|
|
axes.each(function(axis) {
|
|
axis.drawAxis();
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
getLegendColor: function(index) {
|
|
var me = this,
|
|
colorLength = me.colorArrayStyle.length;
|
|
|
|
if (me.style && me.style.fill) {
|
|
return me.style.fill;
|
|
} else {
|
|
return me.colorArrayStyle[index % colorLength];
|
|
}
|
|
},
|
|
|
|
highlightItem: function(item) {
|
|
this.callParent(arguments);
|
|
this.renderLabels();
|
|
},
|
|
|
|
unHighlightItem: function() {
|
|
this.callParent(arguments);
|
|
this.renderLabels();
|
|
},
|
|
|
|
cleanHighlights: function() {
|
|
this.callParent(arguments);
|
|
this.renderLabels();
|
|
}
|
|
});
|
|
|
|
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,
|
|
|
|
|
|
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);
|
|
};
|
|
},
|
|
|
|
//@private updates some onbefore render parameters.
|
|
|
|
initialize: function() {
|
|
var me = this,
|
|
store = me.chart.getChartStore();
|
|
|
|
me.yField = [];
|
|
if (me.label.field) {
|
|
store.each(function(rec) {
|
|
me.yField.push(rec.get(me.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,
|
|
gutterX = chart.maxGutter[0],
|
|
gutterY = chart.maxGutter[1],
|
|
cos = Math.cos,
|
|
sin = Math.sin,
|
|
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()) {
|
|
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 = me.value;
|
|
if (me.needle) {
|
|
sliceA = {
|
|
series: me,
|
|
value: value,
|
|
startAngle: -180,
|
|
endAngle: 0,
|
|
rho: me.radius
|
|
};
|
|
splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
|
|
slices.push(sliceA);
|
|
} else {
|
|
splitAngle = -180 * (1 - (value - minimum) / (maximum - minimum));
|
|
sliceA = {
|
|
series: me,
|
|
value: value,
|
|
startAngle: -180,
|
|
endAngle: splitAngle,
|
|
rho: me.radius
|
|
};
|
|
sliceB = {
|
|
series: me,
|
|
value: me.maximum - value,
|
|
startAngle: splitAngle,
|
|
endAngle: 0,
|
|
rho: me.radius
|
|
};
|
|
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) {
|
|
return false;
|
|
},
|
|
|
|
|
|
showAll: function() {
|
|
if (!isNaN(this._index)) {
|
|
this.__excludes[this._index] = false;
|
|
this.drawSeries();
|
|
}
|
|
},
|
|
|
|
|
|
getLegendColor: function(index) {
|
|
var me = this;
|
|
return me.colorArrayStyle[index % me.colorArrayStyle.length];
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.chart.series.Line', {
|
|
|
|
|
|
|
|
extend: 'Ext.chart.series.Cartesian',
|
|
|
|
alternateClassName: ['Ext.chart.LineSeries', 'Ext.chart.LineChart'],
|
|
|
|
requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.draw.Draw', 'Ext.fx.Anim'],
|
|
|
|
|
|
|
|
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;
|
|
Ext.apply(me, config, {
|
|
highlightCfg: {
|
|
'stroke-width': 3
|
|
},
|
|
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(),
|
|
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 = [],
|
|
xValueMap = {},
|
|
yValues = [],
|
|
yValueMap = {},
|
|
onbreak = false,
|
|
storeIndices = [],
|
|
markerStyle = me.markerStyle,
|
|
seriesStyle = me.style,
|
|
colorArrayStyle = me.colorArrayStyle,
|
|
colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
|
|
isNumber = Ext.isNumber,
|
|
seriesIdx = me.seriesIdx,
|
|
boundAxes = me.getAxesForXAndYFields(),
|
|
boundXAxis = boundAxes.xAxis,
|
|
boundYAxis = boundAxes.yAxis,
|
|
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, items;
|
|
|
|
if (me.fireEvent('beforedraw', me) === false) {
|
|
return;
|
|
}
|
|
|
|
|
|
if (!storeCount || me.seriesIsHidden) {
|
|
items = this.items;
|
|
if (items) {
|
|
for (i = 0, ln = items.length; i < ln; ++i) {
|
|
if (items[i].sprite) {
|
|
items[i].sprite.hide(true);
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
endMarkerStyle = Ext.apply(markerStyle || {}, me.markerConfig);
|
|
type = endMarkerStyle.type;
|
|
delete endMarkerStyle.type;
|
|
endLineStyle = seriesStyle;
|
|
|
|
|
|
if (!endLineStyle['stroke-width']) {
|
|
endLineStyle['stroke-width'] = 0.5;
|
|
}
|
|
|
|
|
|
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];
|
|
for (i = 0, ln = axes.length; i < ln; i++) {
|
|
axis = chartAxes.get(axes[i]);
|
|
if (axis) {
|
|
ends = axis.calcEnds();
|
|
if (axis.position == 'top' || axis.position == 'bottom') {
|
|
minX = ends.from;
|
|
maxX = ends.to;
|
|
}
|
|
else {
|
|
minY = ends.from;
|
|
maxY = ends.to;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (me.xField && !isNumber(minX) &&
|
|
(boundXAxis == 'bottom' || boundXAxis == 'top') &&
|
|
!chartAxes.get(boundXAxis)) {
|
|
axis = Ext.create('Ext.chart.axis.Axis', {
|
|
chart: chart,
|
|
fields: [].concat(me.xField)
|
|
}).calcEnds();
|
|
minX = axis.from;
|
|
maxX = axis.to;
|
|
}
|
|
if (me.yField && !isNumber(minY) &&
|
|
(boundYAxis == 'right' || boundYAxis == 'left') &&
|
|
!chartAxes.get(boundYAxis)) {
|
|
axis = Ext.create('Ext.chart.axis.Axis', {
|
|
chart: chart,
|
|
fields: [].concat(me.yField)
|
|
}).calcEnds();
|
|
minY = axis.from;
|
|
maxY = axis.to;
|
|
}
|
|
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);
|
|
}
|
|
|
|
|
|
me.eachRecord(function(record, i) {
|
|
xValue = record.get(me.xField);
|
|
|
|
|
|
if (typeof xValue == 'string' || typeof xValue == 'object' && !Ext.isDate(xValue)
|
|
|
|
|| boundXAxis && chartAxes.get(boundXAxis) && chartAxes.get(boundXAxis).type == 'Category') {
|
|
if (xValue in xValueMap) {
|
|
xValue = xValueMap[xValue];
|
|
} else {
|
|
xValue = xValueMap[xValue] = i;
|
|
}
|
|
}
|
|
|
|
|
|
yValue = record.get(me.yField);
|
|
|
|
if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
|
|
return;
|
|
}
|
|
|
|
if (typeof yValue == 'string' || typeof yValue == 'object' && !Ext.isDate(yValue)
|
|
|
|
|| boundYAxis && chartAxes.get(boundYAxis) && chartAxes.get(boundYAxis).type == '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 {
|
|
x = (bbox.x + (xValue - minX) * xScale).toFixed(2);
|
|
y = ((bbox.y + bbox.height) - (yValue - minY) * yScale).toFixed(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
|
|
}, true);
|
|
if (me.fillPath) {
|
|
me.fillPath.setAttributes({
|
|
path: dummyPath,
|
|
opacity: 0.2
|
|
}, 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 || {}));
|
|
|
|
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[seriesIdx % 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',
|
|
opacity: endLineStyle.opacity || 0.3,
|
|
fill: endLineStyle.fill || colorArrayStyle[seriesIdx % 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[seriesIdx % colorArrayLength],
|
|
'stroke-width': 0
|
|
}, 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.apply(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);
|
|
|
|
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
|
|
}, 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);
|
|
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': item.point[0],
|
|
'y': bbox.y + bbox.height / 2
|
|
}, endLabelStyle || {}));
|
|
},
|
|
|
|
|
|
onPlaceLabel: function(label, storeItem, item, i, display, animate) {
|
|
var me = this,
|
|
chart = me.chart,
|
|
resizing = chart.resizing,
|
|
config = me.label,
|
|
format = config.renderer,
|
|
field = config.field,
|
|
bbox = me.bbox,
|
|
x = item.point[0],
|
|
y = item.point[1],
|
|
radius = item.sprite.attr.radius,
|
|
bb, width, height;
|
|
|
|
label.setAttributes({
|
|
text: format(storeItem.get(field)),
|
|
hidden: true
|
|
}, true);
|
|
|
|
if (display == 'rotate') {
|
|
label.setAttributes({
|
|
'text-anchor': 'start',
|
|
'rotation': {
|
|
x: x,
|
|
y: y,
|
|
degrees: -45
|
|
}
|
|
}, true);
|
|
|
|
bb = label.getBBox();
|
|
width = bb.width;
|
|
height = bb.height;
|
|
x = x < bbox.x? bbox.x : x;
|
|
x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
|
|
y = (y - height < bbox.y)? bbox.y + height : y;
|
|
|
|
} else if (display == 'under' || display == 'over') {
|
|
|
|
bb = item.sprite.getBBox();
|
|
bb.width = bb.width || (radius * 2);
|
|
bb.height = bb.height || (radius * 2);
|
|
y = y + (display == 'over'? -bb.height : bb.height);
|
|
|
|
bb = label.getBBox();
|
|
width = bb.width/2;
|
|
height = bb.height/2;
|
|
x = x - width < bbox.x? bbox.x + width : x;
|
|
x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
|
|
y = y - height < bbox.y? bbox.y + height : y;
|
|
y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
|
|
}
|
|
|
|
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);
|
|
}
|
|
}
|
|
},
|
|
|
|
//@private Overriding highlights.js highlightItem method.
|
|
|
|
highlightItem: function() {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
if (me.line && !me.highlighted) {
|
|
if (!('__strokeWidth' in me.line)) {
|
|
me.line.__strokeWidth = me.line.attr['stroke-width'] || 0;
|
|
}
|
|
if (me.line.__anim) {
|
|
me.line.__anim.paused = true;
|
|
}
|
|
me.line.__anim = Ext.create('Ext.fx.Anim', {
|
|
target: me.line,
|
|
to: {
|
|
'stroke-width': me.line.__strokeWidth + 3
|
|
}
|
|
});
|
|
me.highlighted = true;
|
|
}
|
|
},
|
|
|
|
//@private Overriding highlights.js unHighlightItem method.
|
|
|
|
unHighlightItem: function() {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
if (me.line && me.highlighted) {
|
|
me.line.__anim = Ext.create('Ext.fx.Anim', {
|
|
target: me.line,
|
|
to: {
|
|
'stroke-width': me.line.__strokeWidth
|
|
}
|
|
});
|
|
me.highlighted = false;
|
|
}
|
|
},
|
|
|
|
//@private called when a callout needs to be placed.
|
|
|
|
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',
|
|
|
|
rad: Math.PI / 180,
|
|
|
|
|
|
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;
|
|
Ext.applyIf(me, {
|
|
highlightCfg: {
|
|
segment: {
|
|
margin: 20
|
|
}
|
|
}
|
|
});
|
|
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);
|
|
};
|
|
me.__excludes = me.__excludes || [];
|
|
},
|
|
|
|
//@private updates some onbefore render parameters.
|
|
|
|
initialize: function() {
|
|
var me = this,
|
|
store = me.chart.getChartStore();
|
|
|
|
me.yField = [];
|
|
if (me.label.field) {
|
|
store.each(function(rec) {
|
|
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;
|
|
|
|
if (Math.abs(x2 - x4) + Math.abs(y2 - y4) < delta) {
|
|
cm = hsqr2;
|
|
sm = -hsqr2;
|
|
flag = 1;
|
|
}
|
|
|
|
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(),
|
|
group = me.group,
|
|
animate = me.chart.animate,
|
|
field = me.angleField || me.field || me.xField,
|
|
lenField = [].concat(me.lengthField),
|
|
totalLenField = 0,
|
|
colors = me.colorSet,
|
|
chart = me.chart,
|
|
surface = chart.surface,
|
|
chartBBox = chart.chartBBox,
|
|
enableShadows = chart.shadow,
|
|
shadowGroups = me.shadowGroups,
|
|
shadowAttributes = me.shadowAttributes,
|
|
lnsh = shadowGroups.length,
|
|
rad = me.rad,
|
|
layers = lenField.length,
|
|
rhoAcum = 0,
|
|
donut = +me.donut,
|
|
layerTotals = [],
|
|
values = {},
|
|
fieldLength,
|
|
items = [],
|
|
passed = false,
|
|
totalField = 0,
|
|
maxLenField = 0,
|
|
cut = 9,
|
|
defcut = true,
|
|
angle = 0,
|
|
seriesStyle = me.seriesStyle,
|
|
seriesLabelStyle = me.seriesLabelStyle,
|
|
colorArrayStyle = me.colorArrayStyle,
|
|
colorArrayLength = colorArrayStyle && colorArrayStyle.length || 0,
|
|
gutterX = chart.maxGutter[0],
|
|
gutterY = chart.maxGutter[1],
|
|
abs = Math.abs,
|
|
rendererAttributes,
|
|
shadowGroup,
|
|
shadowAttr,
|
|
shadows,
|
|
shadow,
|
|
shindex,
|
|
centerX,
|
|
centerY,
|
|
deltaRho,
|
|
first = 0,
|
|
slice,
|
|
slices,
|
|
sprite,
|
|
value,
|
|
item,
|
|
lenValue,
|
|
ln,
|
|
record,
|
|
i,
|
|
j,
|
|
startAngle,
|
|
endAngle,
|
|
middleAngle,
|
|
sliceLength,
|
|
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()) {
|
|
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 = [];
|
|
|
|
store.each(function(record, i) {
|
|
if (this.__excludes && this.__excludes[i]) {
|
|
|
|
return;
|
|
}
|
|
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);
|
|
}
|
|
}, this);
|
|
|
|
totalField = totalField || 1;
|
|
store.each(function(record, 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 = 360 * value / totalField / 2;
|
|
for (j = 0; j < i; j++) {
|
|
slices[j].startAngle = slices[j].endAngle = me.firstAngle;
|
|
}
|
|
}
|
|
|
|
endAngle = angle - 360 * value / totalField;
|
|
slice = {
|
|
series: me,
|
|
value: value,
|
|
startAngle: angle,
|
|
endAngle: endAngle,
|
|
storeItem: record
|
|
};
|
|
if (lenField[0]) {
|
|
lenValue = layerTotals[i];
|
|
slice.rho = me.radius * (lenValue / maxLenField);
|
|
} else {
|
|
slice.rho = me.radius;
|
|
}
|
|
slices[i] = slice;
|
|
angle = endAngle;
|
|
}, me);
|
|
|
|
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 % 360) == (slice.endAngle % 360)
|
|
};
|
|
|
|
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));
|
|
}
|
|
if (animate) {
|
|
shadowAttr = me.renderer(shadow, store.getAt(i), Ext.apply({}, rendererAttributes, shadowAttr), i, store);
|
|
me.onAnimate(shadow, {
|
|
to: shadowAttr
|
|
});
|
|
} else {
|
|
shadowAttr = me.renderer(shadow, store.getAt(i), shadowAttr, i, store);
|
|
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 % 360) == (slice.endAngle % 360))
|
|
}, 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();
|
|
},
|
|
|
|
|
|
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 = [].concat(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 = theta * 180 / Math.PI,
|
|
prevDg;
|
|
if (this.__excludes && this.__excludes[i]) {
|
|
opt.hidden = true;
|
|
}
|
|
function fixAngle(a) {
|
|
if (a < 0) {
|
|
a += 360;
|
|
}
|
|
return a % 360;
|
|
}
|
|
|
|
label.setAttributes({
|
|
text: format(storeItem.get(field[index]))
|
|
}, true);
|
|
|
|
switch (display) {
|
|
case 'outside':
|
|
rho = Math.sqrt(x * x + y * y) * 2;
|
|
|
|
opt.x = rho * Math.cos(theta) + centerX;
|
|
opt.y = rho * Math.sin(theta) + centerY;
|
|
break;
|
|
|
|
case 'rotate':
|
|
dg = fixAngle(dg);
|
|
dg = (dg > 90 && dg < 270) ? dg + 180: dg;
|
|
|
|
prevDg = label.attr.rotation.degrees;
|
|
if (prevDg != null && Math.abs(prevDg - dg) > 180) {
|
|
if (dg > prevDg) {
|
|
dg -= 360;
|
|
} else {
|
|
dg += 360;
|
|
}
|
|
dg = dg % 360;
|
|
} else {
|
|
dg = fixAngle(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;
|
|
},
|
|
|
|
|
|
onPlaceCallout: function(callout, storeItem, item, i, display, animate, index) {
|
|
var me = this,
|
|
chart = me.chart,
|
|
resizing = chart.resizing,
|
|
config = me.callouts,
|
|
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.label.getBBox(),
|
|
offsetFromViz = 20,
|
|
offsetToSide = 10,
|
|
offsetBox = 10,
|
|
p;
|
|
|
|
|
|
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 -= 360;
|
|
}
|
|
return (angle <= startAngle && angle > endAngle
|
|
&& rho >= item.startRho && rho <= item.endRho);
|
|
},
|
|
|
|
|
|
hideAll: function() {
|
|
var i, l, shadow, shadows, sh, lsh, sprite;
|
|
if (!isNaN(this._index)) {
|
|
this.__excludes = this.__excludes || [];
|
|
this.__excludes[this._index] = true;
|
|
sprite = this.slices[this._index].sprite;
|
|
for (sh = 0, lsh = sprite.length; sh < lsh; sh++) {
|
|
sprite[sh].setAttributes({
|
|
hidden: true
|
|
}, true);
|
|
}
|
|
if (this.slices[this._index].shadowAttrs) {
|
|
for (i = 0, shadows = this.slices[this._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() {
|
|
if (!isNaN(this._index)) {
|
|
this.__excludes[this._index] = false;
|
|
this.drawSeries();
|
|
}
|
|
},
|
|
|
|
|
|
highlightItem: function(item) {
|
|
var me = this,
|
|
rad = me.rad;
|
|
item = item || this.items[this._index];
|
|
|
|
|
|
|
|
|
|
|
|
this.unHighlightItem();
|
|
|
|
if (!item || item.sprite && item.sprite._animating) {
|
|
return;
|
|
}
|
|
me.callParent([item]);
|
|
if (!me.highlight) {
|
|
return;
|
|
}
|
|
if ('segment' in me.highlightCfg) {
|
|
var highlightSegment = me.highlightCfg.segment,
|
|
animate = me.chart.animate,
|
|
attrs, i, shadows, shadow, ln, to, itemHighlightSegment, prop;
|
|
|
|
if (me.labelsGroup) {
|
|
var 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;
|
|
}
|
|
|
|
if (animate) {
|
|
label.stopAnimation();
|
|
label.animate({
|
|
to: {
|
|
translate: {
|
|
x: x,
|
|
y: y
|
|
}
|
|
},
|
|
duration: me.highlightDuration
|
|
});
|
|
}
|
|
else {
|
|
label.setAttributes({
|
|
translate: {
|
|
x: x,
|
|
y: y
|
|
}
|
|
}, true);
|
|
}
|
|
}
|
|
|
|
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)
|
|
};
|
|
if (animate) {
|
|
shadow.stopAnimation();
|
|
shadow.animate({
|
|
to: attrs,
|
|
duration: me.highlightDuration
|
|
});
|
|
}
|
|
else {
|
|
shadow.setAttributes(attrs, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
unHighlightItem: function() {
|
|
var me = this;
|
|
if (!me.highlight) {
|
|
return;
|
|
}
|
|
|
|
if (('segment' in me.highlightCfg) && me.items) {
|
|
var 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,
|
|
shadowLen, p, to, ihs, hs, sprite, shadows, shadow, item, label, attrs;
|
|
|
|
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
|
|
}
|
|
}: {});
|
|
if (animate) {
|
|
label.stopAnimation();
|
|
label.animate({
|
|
to: attrs,
|
|
duration: me.highlightDuration
|
|
});
|
|
}
|
|
else {
|
|
label.setAttributes(attrs, true);
|
|
}
|
|
}
|
|
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];
|
|
if (animate) {
|
|
shadow.stopAnimation();
|
|
shadow.animate({
|
|
to: {
|
|
segment: to
|
|
},
|
|
duration: me.highlightDuration
|
|
});
|
|
}
|
|
else {
|
|
shadow.setAttributes({ segment: to }, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
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',
|
|
|
|
requires: ['Ext.chart.Shape', 'Ext.fx.Anim'],
|
|
|
|
|
|
|
|
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, i, l;
|
|
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(),
|
|
group = me.group,
|
|
sprite,
|
|
chart = me.chart,
|
|
animate = chart.animate,
|
|
field = me.field || me.yField,
|
|
surface = chart.surface,
|
|
chartBBox = chart.chartBBox,
|
|
rendererAttributes,
|
|
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,
|
|
seriesLabelStyle = me.seriesLabelStyle,
|
|
first = chart.resizing || !me.radar,
|
|
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()) {
|
|
return;
|
|
}
|
|
|
|
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) {
|
|
|
|
chart.series.each(function(series) {
|
|
fields.push(series.yField);
|
|
});
|
|
|
|
store.each(function(record, i) {
|
|
for (i = 0, nfields = fields.length; i < nfields; i++) {
|
|
maxValue = max(+record.get(fields[i]), maxValue);
|
|
}
|
|
});
|
|
}
|
|
|
|
maxValue = maxValue || 1;
|
|
|
|
startPath = []; path = [];
|
|
store.each(function(record, 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],
|
|
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,
|
|
markerStyle = Ext.apply({}, me.markerStyle || {}),
|
|
endMarkerStyle = Ext.apply(markerStyle, me.markerConfig),
|
|
items = me.items,
|
|
type = endMarkerStyle.type,
|
|
markerGroup = me.markerGroup,
|
|
centerX = me.centerX,
|
|
centerY = me.centerY,
|
|
item, i, l, marker;
|
|
|
|
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();
|
|
}
|
|
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]
|
|
}
|
|
};
|
|
|
|
if (chart.animate) {
|
|
me.onAnimate(marker, {
|
|
to: marker._to
|
|
});
|
|
}
|
|
else {
|
|
marker.setAttributes(Ext.apply(marker._to, endMarkerStyle || {}), 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,
|
|
point = item.point,
|
|
endLabelStyle = Ext.apply(me.seriesLabelStyle || {}, config);
|
|
|
|
return me.chart.surface.add(Ext.apply({
|
|
'type': 'text',
|
|
'text-anchor': 'middle',
|
|
'group': group,
|
|
'x': centerX,
|
|
'y': centerY
|
|
}, config || {}));
|
|
},
|
|
|
|
|
|
onPlaceLabel: function(label, storeItem, item, i, display, animate) {
|
|
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: item.point[0],
|
|
y: item.point[1]
|
|
},
|
|
x = opt.x - centerX,
|
|
y = opt.y - centerY;
|
|
|
|
label.setAttributes({
|
|
text: format(storeItem.get(field)),
|
|
hidden: true
|
|
},
|
|
true);
|
|
|
|
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);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.chart.series.Scatter', {
|
|
|
|
|
|
|
|
extend: 'Ext.chart.series.Cartesian',
|
|
|
|
requires: ['Ext.chart.axis.Axis', 'Ext.chart.Shape', 'Ext.fx.Anim'],
|
|
|
|
|
|
|
|
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(),
|
|
axes = [].concat(me.axis),
|
|
bbox, xScale, yScale, ln, minX, minY, maxX, maxY, i, axis, ends;
|
|
|
|
me.setBBox();
|
|
bbox = me.bbox;
|
|
|
|
for (i = 0, ln = axes.length; i < ln; i++) {
|
|
axis = chart.axes.get(axes[i]);
|
|
if (axis) {
|
|
ends = axis.calcEnds();
|
|
if (axis.position == 'top' || axis.position == 'bottom') {
|
|
minX = ends.from;
|
|
maxX = ends.to;
|
|
}
|
|
else {
|
|
minY = ends.from;
|
|
maxY = ends.to;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (me.xField && !Ext.isNumber(minX)) {
|
|
axis = Ext.create('Ext.chart.axis.Axis', {
|
|
chart: chart,
|
|
fields: [].concat(me.xField)
|
|
}).calcEnds();
|
|
minX = axis.from;
|
|
maxX = axis.to;
|
|
}
|
|
if (me.yField && !Ext.isNumber(minY)) {
|
|
axis = Ext.create('Ext.chart.axis.Axis', {
|
|
chart: chart,
|
|
fields: [].concat(me.yField)
|
|
}).calcEnds();
|
|
minY = axis.from;
|
|
maxY = axis.to;
|
|
}
|
|
|
|
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(),
|
|
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 = [],
|
|
x, y, xValue, yValue, sprite;
|
|
|
|
store.each(function(record, i) {
|
|
xValue = record.get(me.xField);
|
|
yValue = record.get(me.yField);
|
|
|
|
if (typeof yValue == 'undefined' || (typeof yValue == 'string' && !yValue)) {
|
|
return;
|
|
}
|
|
|
|
if (typeof xValue == 'string' || typeof xValue == 'object' && !Ext.isDate(xValue)) {
|
|
xValue = i;
|
|
}
|
|
if (typeof yValue == 'string' || typeof yValue == 'object' && !Ext.isDate(yValue)) {
|
|
yValue = i;
|
|
}
|
|
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;
|
|
delete endMarkerStyle.type;
|
|
|
|
|
|
if (!store || !store.getCount()) {
|
|
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',
|
|
group: group,
|
|
x: item.point[0],
|
|
y: bbox.y + bbox.height / 2
|
|
}, endLabelStyle));
|
|
},
|
|
|
|
|
|
onPlaceLabel: function(label, storeItem, item, i, display, animate) {
|
|
var me = this,
|
|
chart = me.chart,
|
|
resizing = chart.resizing,
|
|
config = me.label,
|
|
format = config.renderer,
|
|
field = config.field,
|
|
bbox = me.bbox,
|
|
x = item.point[0],
|
|
y = item.point[1],
|
|
radius = item.sprite.attr.radius,
|
|
bb, width, height, anim;
|
|
|
|
label.setAttributes({
|
|
text: format(storeItem.get(field)),
|
|
hidden: true
|
|
}, true);
|
|
|
|
if (display == 'rotate') {
|
|
label.setAttributes({
|
|
'text-anchor': 'start',
|
|
'rotation': {
|
|
x: x,
|
|
y: y,
|
|
degrees: -45
|
|
}
|
|
}, true);
|
|
|
|
bb = label.getBBox();
|
|
width = bb.width;
|
|
height = bb.height;
|
|
x = x < bbox.x? bbox.x : x;
|
|
x = (x + width > bbox.x + bbox.width)? (x - (x + width - bbox.x - bbox.width)) : x;
|
|
y = (y - height < bbox.y)? bbox.y + height : y;
|
|
|
|
} else if (display == 'under' || display == 'over') {
|
|
|
|
bb = item.sprite.getBBox();
|
|
bb.width = bb.width || (radius * 2);
|
|
bb.height = bb.height || (radius * 2);
|
|
y = y + (display == 'over'? -bb.height : bb.height);
|
|
|
|
bb = label.getBBox();
|
|
width = bb.width/2;
|
|
height = bb.height/2;
|
|
x = x - width < bbox.x ? bbox.x + width : x;
|
|
x = (x + width > bbox.x + bbox.width) ? (x - (x + width - bbox.x - bbox.width)) : x;
|
|
y = y - height < bbox.y? bbox.y + height : y;
|
|
y = (y + height > bbox.y + bbox.height) ? (y - (y + height - bbox.y - bbox.height)) : y;
|
|
}
|
|
|
|
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.chart.theme.Base', {
|
|
|
|
|
|
|
|
requires: ['Ext.chart.theme.Theme'],
|
|
|
|
|
|
|
|
constructor: function(config) {
|
|
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: function(v) { return v; }
|
|
},
|
|
axisLabelRight: {
|
|
fill: '#444',
|
|
font: '12px Arial, Helvetica, sans-serif',
|
|
spacing: 2,
|
|
padding: 5,
|
|
renderer: function(v) { return v; }
|
|
},
|
|
axisLabelBottom: {
|
|
fill: '#444',
|
|
font: '12px Arial, Helvetica, sans-serif',
|
|
spacing: 2,
|
|
padding: 5,
|
|
renderer: function(v) { return v; }
|
|
},
|
|
axisLabelLeft: {
|
|
fill: '#444',
|
|
font: '12px Arial, Helvetica, sans-serif',
|
|
spacing: 2,
|
|
padding: 5,
|
|
renderer: function(v) { return v; }
|
|
},
|
|
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',
|
|
fill: '#000',
|
|
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: "#a66111"
|
|
}],
|
|
markerThemes: [{
|
|
fill: "#115fa6",
|
|
type: 'circle'
|
|
}, {
|
|
fill: "#94ae0a",
|
|
type: 'cross'
|
|
}, {
|
|
fill: "#a61120",
|
|
type: 'plus'
|
|
}]
|
|
});
|
|
}
|
|
}, 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.data.ArrayStore', {
|
|
extend: 'Ext.data.Store',
|
|
alias: 'store.array',
|
|
uses: ['Ext.data.reader.Array'],
|
|
|
|
constructor: function(config) {
|
|
config = config || {};
|
|
|
|
Ext.applyIf(config, {
|
|
proxy: {
|
|
type: 'memory',
|
|
reader: 'array'
|
|
}
|
|
});
|
|
|
|
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,
|
|
|
|
|
|
current: -1,
|
|
|
|
|
|
total: 0,
|
|
|
|
|
|
isRunning: false,
|
|
|
|
|
|
isComplete: false,
|
|
|
|
|
|
hasException: false,
|
|
|
|
|
|
pauseOnException: true,
|
|
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
me.addEvents(
|
|
|
|
'complete',
|
|
|
|
|
|
'exception',
|
|
|
|
|
|
'operationcomplete'
|
|
);
|
|
|
|
me.mixins.observable.constructor.call(me, config);
|
|
|
|
|
|
me.operations = [];
|
|
},
|
|
|
|
|
|
add: function(operation) {
|
|
this.total++;
|
|
|
|
operation.setBatch(this);
|
|
|
|
this.operations.push(operation);
|
|
},
|
|
|
|
|
|
start: function() {
|
|
this.hasException = false;
|
|
this.isRunning = true;
|
|
|
|
this.runNextOperation();
|
|
},
|
|
|
|
|
|
runNextOperation: function() {
|
|
this.runOperation(this.current + 1);
|
|
},
|
|
|
|
|
|
pause: function() {
|
|
this.isRunning = false;
|
|
},
|
|
|
|
|
|
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.fireEvent('exception', me, operation);
|
|
} else {
|
|
me.fireEvent('operationcomplete', me, operation);
|
|
}
|
|
|
|
if (hasException && me.pauseOnException) {
|
|
me.pause();
|
|
} else {
|
|
operation.setCompleted();
|
|
me.runNextOperation();
|
|
}
|
|
};
|
|
|
|
operation.setStarted();
|
|
|
|
me.proxy[operation.action](operation, onProxyReturn, me);
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.data.BelongsToAssociation', {
|
|
extend: 'Ext.data.Association',
|
|
|
|
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,
|
|
ownerModel = me.ownerModel,
|
|
associatedModel = me.associatedModel,
|
|
foreignKey = me.foreignKey,
|
|
primaryKey = me.primaryKey;
|
|
|
|
|
|
return function(value, options, scope) {
|
|
this.set(foreignKey, value);
|
|
|
|
if (typeof options == 'function') {
|
|
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),
|
|
instance,
|
|
args;
|
|
|
|
if (model[instanceName] === undefined) {
|
|
instance = Ext.ModelManager.create({}, associatedName);
|
|
instance.set(primaryKey, foreignKeyId);
|
|
|
|
if (typeof options == 'function') {
|
|
options = {
|
|
callback: options,
|
|
scope: scope || model
|
|
};
|
|
}
|
|
|
|
associatedModel.load(foreignKeyId, options);
|
|
model[instanceName] = associatedModel;
|
|
return associatedModel;
|
|
} else {
|
|
instance = model[instanceName];
|
|
args = [instance];
|
|
scope = 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.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'
|
|
},
|
|
|
|
requires: ['Ext.util.MixedCollection'],
|
|
|
|
statics: {
|
|
exceptions: {
|
|
TRANSPORT: 'xhr',
|
|
PARSE: 'parse',
|
|
LOGIN: 'login',
|
|
SERVER: 'exception'
|
|
}
|
|
},
|
|
|
|
|
|
|
|
constructor: function(){
|
|
var me = this;
|
|
|
|
me.addEvents(
|
|
|
|
'event',
|
|
|
|
'exception'
|
|
);
|
|
me.transactions = Ext.create('Ext.util.MixedCollection');
|
|
me.providers = Ext.create('Ext.util.MixedCollection');
|
|
|
|
me.mixins.observable.constructor.call(me);
|
|
},
|
|
|
|
|
|
addProvider : function(provider){
|
|
var me = this,
|
|
args = arguments,
|
|
i = 0,
|
|
len;
|
|
|
|
if (args.length > 1) {
|
|
for (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.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;
|
|
|
|
provider = provider.isProvider ? provider : providers.get(provider);
|
|
|
|
if (provider) {
|
|
provider.un('data', me.onProviderData, me);
|
|
providers.remove(provider);
|
|
return provider;
|
|
}
|
|
return null;
|
|
},
|
|
|
|
|
|
addTransaction: function(transaction){
|
|
this.transactions.add(transaction);
|
|
return transaction;
|
|
},
|
|
|
|
|
|
removeTransaction: function(transaction){
|
|
transaction = this.getTransaction(transaction);
|
|
this.transactions.remove(transaction);
|
|
return transaction;
|
|
},
|
|
|
|
|
|
getTransaction: function(transaction){
|
|
return transaction.isTransaction ? transaction : this.transactions.get(transaction);
|
|
},
|
|
|
|
onProviderData : function(provider, event){
|
|
var me = this,
|
|
i = 0,
|
|
len;
|
|
|
|
if (Ext.isArray(event)) {
|
|
for (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);
|
|
}
|
|
}, function(){
|
|
|
|
Ext.Direct = Ext.direct.Manager;
|
|
});
|
|
|
|
|
|
Ext.define('Ext.data.proxy.Direct', {
|
|
|
|
|
|
extend: 'Ext.data.proxy.Server',
|
|
alternateClassName: 'Ext.data.DirectProxy',
|
|
|
|
alias: 'proxy.direct',
|
|
|
|
requires: ['Ext.direct.Manager'],
|
|
|
|
|
|
|
|
|
|
paramOrder: undefined,
|
|
|
|
|
|
paramsAsHash: true,
|
|
|
|
|
|
directFn : undefined,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
paramOrderRe: /[\s,|]/,
|
|
|
|
constructor: function(config){
|
|
var me = this;
|
|
|
|
Ext.apply(me, config);
|
|
if (Ext.isString(me.paramOrder)) {
|
|
me.paramOrder = me.paramOrder.split(me.paramOrderRe);
|
|
}
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
doRequest: function(operation, callback, scope) {
|
|
var me = this,
|
|
writer = me.getWriter(),
|
|
request = me.buildRequest(operation, callback, scope),
|
|
fn = me.api[request.action] || me.directFn,
|
|
args = [],
|
|
params = request.params,
|
|
paramOrder = me.paramOrder,
|
|
method,
|
|
i = 0,
|
|
len;
|
|
|
|
|
|
if (operation.allowWrite()) {
|
|
request = writer.write(request);
|
|
}
|
|
|
|
if (operation.action == 'read') {
|
|
|
|
method = fn.directCfg.method;
|
|
|
|
if (method.ordered) {
|
|
if (method.len > 0) {
|
|
if (paramOrder) {
|
|
for (len = paramOrder.length; i < len; ++i) {
|
|
args.push(params[paramOrder[i]]);
|
|
}
|
|
} else if (me.paramsAsHash) {
|
|
args.push(params);
|
|
}
|
|
}
|
|
} else {
|
|
args.push(params);
|
|
}
|
|
} 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: function(value){
|
|
return value;
|
|
},
|
|
|
|
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',
|
|
|
|
requires: ['Ext.data.proxy.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.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.HasManyAssociation', {
|
|
extend: 'Ext.data.Association',
|
|
requires: ['Ext.util.Inflector'],
|
|
|
|
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 = {};
|
|
|
|
if (me[storeName] === undefined) {
|
|
if (filterProperty) {
|
|
filter = {
|
|
property : filterProperty,
|
|
value : me.get(filterProperty),
|
|
exactMatch: true
|
|
};
|
|
} else {
|
|
filter = {
|
|
property : foreignKey,
|
|
value : me.get(primaryKey),
|
|
exactMatch: true
|
|
};
|
|
}
|
|
|
|
modelDefaults[foreignKey] = me.get(primaryKey);
|
|
|
|
config = Ext.apply({}, storeConfig, {
|
|
model : associatedModel,
|
|
filters : [filter],
|
|
remoteFilter : false,
|
|
modelDefaults: modelDefaults
|
|
});
|
|
|
|
me[storeName] = Ext.create('Ext.data.Store', config);
|
|
if (autoLoad) {
|
|
me[storeName].load();
|
|
}
|
|
}
|
|
|
|
return me[storeName];
|
|
};
|
|
},
|
|
|
|
|
|
read: function(record, reader, associationData){
|
|
var store = record[this.name](),
|
|
inverse;
|
|
|
|
store.add(reader.read(associationData).records);
|
|
|
|
|
|
|
|
inverse = this.associatedModel.prototype.associations.findBy(function(assoc){
|
|
return assoc.type === 'belongsTo' && assoc.associatedName === record.$className;
|
|
});
|
|
|
|
|
|
if (inverse) {
|
|
store.data.each(function(associatedRecord){
|
|
associatedRecord[inverse.instanceName] = record;
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.data.JsonP', {
|
|
|
|
|
|
|
|
singleton: true,
|
|
|
|
statics: {
|
|
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.statics().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.isSandboxed ? Ext.getUniqueGlobalNamespace() : 'Ext',
|
|
request,
|
|
script;
|
|
|
|
params[callbackKey] = name + '.data.JsonP.' + callbackName;
|
|
if (disableCaching) {
|
|
params[cacheParam] = new Date().getTime();
|
|
}
|
|
|
|
script = me.createScript(url, params);
|
|
|
|
me.statics().requests[id] = request = {
|
|
url: url,
|
|
params: params,
|
|
script: script,
|
|
id: id,
|
|
scope: options.scope,
|
|
success: options.success,
|
|
failure: options.failure,
|
|
callback: options.callback,
|
|
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);
|
|
Ext.getHead().appendChild(script);
|
|
return request;
|
|
},
|
|
|
|
|
|
abort: function(request){
|
|
var requests = this.statics().requests,
|
|
key;
|
|
|
|
if (request) {
|
|
if (!request.id) {
|
|
request = requests[request];
|
|
}
|
|
this.abort(request);
|
|
} else {
|
|
for (key in requests) {
|
|
if (requests.hasOwnProperty(key)) {
|
|
this.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.statics()[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]);
|
|
},
|
|
|
|
|
|
createScript: function(url, params) {
|
|
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;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.data.JsonPStore', {
|
|
extend: 'Ext.data.Store',
|
|
alias : 'store.jsonp',
|
|
|
|
|
|
constructor: function(config) {
|
|
this.callParent(Ext.apply(config, {
|
|
reader: Ext.create('Ext.data.reader.Json', config),
|
|
proxy : Ext.create('Ext.data.proxy.JsonP', config)
|
|
}));
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.data.NodeInterface', {
|
|
requires: ['Ext.data.Field'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
statics: {
|
|
|
|
decorate: function(record) {
|
|
if (!record.isNode) {
|
|
|
|
|
|
var mgr = Ext.ModelManager,
|
|
modelName = record.modelName,
|
|
modelClass = mgr.getModel(modelName),
|
|
idName = modelClass.prototype.idProperty,
|
|
newFields = [],
|
|
i, newField, len;
|
|
|
|
|
|
modelClass.override(this.getPrototypeBody());
|
|
newFields = this.applyFields(modelClass, [
|
|
{name: idName, type: 'string', defaultValue: null},
|
|
{name: 'parentId', type: 'string', defaultValue: null},
|
|
{name: 'index', type: 'int', defaultValue: null},
|
|
{name: 'depth', type: 'int', defaultValue: 0},
|
|
{name: 'expanded', type: 'bool', defaultValue: false, persist: false},
|
|
{name: 'expandable', type: 'bool', defaultValue: true, persist: false},
|
|
{name: 'checked', type: 'auto', defaultValue: null},
|
|
{name: 'leaf', type: 'bool', defaultValue: false, persist: false},
|
|
{name: 'cls', type: 'string', defaultValue: null, persist: false},
|
|
{name: 'iconCls', type: 'string', defaultValue: null, persist: false},
|
|
{name: 'icon', type: 'string', defaultValue: null, persist: false},
|
|
{name: 'root', type: 'boolean', defaultValue: false, persist: false},
|
|
{name: 'isLast', type: 'boolean', defaultValue: false, persist: false},
|
|
{name: 'isFirst', type: 'boolean', defaultValue: false, persist: false},
|
|
{name: 'allowDrop', type: 'boolean', defaultValue: true, persist: false},
|
|
{name: 'allowDrag', type: 'boolean', defaultValue: true, persist: false},
|
|
{name: 'loaded', type: 'boolean', defaultValue: false, persist: false},
|
|
{name: 'loading', type: 'boolean', defaultValue: false, persist: false},
|
|
{name: 'href', type: 'string', defaultValue: null, persist: false},
|
|
{name: 'hrefTarget', type: 'string', defaultValue: null, persist: false},
|
|
{name: 'qtip', type: 'string', defaultValue: null, persist: false},
|
|
{name: 'qtitle', type: 'string', defaultValue: null, persist: false}
|
|
]);
|
|
|
|
len = newFields.length;
|
|
|
|
for (i = 0; i < len; ++i) {
|
|
newField = newFields[i];
|
|
if (record.get(newField.name) === undefined) {
|
|
record.data[newField.name] = newField.defaultValue;
|
|
}
|
|
}
|
|
}
|
|
|
|
Ext.applyIf(record, {
|
|
firstChild: null,
|
|
lastChild: null,
|
|
parentNode: null,
|
|
previousSibling: null,
|
|
nextSibling: null,
|
|
childNodes: []
|
|
});
|
|
|
|
record.commit(true);
|
|
|
|
record.enableBubble([
|
|
|
|
"append",
|
|
|
|
|
|
"remove",
|
|
|
|
|
|
"move",
|
|
|
|
|
|
"insert",
|
|
|
|
|
|
"beforeappend",
|
|
|
|
|
|
"beforeremove",
|
|
|
|
|
|
"beforemove",
|
|
|
|
|
|
"beforeinsert",
|
|
|
|
|
|
"expand",
|
|
|
|
|
|
"collapse",
|
|
|
|
|
|
"beforeexpand",
|
|
|
|
|
|
"beforecollapse",
|
|
|
|
|
|
"sort"
|
|
]);
|
|
|
|
return record;
|
|
},
|
|
|
|
applyFields: function(modelClass, addFields) {
|
|
var modelPrototype = modelClass.prototype,
|
|
fields = modelPrototype.fields,
|
|
keys = fields.keys,
|
|
ln = addFields.length,
|
|
addField, i, name,
|
|
newFields = [];
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
addField = addFields[i];
|
|
if (!Ext.Array.contains(keys, addField.name)) {
|
|
addField = Ext.create('data.field', addField);
|
|
|
|
newFields.push(addField);
|
|
fields.add(addField);
|
|
}
|
|
}
|
|
|
|
return newFields;
|
|
},
|
|
|
|
getPrototypeBody: function() {
|
|
return {
|
|
isNode: true,
|
|
|
|
|
|
createNode: function(node) {
|
|
if (Ext.isObject(node) && !node.isModel) {
|
|
node = Ext.ModelManager.create(node, this.modelName);
|
|
}
|
|
|
|
return Ext.data.NodeInterface.decorate(node);
|
|
},
|
|
|
|
|
|
isLeaf : function() {
|
|
return this.get('leaf') === true;
|
|
},
|
|
|
|
|
|
setFirstChild : function(node) {
|
|
this.firstChild = node;
|
|
},
|
|
|
|
|
|
setLastChild : function(node) {
|
|
this.lastChild = node;
|
|
},
|
|
|
|
|
|
updateInfo: function(silent) {
|
|
var me = this,
|
|
isRoot = me.isRoot(),
|
|
parentNode = me.parentNode,
|
|
isFirst = (!parentNode ? true : parentNode.firstChild == me),
|
|
isLast = (!parentNode ? true : parentNode.lastChild == me),
|
|
depth = 0,
|
|
parent = me,
|
|
children = me.childNodes,
|
|
len = children.length,
|
|
i = 0;
|
|
|
|
while (parent.parentNode) {
|
|
++depth;
|
|
parent = parent.parentNode;
|
|
}
|
|
|
|
me.beginEdit();
|
|
me.set({
|
|
isFirst: isFirst,
|
|
isLast: isLast,
|
|
depth: depth,
|
|
index: parentNode ? parentNode.indexOf(me) : 0,
|
|
parentId: parentNode ? parentNode.getId() : null
|
|
});
|
|
me.endEdit(silent);
|
|
if (silent) {
|
|
me.commit();
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
children[i].updateInfo(silent);
|
|
}
|
|
},
|
|
|
|
|
|
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.hasChildNodes()));
|
|
}
|
|
return false;
|
|
},
|
|
|
|
|
|
appendChild : function(node, suppressEvents, suppressNodeUpdate) {
|
|
var me = this,
|
|
i, ln,
|
|
index,
|
|
oldParent,
|
|
ps;
|
|
|
|
|
|
if (Ext.isArray(node)) {
|
|
for (i = 0, ln = node.length; i < ln; i++) {
|
|
me.appendChild(node[i]);
|
|
}
|
|
} else {
|
|
|
|
node = me.createNode(node);
|
|
|
|
if (suppressEvents !== true && me.fireEvent("beforeappend", me, node) === false) {
|
|
return false;
|
|
}
|
|
|
|
index = me.childNodes.length;
|
|
oldParent = node.parentNode;
|
|
|
|
|
|
if (oldParent) {
|
|
if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index) === false) {
|
|
return false;
|
|
}
|
|
oldParent.removeChild(node, null, false, true);
|
|
}
|
|
|
|
index = me.childNodes.length;
|
|
if (index === 0) {
|
|
me.setFirstChild(node);
|
|
}
|
|
|
|
me.childNodes.push(node);
|
|
node.parentNode = me;
|
|
node.nextSibling = null;
|
|
|
|
me.setLastChild(node);
|
|
|
|
ps = me.childNodes[index - 1];
|
|
if (ps) {
|
|
node.previousSibling = ps;
|
|
ps.nextSibling = node;
|
|
ps.updateInfo(suppressNodeUpdate);
|
|
} else {
|
|
node.previousSibling = null;
|
|
}
|
|
|
|
node.updateInfo(suppressNodeUpdate);
|
|
|
|
|
|
if (!me.isLoaded()) {
|
|
me.set('loaded', true);
|
|
}
|
|
|
|
else if (me.childNodes.length === 1) {
|
|
me.set('loaded', me.isLoaded());
|
|
}
|
|
|
|
if (suppressEvents !== true) {
|
|
me.fireEvent("append", me, node, index);
|
|
|
|
if (oldParent) {
|
|
node.fireEvent("move", node, oldParent, me, index);
|
|
}
|
|
}
|
|
|
|
return node;
|
|
}
|
|
},
|
|
|
|
|
|
getBubbleTarget: function() {
|
|
return this.parentNode;
|
|
},
|
|
|
|
|
|
removeChild : function(node, destroy, suppressEvents, suppressNodeUpdate) {
|
|
var me = this,
|
|
index = me.indexOf(node);
|
|
|
|
if (index == -1 || (suppressEvents !== true && me.fireEvent("beforeremove", me, node) === false)) {
|
|
return false;
|
|
}
|
|
|
|
|
|
Ext.Array.erase(me.childNodes, index, 1);
|
|
|
|
|
|
if (me.firstChild == node) {
|
|
me.setFirstChild(node.nextSibling);
|
|
}
|
|
if (me.lastChild == node) {
|
|
me.setLastChild(node.previousSibling);
|
|
}
|
|
|
|
|
|
if (node.previousSibling) {
|
|
node.previousSibling.nextSibling = node.nextSibling;
|
|
node.previousSibling.updateInfo(suppressNodeUpdate);
|
|
}
|
|
if (node.nextSibling) {
|
|
node.nextSibling.previousSibling = node.previousSibling;
|
|
node.nextSibling.updateInfo(suppressNodeUpdate);
|
|
}
|
|
|
|
if (suppressEvents !== true) {
|
|
me.fireEvent("remove", me, node);
|
|
}
|
|
|
|
|
|
|
|
if (!me.childNodes.length) {
|
|
me.set('loaded', me.isLoaded());
|
|
}
|
|
|
|
if (destroy) {
|
|
node.destroy(true);
|
|
} else {
|
|
node.clear();
|
|
}
|
|
|
|
return node;
|
|
},
|
|
|
|
|
|
copy: function(newId, deep) {
|
|
var me = this,
|
|
result = me.callOverridden(arguments),
|
|
len = me.childNodes ? me.childNodes.length : 0,
|
|
i;
|
|
|
|
|
|
if (deep) {
|
|
for (i = 0; i < len; i++) {
|
|
result.appendChild(me.childNodes[i].copy(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;
|
|
|
|
if (silent === true) {
|
|
me.clear(true);
|
|
Ext.each(me.childNodes, function(n) {
|
|
n.destroy(true);
|
|
});
|
|
me.childNodes = null;
|
|
delete me.destroyOptions;
|
|
me.callOverridden([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,
|
|
ps;
|
|
|
|
if (!refNode) {
|
|
return me.appendChild(node);
|
|
}
|
|
|
|
|
|
if (node == refNode) {
|
|
return false;
|
|
}
|
|
|
|
|
|
node = me.createNode(node);
|
|
|
|
if (suppressEvents !== true && me.fireEvent("beforeinsert", me, node, refNode) === false) {
|
|
return false;
|
|
}
|
|
|
|
|
|
if (oldParent == me && me.indexOf(node) < index) {
|
|
refIndex--;
|
|
}
|
|
|
|
|
|
if (oldParent) {
|
|
if (suppressEvents !== true && node.fireEvent("beforemove", node, oldParent, me, index, refNode) === false) {
|
|
return false;
|
|
}
|
|
oldParent.removeChild(node);
|
|
}
|
|
|
|
if (refIndex === 0) {
|
|
me.setFirstChild(node);
|
|
}
|
|
|
|
Ext.Array.splice(me.childNodes, refIndex, 0, node);
|
|
node.parentNode = me;
|
|
|
|
node.nextSibling = refNode;
|
|
refNode.previousSibling = node;
|
|
|
|
ps = me.childNodes[refIndex - 1];
|
|
if (ps) {
|
|
node.previousSibling = ps;
|
|
ps.nextSibling = node;
|
|
ps.updateInfo();
|
|
} else {
|
|
node.previousSibling = null;
|
|
}
|
|
|
|
node.updateInfo();
|
|
|
|
if (!me.isLoaded()) {
|
|
me.set('loaded', true);
|
|
}
|
|
|
|
else if (me.childNodes.length === 1) {
|
|
me.set('loaded', me.isLoaded());
|
|
}
|
|
|
|
if (suppressEvents !== true) {
|
|
me.fireEvent("insert", me, node, refNode);
|
|
|
|
if (oldParent) {
|
|
node.fireEvent("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 parentNode = this.parentNode;
|
|
|
|
if (parentNode) {
|
|
parentNode.removeChild(this, destroy, suppressEvents, true);
|
|
}
|
|
return this;
|
|
},
|
|
|
|
|
|
removeAll : function(destroy, suppressEvents) {
|
|
var cn = this.childNodes,
|
|
n;
|
|
|
|
while ((n = cn[0])) {
|
|
this.removeChild(n, destroy, suppressEvents);
|
|
}
|
|
return this;
|
|
},
|
|
|
|
|
|
getChildAt : function(index) {
|
|
return this.childNodes[index];
|
|
},
|
|
|
|
|
|
replaceChild : function(newChild, oldChild, suppressEvents) {
|
|
var s = oldChild ? oldChild.nextSibling : null;
|
|
|
|
this.removeChild(oldChild, suppressEvents);
|
|
this.insertBefore(newChild, s, suppressEvents);
|
|
return oldChild;
|
|
},
|
|
|
|
|
|
indexOf : function(child) {
|
|
return Ext.Array.indexOf(this.childNodes, child);
|
|
},
|
|
|
|
|
|
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;
|
|
|
|
if (ln > 0) {
|
|
Ext.Array.sort(cs, sortFn);
|
|
for (i = 0; i < ln; i++) {
|
|
n = cs[i];
|
|
n.previousSibling = cs[i-1];
|
|
n.nextSibling = cs[i+1];
|
|
|
|
if (i === 0) {
|
|
this.setFirstChild(n);
|
|
n.updateInfo();
|
|
}
|
|
if (i == ln - 1) {
|
|
this.setLastChild(n);
|
|
n.updateInfo();
|
|
}
|
|
if (recursive && !n.isLeaf()) {
|
|
n.sort(sortFn, true, true);
|
|
}
|
|
}
|
|
|
|
if (suppressEvent !== true) {
|
|
this.fireEvent('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;
|
|
|
|
|
|
|
|
|
|
|
|
if (!me.isLeaf()) {
|
|
|
|
if (me.isLoading()) {
|
|
me.on('expand', function(){
|
|
me.expand(recursive, callback, scope);
|
|
}, me, {single: true});
|
|
} else {
|
|
|
|
if (!me.isExpanded()) {
|
|
|
|
|
|
|
|
|
|
me.fireEvent('beforeexpand', me, function(){
|
|
me.set('expanded', true);
|
|
me.fireEvent('expand', me, me.childNodes, false);
|
|
|
|
|
|
if (recursive) {
|
|
me.expandChildren(true, callback, scope);
|
|
} else {
|
|
Ext.callback(callback, scope || me, [me.childNodes]);
|
|
}
|
|
}, me);
|
|
} else if (recursive) {
|
|
|
|
me.expandChildren(true, callback, scope);
|
|
} else {
|
|
Ext.callback(callback, scope || me, [me.childNodes]);
|
|
}
|
|
}
|
|
} else {
|
|
|
|
Ext.callback(callback, scope || me);
|
|
}
|
|
},
|
|
|
|
|
|
expandChildren: function(recursive, callback, scope) {
|
|
var me = this,
|
|
i = 0,
|
|
nodes = me.childNodes,
|
|
ln = nodes.length,
|
|
node,
|
|
expanding = 0;
|
|
|
|
for (; i < ln; ++i) {
|
|
node = nodes[i];
|
|
if (!node.isLeaf() && !node.isExpanded()) {
|
|
expanding++;
|
|
nodes[i].expand(recursive, function () {
|
|
expanding--;
|
|
if (callback && !expanding) {
|
|
Ext.callback(callback, scope || me, [me.childNodes]);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
if (!expanding && callback) {
|
|
Ext.callback(callback, scope || me, [me.childNodes]); }
|
|
},
|
|
|
|
|
|
collapse: function(recursive, callback, scope) {
|
|
var me = this;
|
|
|
|
|
|
if (!me.isLeaf()) {
|
|
|
|
if (!me.collapsing && me.isExpanded()) {
|
|
me.fireEvent('beforecollapse', me, function() {
|
|
me.set('expanded', false);
|
|
me.fireEvent('collapse', me, me.childNodes, false);
|
|
|
|
|
|
if (recursive) {
|
|
me.collapseChildren(true, callback, scope);
|
|
}
|
|
else {
|
|
Ext.callback(callback, scope || me, [me.childNodes]);
|
|
}
|
|
}, me);
|
|
}
|
|
|
|
else if (recursive) {
|
|
me.collapseChildren(true, callback, scope);
|
|
}
|
|
}
|
|
|
|
else {
|
|
Ext.callback(callback, scope || me, [me.childNodes]);
|
|
}
|
|
},
|
|
|
|
|
|
collapseChildren: function(recursive, callback, scope) {
|
|
var me = this,
|
|
i = 0,
|
|
nodes = me.childNodes,
|
|
ln = nodes.length,
|
|
node,
|
|
collapsing = 0;
|
|
|
|
for (; i < ln; ++i) {
|
|
node = nodes[i];
|
|
if (!node.isLeaf() && node.isExpanded()) {
|
|
collapsing++;
|
|
nodes[i].collapse(recursive, function () {
|
|
collapsing--;
|
|
if (callback && !collapsing) {
|
|
Ext.callback(callback, scope || me, [me.childNodes]);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
if (!collapsing && callback) {
|
|
Ext.callback(callback, scope || me, [me.childNodes]);
|
|
}
|
|
}
|
|
};
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.data.NodeStore', {
|
|
extend: 'Ext.data.Store',
|
|
alias: 'store.node',
|
|
requires: ['Ext.data.NodeInterface'],
|
|
|
|
|
|
node: null,
|
|
|
|
|
|
recursive: false,
|
|
|
|
|
|
rootVisible: false,
|
|
|
|
constructor: function(config) {
|
|
var me = this,
|
|
node;
|
|
|
|
config = config || {};
|
|
Ext.apply(me, config);
|
|
|
|
|
|
config.proxy = {type: 'proxy'};
|
|
me.callParent([config]);
|
|
|
|
me.addEvents('expand', 'collapse', 'beforeexpand', 'beforecollapse');
|
|
|
|
node = me.node;
|
|
if (node) {
|
|
me.node = null;
|
|
me.setNode(node);
|
|
}
|
|
},
|
|
|
|
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,
|
|
remove: me.onNodeRemove,
|
|
sort: me.onNodeSort,
|
|
scope: me
|
|
});
|
|
me.node = null;
|
|
}
|
|
|
|
if (node) {
|
|
Ext.data.NodeInterface.decorate(node);
|
|
me.removeAll();
|
|
if (me.rootVisible) {
|
|
me.add(node);
|
|
}
|
|
me.mon(node, {
|
|
expand: me.onNodeExpand,
|
|
collapse: me.onNodeCollapse,
|
|
append: me.onNodeAppend,
|
|
insert: me.onNodeInsert,
|
|
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())) {
|
|
me.onNodeCollapse(node, childNodes, true);
|
|
me.onNodeExpand(node, childNodes, true);
|
|
}
|
|
},
|
|
|
|
onNodeExpand: function(parent, records, suppressEvent) {
|
|
var me = this,
|
|
insertIndex = me.indexOf(parent) + 1,
|
|
ln = records ? records.length : 0,
|
|
i, record;
|
|
|
|
if (!me.recursive && parent !== me.node) {
|
|
return;
|
|
}
|
|
|
|
if (!me.isVisible(parent)) {
|
|
return;
|
|
}
|
|
|
|
if (!suppressEvent && me.fireEvent('beforeexpand', parent, records, insertIndex) === false) {
|
|
return;
|
|
}
|
|
|
|
if (ln) {
|
|
me.insert(insertIndex, records);
|
|
for (i = 0; i < ln; i++) {
|
|
record = records[i];
|
|
if (record.isExpanded()) {
|
|
if (record.isLoaded()) {
|
|
|
|
me.onNodeExpand(record, record.childNodes, true);
|
|
}
|
|
else {
|
|
record.set('expanded', false);
|
|
record.expand();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!suppressEvent) {
|
|
me.fireEvent('expand', parent, records);
|
|
}
|
|
},
|
|
|
|
onNodeCollapse: function(parent, records, suppressEvent) {
|
|
var me = this,
|
|
ln = records.length,
|
|
collapseIndex = me.indexOf(parent) + 1,
|
|
i, record;
|
|
|
|
if (!me.recursive && parent !== me.node) {
|
|
return;
|
|
}
|
|
|
|
if (!suppressEvent && me.fireEvent('beforecollapse', parent, records, collapseIndex) === false) {
|
|
return;
|
|
}
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
record = records[i];
|
|
me.remove(record);
|
|
if (record.isExpanded()) {
|
|
me.onNodeCollapse(record, record.childNodes, true);
|
|
}
|
|
}
|
|
|
|
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 {
|
|
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, index) {
|
|
var me = this;
|
|
if (me.indexOf(node) != -1) {
|
|
if (!node.isLeaf() && node.isExpanded()) {
|
|
me.onNodeCollapse(node, node.childNodes, true);
|
|
}
|
|
me.remove(node);
|
|
}
|
|
},
|
|
|
|
isVisible: function(node) {
|
|
var parent = node.parentNode;
|
|
while (parent) {
|
|
if (parent === this.node && !this.rootVisible && parent.isExpanded()) {
|
|
return true;
|
|
}
|
|
|
|
if (this.indexOf(parent) === -1 || !parent.isExpanded()) {
|
|
return false;
|
|
}
|
|
|
|
parent = parent.parentNode;
|
|
}
|
|
return true;
|
|
}
|
|
});
|
|
|
|
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);
|
|
}
|
|
},
|
|
|
|
|
|
getRootNode : function() {
|
|
return this.root;
|
|
},
|
|
|
|
|
|
setRootNode : function(node) {
|
|
var me = this;
|
|
|
|
me.root = node;
|
|
Ext.data.NodeInterface.decorate(node);
|
|
|
|
if (me.fireEvent('beforeappend', null, node) !== false) {
|
|
node.set('root', true);
|
|
node.updateInfo();
|
|
|
|
me.relayEvents(node, [
|
|
|
|
"append",
|
|
|
|
|
|
"remove",
|
|
|
|
|
|
"move",
|
|
|
|
|
|
"insert",
|
|
|
|
|
|
"beforeappend",
|
|
|
|
|
|
"beforeremove",
|
|
|
|
|
|
"beforemove",
|
|
|
|
|
|
"beforeinsert",
|
|
|
|
|
|
"expand",
|
|
|
|
|
|
"collapse",
|
|
|
|
|
|
"beforeexpand",
|
|
|
|
|
|
"beforecollapse" ,
|
|
|
|
|
|
"rootchange"
|
|
]);
|
|
|
|
node.on({
|
|
scope: me,
|
|
insert: me.onNodeInsert,
|
|
append: me.onNodeAppend,
|
|
remove: me.onNodeRemove
|
|
});
|
|
|
|
me.nodeHash = {};
|
|
me.registerNode(node);
|
|
me.fireEvent('append', null, node);
|
|
me.fireEvent('rootchange', node);
|
|
}
|
|
|
|
return node;
|
|
},
|
|
|
|
|
|
flatten: function(){
|
|
var nodes = [],
|
|
hash = this.nodeHash,
|
|
key;
|
|
|
|
for (key in hash) {
|
|
if (hash.hasOwnProperty(key)) {
|
|
nodes.push(hash[key]);
|
|
}
|
|
}
|
|
return nodes;
|
|
},
|
|
|
|
|
|
onNodeInsert: function(parent, node) {
|
|
this.registerNode(node, true);
|
|
},
|
|
|
|
|
|
onNodeAppend: function(parent, node) {
|
|
this.registerNode(node, true);
|
|
},
|
|
|
|
|
|
onNodeRemove: function(parent, node) {
|
|
this.unregisterNode(node, true);
|
|
},
|
|
|
|
|
|
getNodeById : function(id) {
|
|
return this.nodeHash[id];
|
|
},
|
|
|
|
|
|
registerNode : function(node, includeChildren) {
|
|
this.nodeHash[node.getId() || node.internalId] = node;
|
|
if (includeChildren === true) {
|
|
node.eachChild(function(child){
|
|
this.registerNode(child, true);
|
|
}, this);
|
|
}
|
|
},
|
|
|
|
|
|
unregisterNode : function(node, includeChildren) {
|
|
delete this.nodeHash[node.getId() || node.internalId];
|
|
if (includeChildren === true) {
|
|
node.eachChild(function(child){
|
|
this.unregisterNode(child, true);
|
|
}, this);
|
|
}
|
|
},
|
|
|
|
|
|
sort: function(sorterFn, recursive) {
|
|
this.getRootNode().sort(sorterFn, recursive);
|
|
},
|
|
|
|
|
|
filter: function(filters, recursive) {
|
|
this.getRootNode().filter(filters, recursive);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.data.TreeStore', {
|
|
extend: 'Ext.data.AbstractStore',
|
|
alias: 'store.tree',
|
|
requires: ['Ext.data.Tree', 'Ext.data.NodeInterface', 'Ext.data.NodeStore'],
|
|
|
|
|
|
|
|
|
|
clearOnLoad : true,
|
|
|
|
|
|
nodeParam: 'node',
|
|
|
|
|
|
defaultRootId: 'root',
|
|
|
|
|
|
defaultRootProperty: 'children',
|
|
|
|
|
|
folderSort: false,
|
|
|
|
constructor: function(config) {
|
|
var me = this,
|
|
root,
|
|
fields;
|
|
|
|
config = Ext.apply({}, config);
|
|
|
|
|
|
fields = config.fields || me.fields;
|
|
if (!fields) {
|
|
config.fields = [{name: 'text', type: 'string'}];
|
|
}
|
|
|
|
me.callParent([config]);
|
|
|
|
|
|
me.tree = Ext.create('Ext.data.Tree');
|
|
|
|
me.relayEvents(me.tree, [
|
|
|
|
"append",
|
|
|
|
|
|
"remove",
|
|
|
|
|
|
"move",
|
|
|
|
|
|
"insert",
|
|
|
|
|
|
"beforeappend",
|
|
|
|
|
|
"beforeremove",
|
|
|
|
|
|
"beforemove",
|
|
|
|
|
|
"beforeinsert",
|
|
|
|
|
|
"expand",
|
|
|
|
|
|
"collapse",
|
|
|
|
|
|
"beforeexpand",
|
|
|
|
|
|
"beforecollapse",
|
|
|
|
|
|
"rootchange"
|
|
]);
|
|
|
|
me.tree.on({
|
|
scope: me,
|
|
remove: me.onNodeRemove,
|
|
|
|
|
|
beforeexpand: me.onBeforeNodeExpand,
|
|
beforecollapse: me.onBeforeNodeCollapse,
|
|
append: me.onNodeAdded,
|
|
insert: me.onNodeAdded
|
|
});
|
|
|
|
me.onBeforeSort();
|
|
|
|
root = me.root;
|
|
if (root) {
|
|
delete me.root;
|
|
me.setRootNode(root);
|
|
}
|
|
|
|
me.addEvents(
|
|
|
|
'sort'
|
|
);
|
|
|
|
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);
|
|
if (needsRoot) {
|
|
reader = proxy.getReader();
|
|
reader.root = this.defaultRootProperty;
|
|
|
|
reader.buildExtractors(true);
|
|
}
|
|
},
|
|
|
|
|
|
onBeforeSort: function() {
|
|
if (this.folderSort) {
|
|
this.sort({
|
|
property: 'leaf',
|
|
direction: 'ASC'
|
|
}, 'prepend', false);
|
|
}
|
|
},
|
|
|
|
|
|
onBeforeNodeExpand: function(node, callback, scope) {
|
|
if (node.isLoaded()) {
|
|
Ext.callback(callback, scope || node, [node.childNodes]);
|
|
}
|
|
else if (node.isLoading()) {
|
|
this.on('load', function() {
|
|
Ext.callback(callback, scope || node, [node.childNodes]);
|
|
}, this, {single: true});
|
|
}
|
|
else {
|
|
this.read({
|
|
node: node,
|
|
callback: function() {
|
|
Ext.callback(callback, scope || node, [node.childNodes]);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
getNewRecords: function() {
|
|
return Ext.Array.filter(this.tree.flatten(), this.filterNew);
|
|
},
|
|
|
|
|
|
getUpdatedRecords: function() {
|
|
return Ext.Array.filter(this.tree.flatten(), this.filterUpdated);
|
|
},
|
|
|
|
|
|
onBeforeNodeCollapse: function(node, callback, scope) {
|
|
callback.call(scope || node, node.childNodes);
|
|
},
|
|
|
|
onNodeRemove: function(parent, node) {
|
|
var removed = this.removed;
|
|
|
|
if (!node.isReplace && Ext.Array.indexOf(removed, node) == -1) {
|
|
removed.push(node);
|
|
}
|
|
},
|
|
|
|
onNodeAdded: function(parent, node) {
|
|
var proxy = this.getProxy(),
|
|
reader = proxy.getReader(),
|
|
data = node.raw || node.data,
|
|
dataRoot, children;
|
|
|
|
Ext.Array.remove(this.removed, node);
|
|
|
|
if (!node.isLeaf() && !node.isLoaded()) {
|
|
dataRoot = reader.getRoot(data);
|
|
if (dataRoot) {
|
|
this.fillNode(node, reader.extractData(dataRoot));
|
|
delete data[reader.root];
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
setRootNode: function(root) {
|
|
var me = this;
|
|
|
|
root = root || {};
|
|
if (!root.isNode) {
|
|
|
|
Ext.applyIf(root, {
|
|
id: me.defaultRootId,
|
|
text: 'Root',
|
|
allowDrag: false
|
|
});
|
|
root = Ext.ModelManager.create(root, me.model);
|
|
}
|
|
Ext.data.NodeInterface.decorate(root);
|
|
|
|
|
|
|
|
me.getProxy().getReader().buildExtractors(true);
|
|
|
|
|
|
me.tree.setRootNode(root);
|
|
|
|
|
|
if (!root.isLoaded() && (me.autoLoad === true || root.isExpanded())) {
|
|
me.load({
|
|
node: root
|
|
});
|
|
}
|
|
|
|
return root;
|
|
},
|
|
|
|
|
|
getRootNode: function() {
|
|
return this.tree.getRootNode();
|
|
},
|
|
|
|
|
|
getNodeById: function(id) {
|
|
return this.tree.getNodeById(id);
|
|
},
|
|
|
|
|
|
load: function(options) {
|
|
options = options || {};
|
|
options.params = options.params || {};
|
|
|
|
var me = this,
|
|
node = options.node || me.tree.getRootNode(),
|
|
root;
|
|
|
|
|
|
|
|
if (!node) {
|
|
node = me.setRootNode({
|
|
expanded: true
|
|
});
|
|
}
|
|
|
|
if (me.clearOnLoad) {
|
|
node.removeAll(true);
|
|
}
|
|
|
|
Ext.applyIf(options, {
|
|
node: node
|
|
});
|
|
options.params[me.nodeParam] = node ? node.getId() : 'root';
|
|
|
|
if (node) {
|
|
node.set('loading', true);
|
|
}
|
|
|
|
return me.callParent([options]);
|
|
},
|
|
|
|
|
|
|
|
fillNode: function(node, records) {
|
|
var me = this,
|
|
ln = records ? records.length : 0,
|
|
i = 0, sortCollection;
|
|
|
|
if (ln && me.sortOnLoad && !me.remoteSort && me.sorters && me.sorters.items) {
|
|
sortCollection = Ext.create('Ext.util.MixedCollection');
|
|
sortCollection.addAll(records);
|
|
sortCollection.sort(me.sorters.items);
|
|
records = sortCollection.items;
|
|
}
|
|
|
|
node.set('loaded', true);
|
|
for (; i < ln; i++) {
|
|
node.appendChild(records[i], undefined, true);
|
|
}
|
|
|
|
return records;
|
|
},
|
|
|
|
|
|
onProxyLoad: function(operation) {
|
|
var me = this,
|
|
successful = operation.wasSuccessful(),
|
|
records = operation.getRecords(),
|
|
node = operation.node;
|
|
|
|
me.loading = false;
|
|
node.set('loading', false);
|
|
if (successful) {
|
|
records = me.fillNode(node, records);
|
|
}
|
|
|
|
|
|
|
|
|
|
me.fireEvent('read', me, operation.node, records, successful);
|
|
me.fireEvent('load', me, operation.node, records, successful);
|
|
|
|
Ext.callback(operation.callback, operation.scope || me, [records, operation, successful]);
|
|
},
|
|
|
|
|
|
onCreateRecords: function(records, operation, success) {
|
|
if (success) {
|
|
var i = 0,
|
|
length = records.length,
|
|
originalRecords = operation.records,
|
|
parentNode,
|
|
record,
|
|
original,
|
|
index;
|
|
|
|
|
|
for (; i < length; ++i) {
|
|
record = records[i];
|
|
original = originalRecords[i];
|
|
if (original) {
|
|
parentNode = original.parentNode;
|
|
if (parentNode) {
|
|
|
|
original.isReplace = true;
|
|
parentNode.replaceChild(record, original);
|
|
delete original.isReplace;
|
|
}
|
|
record.phantom = false;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onUpdateRecords: function(records, operation, success){
|
|
if (success) {
|
|
var me = this,
|
|
i = 0,
|
|
length = records.length,
|
|
data = me.data,
|
|
original,
|
|
parentNode,
|
|
record;
|
|
|
|
for (; i < length; ++i) {
|
|
record = records[i];
|
|
original = me.tree.getNodeById(record.getId());
|
|
parentNode = original.parentNode;
|
|
if (parentNode) {
|
|
|
|
original.isReplace = true;
|
|
parentNode.replaceChild(record, original);
|
|
original.isReplace = false;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onDestroyRecords: function(records, operation, success){
|
|
if (success) {
|
|
this.removed = [];
|
|
}
|
|
},
|
|
|
|
|
|
removeAll: function() {
|
|
this.getRootNode().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('sort', me);
|
|
}
|
|
});
|
|
|
|
|
|
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.XmlStore', {
|
|
extend: 'Ext.data.Store',
|
|
alternateClassName: 'Ext.data.XmlStore',
|
|
alias: 'store.xml',
|
|
|
|
|
|
constructor: function(config){
|
|
config = config || {};
|
|
config = config || {};
|
|
|
|
Ext.applyIf(config, {
|
|
proxy: {
|
|
type: 'ajax',
|
|
reader: 'xml',
|
|
writer: 'xml'
|
|
}
|
|
});
|
|
|
|
this.callParent([config]);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.data.proxy.Client', {
|
|
extend: 'Ext.data.proxy.Proxy',
|
|
alternateClassName: 'Ext.data.ClientProxy',
|
|
|
|
|
|
clear: function() {
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.data.proxy.JsonP', {
|
|
extend: 'Ext.data.proxy.Server',
|
|
alternateClassName: 'Ext.data.ScriptTagProxy',
|
|
alias: ['proxy.jsonp', 'proxy.scripttag'],
|
|
requires: ['Ext.data.JsonP'],
|
|
|
|
defaultWriterType: 'base',
|
|
|
|
|
|
callbackKey : 'callback',
|
|
|
|
|
|
recordParam: 'records',
|
|
|
|
|
|
autoAppendParams: true,
|
|
|
|
constructor: function(){
|
|
this.addEvents(
|
|
|
|
'exception'
|
|
);
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
doRequest: function(operation, callback, scope) {
|
|
|
|
var me = this,
|
|
writer = me.getWriter(),
|
|
request = me.buildRequest(operation),
|
|
params = request.params;
|
|
|
|
if (operation.allowWrite()) {
|
|
request = writer.write(request);
|
|
}
|
|
|
|
|
|
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),
|
|
params = Ext.apply({}, request.params),
|
|
filters = params.filters,
|
|
records,
|
|
filter, i;
|
|
|
|
delete params.filters;
|
|
|
|
if (me.autoAppendParams) {
|
|
url = Ext.urlAppend(url, Ext.Object.toQueryString(params));
|
|
}
|
|
|
|
if (filters && filters.length) {
|
|
for (i = 0; i < filters.length; i++) {
|
|
filter = filters[i];
|
|
|
|
if (filter.value) {
|
|
url = Ext.urlAppend(url, filter.property + "=" + filter.value);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
records = request.records;
|
|
|
|
if (Ext.isArray(records) && records.length > 0) {
|
|
url = Ext.urlAppend(url, Ext.String.format("{0}={1}", me.recordParam, me.encodeRecords(records)));
|
|
}
|
|
|
|
return url;
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
this.abort();
|
|
this.callParent();
|
|
},
|
|
|
|
|
|
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 += Ext.Object.toQueryString(records[i].data);
|
|
}
|
|
|
|
return encoded;
|
|
}
|
|
});
|
|
|
|
|
|
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 records = operation.records,
|
|
length = records.length,
|
|
ids = this.getIds(),
|
|
id, record, i;
|
|
|
|
operation.setStarted();
|
|
|
|
for (i = 0; i < length; i++) {
|
|
record = records[i];
|
|
|
|
if (record.phantom) {
|
|
record.phantom = false;
|
|
id = this.getNextId();
|
|
} else {
|
|
id = record.getId();
|
|
}
|
|
|
|
this.setRecord(record, id);
|
|
ids.push(id);
|
|
}
|
|
|
|
this.setIds(ids);
|
|
|
|
operation.setCompleted();
|
|
operation.setSuccessful();
|
|
|
|
if (typeof callback == 'function') {
|
|
callback.call(scope || this, operation);
|
|
}
|
|
},
|
|
|
|
|
|
read: function(operation, callback, scope) {
|
|
|
|
|
|
var records = [],
|
|
ids = this.getIds(),
|
|
length = ids.length,
|
|
i, recordData, record;
|
|
|
|
|
|
if (operation.id) {
|
|
record = this.getRecord(operation.id);
|
|
|
|
if (record) {
|
|
records.push(record);
|
|
operation.setSuccessful();
|
|
}
|
|
} else {
|
|
for (i = 0; i < length; i++) {
|
|
records.push(this.getRecord(ids[i]));
|
|
}
|
|
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 || this, 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);
|
|
|
|
|
|
|
|
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 records = operation.records,
|
|
length = records.length,
|
|
ids = this.getIds(),
|
|
|
|
|
|
newIds = [].concat(ids),
|
|
i;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
Ext.Array.remove(newIds, records[i].getId());
|
|
this.removeRecord(records[i], false);
|
|
}
|
|
|
|
this.setIds(newIds);
|
|
|
|
operation.setCompleted();
|
|
operation.setSuccessful();
|
|
|
|
if (typeof callback == 'function') {
|
|
callback.call(scope || this, operation);
|
|
}
|
|
},
|
|
|
|
|
|
getRecord: function(id) {
|
|
if (this.cache[id] === undefined) {
|
|
var rawData = Ext.decode(this.getStorageObject().getItem(this.getRecordKey(id))),
|
|
data = {},
|
|
Model = this.model,
|
|
fields = Model.prototype.fields.items,
|
|
length = fields.length,
|
|
i, field, name, record;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
field = fields[i];
|
|
name = field.name;
|
|
|
|
if (typeof field.decode == 'function') {
|
|
data[name] = field.decode(rawData[name]);
|
|
} else {
|
|
data[name] = rawData[name];
|
|
}
|
|
}
|
|
|
|
record = new Model(data, id);
|
|
record.phantom = false;
|
|
|
|
this.cache[id] = record;
|
|
}
|
|
|
|
return this.cache[id];
|
|
},
|
|
|
|
|
|
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 (typeof field.encode == 'function') {
|
|
data[name] = field.encode(rawData[name], record);
|
|
} else {
|
|
data[name] = rawData[name];
|
|
}
|
|
}
|
|
|
|
obj = me.getStorageObject();
|
|
key = me.getRecordKey(id);
|
|
|
|
|
|
me.cache[id] = record;
|
|
|
|
|
|
obj.removeItem(key);
|
|
obj.setItem(key, Ext.encode(data));
|
|
},
|
|
|
|
|
|
removeRecord: function(id, updateIds) {
|
|
var me = this,
|
|
ids;
|
|
|
|
if (id.isModel) {
|
|
id = id.getId();
|
|
}
|
|
|
|
if (updateIds !== false) {
|
|
ids = me.getIds();
|
|
Ext.Array.remove(ids, id);
|
|
me.setIds(ids);
|
|
}
|
|
|
|
me.getStorageObject().removeItem(me.getRecordKey(id));
|
|
},
|
|
|
|
|
|
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);
|
|
},
|
|
|
|
|
|
getIds: function() {
|
|
var ids = (this.getStorageObject().getItem(this.id) || "").split(","),
|
|
length = ids.length,
|
|
i;
|
|
|
|
if (length == 1 && ids[0] === "") {
|
|
ids = [];
|
|
} else {
|
|
for (i = 0; i < length; i++) {
|
|
ids[i] = parseInt(ids[i], 10);
|
|
}
|
|
}
|
|
|
|
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 obj = this.getStorageObject(),
|
|
key = this.getRecordCounterKey(),
|
|
last = obj.getItem(key),
|
|
ids, id;
|
|
|
|
if (last === null) {
|
|
ids = this.getIds();
|
|
last = ids[ids.length - 1] || 0;
|
|
}
|
|
|
|
id = parseInt(last, 10) + 1;
|
|
obj.setItem(key, id);
|
|
|
|
return id;
|
|
},
|
|
|
|
|
|
initialize: function() {
|
|
var storageObject = this.getStorageObject();
|
|
storageObject.setItem(this.id, storageObject.getItem(this.id) || "");
|
|
},
|
|
|
|
|
|
clear: function() {
|
|
var obj = this.getStorageObject(),
|
|
ids = this.getIds(),
|
|
len = ids.length,
|
|
i;
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
this.removeRecord(ids[i]);
|
|
}
|
|
|
|
|
|
obj.removeItem(this.getRecordCounterKey());
|
|
obj.removeItem(this.id);
|
|
},
|
|
|
|
|
|
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.Memory', {
|
|
extend: 'Ext.data.proxy.Client',
|
|
alias: 'proxy.memory',
|
|
alternateClassName: 'Ext.data.MemoryProxy',
|
|
|
|
|
|
|
|
constructor: function(config) {
|
|
this.callParent([config]);
|
|
|
|
|
|
this.setReader(this.reader);
|
|
},
|
|
|
|
|
|
read: function(operation, callback, scope) {
|
|
var me = this,
|
|
reader = me.getReader(),
|
|
result = reader.read(me.data);
|
|
|
|
Ext.apply(operation, {
|
|
resultSet: result
|
|
});
|
|
|
|
operation.setCompleted();
|
|
operation.setSuccessful();
|
|
Ext.callback(callback, scope || me, [operation]);
|
|
},
|
|
|
|
clear: Ext.emptyFn
|
|
});
|
|
|
|
|
|
Ext.define('Ext.data.proxy.Rest', {
|
|
extend: 'Ext.data.proxy.Ajax',
|
|
alternateClassName: 'Ext.data.RestProxy',
|
|
alias : 'proxy.rest',
|
|
|
|
|
|
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 && id) {
|
|
if (!url.match(/\/$/)) {
|
|
url += '/';
|
|
}
|
|
|
|
url += id;
|
|
}
|
|
|
|
if (format) {
|
|
if (!url.match(/\.$/)) {
|
|
url += '.';
|
|
}
|
|
|
|
url += format;
|
|
}
|
|
|
|
request.url = url;
|
|
|
|
return me.callParent(arguments);
|
|
}
|
|
}, function() {
|
|
Ext.apply(this.prototype, {
|
|
|
|
actionMethods: {
|
|
create : 'POST',
|
|
read : 'GET',
|
|
update : 'PUT',
|
|
destroy: 'DELETE'
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
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.data.reader.Array', {
|
|
extend: 'Ext.data.reader.Json',
|
|
alternateClassName: 'Ext.data.ArrayReader',
|
|
alias : 'reader.array',
|
|
|
|
|
|
buildExtractors: function() {
|
|
this.callParent(arguments);
|
|
|
|
var fields = this.model.prototype.fields.items,
|
|
i = 0,
|
|
length = fields.length,
|
|
extractorFunctions = [],
|
|
map;
|
|
|
|
for (; i < length; i++) {
|
|
map = fields[i].mapping;
|
|
extractorFunctions.push(function(index) {
|
|
return function(data) {
|
|
return data[index];
|
|
};
|
|
}(map !== null ? map : i));
|
|
}
|
|
|
|
this.extractorFunctions = extractorFunctions;
|
|
}
|
|
});
|
|
|
|
|
|
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 && node.firstChild) {
|
|
return node.firstChild.nodeValue;
|
|
}
|
|
return undefined;
|
|
},
|
|
|
|
|
|
getResponseData: function(response) {
|
|
var xml = response.responseXML;
|
|
|
|
|
|
return 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]);
|
|
}
|
|
});
|
|
|
|
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], '</', key, '>');
|
|
}
|
|
}
|
|
xml.push('</', record, '>');
|
|
}
|
|
|
|
if (root) {
|
|
xml.push('</', root, '>');
|
|
}
|
|
|
|
request.xmlData = xml.join('');
|
|
return request;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.direct.Event', {
|
|
|
|
|
|
|
|
alias: 'direct.event',
|
|
|
|
requires: ['Ext.direct.Manager'],
|
|
|
|
|
|
|
|
status: true,
|
|
|
|
|
|
constructor: function(config) {
|
|
Ext.apply(this, config);
|
|
},
|
|
|
|
|
|
getData: function(){
|
|
return this.data;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.direct.RemotingEvent', {
|
|
|
|
|
|
|
|
extend: 'Ext.direct.Event',
|
|
|
|
alias: 'direct.rpc',
|
|
|
|
|
|
|
|
|
|
getTransaction: function(){
|
|
return this.transaction || Ext.direct.Manager.getTransaction(this.tid);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.direct.ExceptionEvent', {
|
|
|
|
|
|
|
|
extend: 'Ext.direct.RemotingEvent',
|
|
|
|
alias: 'direct.exception',
|
|
|
|
|
|
|
|
status: false
|
|
});
|
|
|
|
|
|
Ext.define('Ext.direct.Provider', {
|
|
|
|
|
|
|
|
alias: 'direct.provider',
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
constructor : function(config){
|
|
var me = this;
|
|
|
|
Ext.apply(me, config);
|
|
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.direct.JsonProvider', {
|
|
|
|
|
|
|
|
extend: 'Ext.direct.Provider',
|
|
|
|
alias: 'direct.jsonprovider',
|
|
|
|
uses: ['Ext.direct.ExceptionEvent'],
|
|
|
|
|
|
|
|
|
|
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 data = null,
|
|
events = [],
|
|
event,
|
|
i = 0,
|
|
len;
|
|
|
|
try{
|
|
data = this.parseResponse(response);
|
|
} catch(e) {
|
|
event = Ext.create('Ext.direct.ExceptionEvent', {
|
|
data: e,
|
|
xhr: response,
|
|
code: Ext.direct.Manager.self.exceptions.PARSE,
|
|
message: 'Error parsing json response: \n\n ' + data
|
|
});
|
|
return [event];
|
|
}
|
|
|
|
if (Ext.isArray(data)) {
|
|
for (len = data.length; i < len; ++i) {
|
|
events.push(this.createEvent(data[i]));
|
|
}
|
|
} else {
|
|
events.push(this.createEvent(data));
|
|
}
|
|
return events;
|
|
},
|
|
|
|
|
|
createEvent: function(response){
|
|
return Ext.create('direct.' + response.type, response);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.direct.PollingProvider', {
|
|
|
|
|
|
|
|
extend: 'Ext.direct.JsonProvider',
|
|
|
|
alias: 'direct.pollingprovider',
|
|
|
|
uses: ['Ext.direct.ExceptionEvent'],
|
|
|
|
requires: ['Ext.Ajax', 'Ext.util.DelayedTask'],
|
|
|
|
|
|
|
|
|
|
interval: 3000,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor : function(config){
|
|
this.callParent(arguments);
|
|
this.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: function(){
|
|
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
|
|
});
|
|
}
|
|
}
|
|
},
|
|
interval: me.interval,
|
|
scope: me
|
|
});
|
|
me.fireEvent('connect', me);
|
|
} else if (!url) {
|
|
}
|
|
},
|
|
|
|
|
|
disconnect: function(){
|
|
var me = this;
|
|
|
|
if (me.pollTask) {
|
|
Ext.TaskManager.stop(me.pollTask);
|
|
delete me.pollTask;
|
|
me.fireEvent('disconnect', me);
|
|
}
|
|
},
|
|
|
|
|
|
onData: function(opt, success, response){
|
|
var me = this,
|
|
i = 0,
|
|
len,
|
|
events;
|
|
|
|
if (success) {
|
|
events = me.createEvents(response);
|
|
for (len = events.length; i < len; ++i) {
|
|
me.fireEvent('data', me, events[i]);
|
|
}
|
|
} else {
|
|
me.fireEvent('data', me, Ext.create('Ext.direct.ExceptionEvent', {
|
|
data: null,
|
|
code: Ext.direct.Manager.self.exceptions.TRANSPORT,
|
|
message: 'Unable to connect to the server.',
|
|
xhr: response
|
|
}));
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.direct.RemotingMethod', {
|
|
|
|
constructor: function(config){
|
|
var me = this,
|
|
params = Ext.isDefined(config.params) ? config.params : config.len,
|
|
name;
|
|
|
|
me.name = config.name;
|
|
me.formHandler = config.formHandler;
|
|
if (Ext.isNumber(params)) {
|
|
|
|
me.len = params;
|
|
me.ordered = true;
|
|
} else {
|
|
|
|
me.params = [];
|
|
Ext.each(params, function(param){
|
|
name = Ext.isObject(param) ? param.name : param;
|
|
me.params.push(name);
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
getCallData: function(args){
|
|
var me = this,
|
|
data = null,
|
|
len = me.len,
|
|
params = me.params,
|
|
callback,
|
|
scope,
|
|
name;
|
|
|
|
if (me.ordered) {
|
|
callback = args[len];
|
|
scope = args[len + 1];
|
|
if (len !== 0) {
|
|
data = args.slice(0, len);
|
|
}
|
|
} else {
|
|
data = Ext.apply({}, args[0]);
|
|
callback = args[1];
|
|
scope = args[2];
|
|
|
|
|
|
for (name in data) {
|
|
if (data.hasOwnProperty(name)) {
|
|
if (!Ext.Array.contains(params, name)) {
|
|
delete data[name];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
data: data,
|
|
callback: callback,
|
|
scope: scope
|
|
};
|
|
}
|
|
});
|
|
|
|
|
|
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.self.TRANSACTION_ID;
|
|
me.retryCount = 0;
|
|
},
|
|
|
|
send: function(){
|
|
this.provider.queueTransaction(this);
|
|
},
|
|
|
|
retry: function(){
|
|
this.retryCount++;
|
|
this.send();
|
|
},
|
|
|
|
getProvider: function(){
|
|
return this.provider;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.direct.RemotingProvider', {
|
|
|
|
|
|
|
|
alias: 'direct.remotingprovider',
|
|
|
|
extend: 'Ext.direct.JsonProvider',
|
|
|
|
requires: [
|
|
'Ext.util.MixedCollection',
|
|
'Ext.util.DelayedTask',
|
|
'Ext.direct.Transaction',
|
|
'Ext.direct.RemotingMethod'
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enableBuffer: 10,
|
|
|
|
|
|
maxRetries: 1,
|
|
|
|
|
|
timeout: undefined,
|
|
|
|
constructor : function(config){
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
me.addEvents(
|
|
|
|
'beforecall',
|
|
|
|
'call'
|
|
);
|
|
me.namespace = (Ext.isString(me.namespace)) ? Ext.ns(me.namespace) : me.namespace || window;
|
|
me.transactions = Ext.create('Ext.util.MixedCollection');
|
|
me.callBuffer = [];
|
|
},
|
|
|
|
|
|
initAPI : function(){
|
|
var actions = this.actions,
|
|
namespace = this.namespace,
|
|
action,
|
|
cls,
|
|
methods,
|
|
i,
|
|
len,
|
|
method;
|
|
|
|
for (action in actions) {
|
|
cls = namespace[action];
|
|
if (!cls) {
|
|
cls = namespace[action] = {};
|
|
}
|
|
methods = actions[action];
|
|
|
|
for (i = 0, len = methods.length; i < len; ++i) {
|
|
method = Ext.create('Ext.direct.RemotingMethod', methods[i]);
|
|
cls[method.name] = this.createHandler(action, method);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
createHandler : function(action, method){
|
|
var me = this,
|
|
handler;
|
|
|
|
if (!method.formHandler) {
|
|
handler = function(){
|
|
me.configureRequest(action, method, Array.prototype.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);
|
|
} else if(!me.url) {
|
|
}
|
|
},
|
|
|
|
|
|
disconnect: function(){
|
|
var me = this;
|
|
|
|
if (me.connected) {
|
|
me.connected = false;
|
|
me.fireEvent('disconnect', me);
|
|
}
|
|
},
|
|
|
|
|
|
runCallback: function(transaction, event){
|
|
var funcName = event.status ? 'success' : 'failure',
|
|
callback,
|
|
result;
|
|
|
|
if (transaction && transaction.callback) {
|
|
callback = transaction.callback;
|
|
result = Ext.isDefined(event.result) ? event.result : event.data;
|
|
|
|
if (Ext.isFunction(callback)) {
|
|
callback(result, event);
|
|
} else {
|
|
Ext.callback(callback[funcName], callback.scope, [result, event]);
|
|
Ext.callback(callback.callback, callback.scope, [result, event]);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onData: function(options, success, response){
|
|
var me = this,
|
|
i = 0,
|
|
len,
|
|
events,
|
|
event,
|
|
transaction,
|
|
transactions;
|
|
|
|
if (success) {
|
|
events = me.createEvents(response);
|
|
for (len = events.length; i < len; ++i) {
|
|
event = events[i];
|
|
transaction = me.getTransaction(event);
|
|
me.fireEvent('data', me, event);
|
|
if (transaction) {
|
|
me.runCallback(transaction, event, true);
|
|
Ext.direct.Manager.removeTransaction(transaction);
|
|
}
|
|
}
|
|
} else {
|
|
transactions = [].concat(options.transaction);
|
|
for (len = transactions.length; i < len; ++i) {
|
|
transaction = me.getTransaction(transactions[i]);
|
|
if (transaction && transaction.retryCount < me.maxRetries) {
|
|
transaction.retry();
|
|
} else {
|
|
event = Ext.create('Ext.direct.ExceptionEvent', {
|
|
data: null,
|
|
transaction: transaction,
|
|
code: Ext.direct.Manager.self.exceptions.TRANSPORT,
|
|
message: 'Unable to connect to the server.',
|
|
xhr: response
|
|
});
|
|
me.fireEvent('data', me, event);
|
|
if (transaction) {
|
|
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 = method.getCallData(args),
|
|
data = callData.data,
|
|
callback = callData.callback,
|
|
scope = callData.scope,
|
|
transaction;
|
|
|
|
transaction = Ext.create('Ext.direct.Transaction', {
|
|
provider: me,
|
|
args: args,
|
|
action: action,
|
|
method: method.name,
|
|
data: data,
|
|
callback: scope && Ext.isFunction(callback) ? Ext.Function.bind(callback, scope) : callback
|
|
});
|
|
|
|
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 = {
|
|
url: me.url,
|
|
callback: me.onData,
|
|
scope: me,
|
|
transaction: data,
|
|
timeout: me.timeout
|
|
}, callData,
|
|
enableUrlEncode = me.enableUrlEncode,
|
|
i = 0,
|
|
len,
|
|
params;
|
|
|
|
|
|
if (Ext.isArray(data)) {
|
|
callData = [];
|
|
for (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;
|
|
}
|
|
|
|
me.callBuffer.push(transaction);
|
|
if (enableBuffer) {
|
|
if (!me.callTask) {
|
|
me.callTask = Ext.create('Ext.util.DelayedTask', me.combineAndSend, me);
|
|
}
|
|
me.callTask.delay(Ext.isNumber(enableBuffer) ? enableBuffer : 10);
|
|
} else {
|
|
me.combineAndSend();
|
|
}
|
|
},
|
|
|
|
|
|
combineAndSend : function(){
|
|
var buffer = this.callBuffer,
|
|
len = buffer.length;
|
|
|
|
if (len > 0) {
|
|
this.sendRequest(len == 1 ? buffer[0] : buffer);
|
|
this.callBuffer = [];
|
|
}
|
|
},
|
|
|
|
|
|
configureFormRequest : function(action, method, form, callback, scope){
|
|
var me = this,
|
|
transaction = Ext.create('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
|
|
}),
|
|
isUpload,
|
|
params;
|
|
|
|
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){
|
|
Ext.Ajax.request({
|
|
url: this.url,
|
|
params: transaction.params,
|
|
callback: this.onData,
|
|
scope: this,
|
|
form: transaction.form,
|
|
isUpload: transaction.isUpload,
|
|
transaction: transaction
|
|
});
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.draw.Matrix', {
|
|
|
|
|
|
|
|
requires: ['Ext.draw.Draw'],
|
|
|
|
|
|
|
|
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(1, 0, 0, 1, cx, cy);
|
|
me.add(x, 0, 0, y, 0, 0);
|
|
me.add(1, 0, 0, 1, -cx, -cy);
|
|
},
|
|
|
|
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, y);
|
|
me.add(1, 0, 0, 1, -x, -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() {
|
|
var me = this;
|
|
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) + ", Dy=" + me.get(1, 2) + ")";
|
|
},
|
|
|
|
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][0], 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 Ext.create('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'
|
|
},
|
|
|
|
requires: ['Ext.draw.SpriteDD'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 = 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;
|
|
me.draggable = true;
|
|
|
|
if (!me.el) {
|
|
me.surface.createSpriteElement(me);
|
|
}
|
|
me.dd = Ext.create('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,
|
|
attr, i, translate, translation, rotate, rotation, scale, 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;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
if ('zIndex' in attrs) {
|
|
me.zIndexDirty = true;
|
|
}
|
|
|
|
|
|
for (i = 0; i < fontPropsLength; i++) {
|
|
attr = fontProps[i];
|
|
if (attr in attrs && attrs[attr] !== spriteAttrs[attr]) {
|
|
me.dirtyFont = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
translate = attrs.translate;
|
|
translation = spriteAttrs.translation;
|
|
if (translate) {
|
|
if ((translate.x && translate.x !== translation.x) ||
|
|
(translate.y && translate.y !== translation.y)) {
|
|
Ext.apply(translation, translate);
|
|
me.dirtyTransform = true;
|
|
}
|
|
delete attrs.translate;
|
|
}
|
|
|
|
rotate = attrs.rotate;
|
|
rotation = spriteAttrs.rotation;
|
|
if (rotate) {
|
|
if ((rotate.x && rotate.x !== rotation.x) ||
|
|
(rotate.y && rotate.y !== rotation.y) ||
|
|
(rotate.degrees && rotate.degrees !== rotation.degrees)) {
|
|
Ext.apply(rotation, rotate);
|
|
me.dirtyTransform = true;
|
|
}
|
|
delete attrs.rotate;
|
|
}
|
|
|
|
scale = attrs.scale;
|
|
scaling = spriteAttrs.scaling;
|
|
if (scale) {
|
|
if ((scale.x && scale.x !== scaling.x) ||
|
|
(scale.y && scale.y !== scaling.y) ||
|
|
(scale.cx && scale.cx !== scaling.cx) ||
|
|
(scale.cy && scale.cy !== scaling.cy)) {
|
|
Ext.apply(scaling, scale);
|
|
me.dirtyTransform = true;
|
|
}
|
|
delete attrs.scale;
|
|
}
|
|
|
|
Ext.apply(spriteAttrs, attrs);
|
|
me.dirty = true;
|
|
|
|
if (redraw === true && hasSurface) {
|
|
me.redraw();
|
|
}
|
|
return this;
|
|
},
|
|
|
|
|
|
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() {
|
|
this.surface.renderItem(this);
|
|
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.engine.Svg', {
|
|
|
|
|
|
|
|
extend: 'Ext.draw.Surface',
|
|
|
|
requires: ['Ext.draw.Draw', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.Element'],
|
|
|
|
|
|
|
|
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 = Ext.create('Ext.draw.Matrix');
|
|
sprite.bbox = {
|
|
plain: 0,
|
|
transform: 0
|
|
};
|
|
sprite.fireEvent("render", sprite);
|
|
return el;
|
|
},
|
|
|
|
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;
|
|
}
|
|
sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
|
|
return sprite.bbox.transform;
|
|
},
|
|
|
|
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) {
|
|
var me = this,
|
|
matrix = Ext.create('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;
|
|
sprite.el.set({transform: matrix.toSvg()});
|
|
},
|
|
|
|
setSize: function(w, h) {
|
|
var me = this,
|
|
el = me.el;
|
|
|
|
w = +w || me.width;
|
|
h = +h || me.height;
|
|
me.width = w;
|
|
me.height = h;
|
|
|
|
el.setSize(w, h);
|
|
el.set({
|
|
width: w,
|
|
height: h
|
|
});
|
|
me.callParent([w, h]);
|
|
},
|
|
|
|
|
|
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.remove();
|
|
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;
|
|
if (!me.el) {
|
|
var width = me.width || 10,
|
|
height = me.height || 10,
|
|
el = me.createSvgElement('svg', {
|
|
xmlns: "http:/" + "/www.w3.org/2000/svg",
|
|
version: 1.1,
|
|
width: width,
|
|
height: height
|
|
}),
|
|
defs = me.getDefs(),
|
|
|
|
|
|
|
|
|
|
|
|
bgRect = me.createSvgElement("rect", {
|
|
width: "100%",
|
|
height: "100%",
|
|
fill: "#000",
|
|
stroke: "none",
|
|
opacity: 0
|
|
}),
|
|
webkitRect;
|
|
|
|
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
|
|
});
|
|
}
|
|
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;
|
|
|
|
if (attrs.hasOwnProperty("text")) {
|
|
tspans = this.setText(sprite, attrs.text);
|
|
}
|
|
|
|
if (tspans.length) {
|
|
height = this.getBBoxText(sprite).height;
|
|
for (i = 0, ln = tspans.length; i < ln; i++) {
|
|
|
|
|
|
factor = (Ext.isFF3_0 || Ext.isFF3_5) ? 2 : 4;
|
|
tspans[i].setAttribute("dy", i ? height * 1.2 : height / factor);
|
|
}
|
|
sprite.dirty = true;
|
|
}
|
|
},
|
|
|
|
setText: function(sprite, textString) {
|
|
var me = this,
|
|
el = sprite.el.dom,
|
|
x = el.getAttribute("x"),
|
|
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)));
|
|
tspan.setAttribute("x", x);
|
|
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);
|
|
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});
|
|
sprite.dirtyFont = false;
|
|
}
|
|
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 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);
|
|
}
|
|
|
|
|
|
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 = Ext.create('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();
|
|
}
|
|
delete me.el;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.draw.engine.Vml', {
|
|
|
|
|
|
|
|
extend: 'Ext.draw.Surface',
|
|
|
|
requires: ['Ext.draw.Draw', 'Ext.draw.Color', 'Ext.draw.Sprite', 'Ext.draw.Matrix', 'Ext.Element'],
|
|
|
|
|
|
|
|
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',
|
|
|
|
// 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 = 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);
|
|
me.el.appendChild(el);
|
|
if (type !== 'image') {
|
|
skew = me.createNode("skew");
|
|
skew.on = true;
|
|
el.appendChild(skew);
|
|
sprite.skew = skew;
|
|
}
|
|
sprite.matrix = Ext.create('Ext.draw.Matrix');
|
|
sprite.bbox = {
|
|
plain: null,
|
|
transform: null
|
|
};
|
|
sprite.fireEvent("render", sprite);
|
|
return sprite.el;
|
|
},
|
|
|
|
|
|
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;
|
|
}
|
|
sprite.bbox.transform = sprite.bbox.transform || Ext.draw.Draw.pathDimensions(Ext.draw.Draw.mapPath(realPath, sprite.matrix));
|
|
return sprite.bbox.transform;
|
|
},
|
|
|
|
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, bbox;
|
|
|
|
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 (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") {
|
|
var 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.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 (sprite.type == 'image' || scrubbedAttrs.opacity || scrubbedAttrs['fill-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) {
|
|
if (sprite.el) {
|
|
if (sprite.attr.zIndex != undefined) {
|
|
sprite.el.setStyle('zIndex', sprite.attr.zIndex);
|
|
}
|
|
sprite.zIndexDirty = false;
|
|
}
|
|
},
|
|
|
|
|
|
setPaths: function(sprite, params) {
|
|
var spriteAttr = sprite.attr;
|
|
|
|
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' || sprite.type == 'image') {
|
|
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 = el.dom,
|
|
fillEl = dom.getElementsByTagName('fill')[0],
|
|
opacity, gradient, fillUrl, rotation, angle;
|
|
|
|
if (fillEl) {
|
|
dom.removeChild(fillEl);
|
|
} else {
|
|
fillEl = me.createNode('fill');
|
|
}
|
|
if (Ext.isArray(params.fill)) {
|
|
params.fill = params.fill[0];
|
|
}
|
|
if (sprite.type == 'image') {
|
|
fillEl.on = true;
|
|
fillEl.src = params.src;
|
|
fillEl.type = "tile";
|
|
fillEl.rotate = true;
|
|
} else 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";
|
|
fillEl.colors = gradient.colors;
|
|
}
|
|
|
|
else {
|
|
fillEl.src = fillUrl;
|
|
fillEl.type = "tile";
|
|
fillEl.rotate = true;
|
|
}
|
|
}
|
|
else {
|
|
fillEl.color = Ext.draw.Color.toHex(params.fill) || params.fill;
|
|
fillEl.src = "";
|
|
fillEl.type = "solid";
|
|
}
|
|
}
|
|
}
|
|
dom.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.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(/</g, "<").replace(/&/g, "&").replace(/\n/g, "<br>");
|
|
}
|
|
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.applyViewBox();
|
|
|
|
me.callParent(arguments);
|
|
}
|
|
},
|
|
|
|
setViewBox: function(x, y, width, height) {
|
|
this.callParent(arguments);
|
|
this.viewBox = {
|
|
x: x,
|
|
y: y,
|
|
width: width,
|
|
height: height
|
|
};
|
|
this.applyViewBox();
|
|
},
|
|
|
|
|
|
applyViewBox: function() {
|
|
var me = this,
|
|
viewBox = me.viewBox,
|
|
width = me.width,
|
|
height = me.height,
|
|
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;
|
|
|
|
if (viewBoxWidth * relativeHeight < width) {
|
|
viewBoxX -= (width - viewBoxWidth * relativeHeight) / 2 / relativeHeight;
|
|
}
|
|
if (viewBoxHeight * relativeWidth < height) {
|
|
viewBoxY -= (height - viewBoxHeight * relativeWidth) / 2 / relativeWidth;
|
|
}
|
|
|
|
size = 1 / Math.max(viewBoxWidth / width, viewBoxHeight / height);
|
|
|
|
me.viewBoxShift = {
|
|
dx: -viewBoxX,
|
|
dy: -viewBoxY,
|
|
scale: size
|
|
};
|
|
me.items.each(function(item) {
|
|
me.transform(item);
|
|
});
|
|
}
|
|
},
|
|
|
|
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);
|
|
},
|
|
|
|
|
|
createNode : (function () {
|
|
try {
|
|
var doc = Ext.getDoc().dom;
|
|
if (!doc.namespaces.rvml) {
|
|
doc.namespaces.add("rvml", "urn:schemas-microsoft-com:vml");
|
|
}
|
|
return function (tagName) {
|
|
return doc.createElement("<rvml:" + tagName + ' class="rvml">');
|
|
};
|
|
} catch (e) {
|
|
return function (tagName) {
|
|
return doc.createElement("<" + tagName + ' xmlns="urn:schemas-microsoft.com:vml" class="rvml">');
|
|
};
|
|
}
|
|
})(),
|
|
|
|
render: function (container) {
|
|
var me = this,
|
|
doc = Ext.getDoc().dom;
|
|
|
|
if (!me.el) {
|
|
var 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 || 10, me.height || 10);
|
|
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
|
|
});
|
|
}
|
|
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 = Ext.create('Ext.draw.Matrix');
|
|
matrix.rotate(-deg, 0.5, 0.5);
|
|
return {
|
|
x: matrix.x(dx, dy),
|
|
y: matrix.y(dx, dy)
|
|
};
|
|
},
|
|
|
|
extractTransform: function (sprite) {
|
|
var me = this,
|
|
matrix = Ext.create('Ext.draw.Matrix'), scale,
|
|
transformstions, tranformationsLength,
|
|
transform, i = 0,
|
|
shift = me.viewBoxShift;
|
|
|
|
for(transformstions = sprite.transformations, tranformationsLength = transformstions.length;
|
|
i < tranformationsLength; i ++) {
|
|
transform = transformstions[i];
|
|
switch (transform.type) {
|
|
case 'translate' :
|
|
matrix.translate(transform.x, transform.y);
|
|
break;
|
|
case 'rotate':
|
|
matrix.rotate(transform.degrees, transform.x, transform.y);
|
|
break;
|
|
case 'scale':
|
|
matrix.scale(transform.x || transform.scale, transform.y || transform.scale, transform.centerX, transform.centerY);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (shift) {
|
|
matrix.add(1, 0, 0, 1, shift.dx, shift.dy);
|
|
matrix.prepend(shift.scale, 0, 0, shift.scale, 0, 0);
|
|
}
|
|
|
|
return sprite.matrix = matrix;
|
|
},
|
|
|
|
setSimpleCoords: function(sprite, sx, sy, dx, dy, rotate) {
|
|
var me = this,
|
|
matrix = sprite.matrix,
|
|
dom = sprite.el.dom,
|
|
style = dom.style,
|
|
yFlipper = 1,
|
|
flip = "",
|
|
fill = dom.getElementsByTagName('fill')[0],
|
|
kx = me.zoom / sx,
|
|
ky = me.zoom / sy,
|
|
rotationCompensation;
|
|
if (!sx || !sy) {
|
|
return;
|
|
}
|
|
dom.coordsize = Math.abs(kx) + ' ' + Math.abs(ky);
|
|
style.rotation = rotate * (sx * sy < 0 ? -1 : 1);
|
|
if (rotate) {
|
|
rotationCompensation = me.rotationCompensation(rotate, dx, dy);
|
|
dx = rotationCompensation.x;
|
|
dy = rotationCompensation.y;
|
|
}
|
|
if (sx < 0) {
|
|
flip += "x"
|
|
}
|
|
if (sy < 0) {
|
|
flip += " y";
|
|
yFlipper = -1;
|
|
}
|
|
style.flip = flip;
|
|
dom.coordorigin = (dx * -kx) + ' ' + (dy * -ky);
|
|
if (fill) {
|
|
dom.removeChild(fill);
|
|
rotationCompensation = me.rotationCompensation(rotate, matrix.x(sprite.x, sprite.y), matrix.y(sprite.x, sprite.y));
|
|
fill.position = rotationCompensation.x * yFlipper + ' ' + rotationCompensation.y * yFlipper;
|
|
fill.size = sprite.width * Math.abs(sx) + ' ' + sprite.height * Math.abs(sy);
|
|
dom.appendChild(fill);
|
|
}
|
|
},
|
|
|
|
transform : function (sprite) {
|
|
var me = this,
|
|
el = sprite.el,
|
|
skew = sprite.skew,
|
|
dom = el.dom,
|
|
domStyle = dom.style,
|
|
matrix = me.extractTransform(sprite).clone(),
|
|
split, zoom = me.zoom,
|
|
fill = dom.getElementsByTagName('fill')[0],
|
|
isPatt = !String(sprite.fill).indexOf("url("),
|
|
offset, c;
|
|
|
|
|
|
|
|
|
|
if (sprite.type != "image" && skew && !isPatt) {
|
|
|
|
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 {
|
|
if (skew) {
|
|
skew.matrix = "1 0 0 1";
|
|
skew.offset = "0 0";
|
|
}
|
|
split = matrix.split();
|
|
if (split.isSimple) {
|
|
domStyle.filter = '';
|
|
me.setSimpleCoords(sprite, split.scaleX, split.scaleY, split.translateX, split.translateY, split.rotate / Math.PI * 180);
|
|
} else {
|
|
domStyle.filter = matrix.toFilter();
|
|
var bb = me.getBBox(sprite),
|
|
dx = bb.x - sprite.x,
|
|
dy = bb.y - sprite.y;
|
|
dom.coordorigin = (dx * -zoom) + ' ' + (dy * -zoom);
|
|
if (fill) {
|
|
dom.removeChild(fill);
|
|
fill.position = dx + ' ' + dy;
|
|
fill.size = sprite.width * sprite.scale.x + ' ' + sprite.height * 1.1;
|
|
dom.appendChild(fill);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
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');
|
|
|
|
|
|
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);
|
|
});
|
|
stops.eachKey(function(k, v) {
|
|
colors.push(k + "% " + v.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.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.CompositeElementCSS', {
|
|
|
|
|
|
|
|
extend: 'Ext.fx.target.CompositeElement',
|
|
|
|
requires: ['Ext.fx.target.ElementCSS'],
|
|
|
|
|
|
setAttr: function() {
|
|
return Ext.fx.target.ElementCSS.prototype.setAttr.apply(this, arguments);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.layout.container.AbstractFit', {
|
|
|
|
|
|
|
|
extend: 'Ext.layout.container.Container',
|
|
|
|
|
|
|
|
itemCls: Ext.baseCSSPrefix + 'fit-item',
|
|
targetCls: Ext.baseCSSPrefix + 'layout-fit',
|
|
type: 'fit'
|
|
});
|
|
|
|
Ext.define('Ext.layout.container.Fit', {
|
|
|
|
|
|
|
|
extend: 'Ext.layout.container.AbstractFit',
|
|
alias: 'layout.fit',
|
|
alternateClassName: 'Ext.layout.FitLayout',
|
|
requires: ['Ext.layout.container.Box'],
|
|
|
|
|
|
|
|
|
|
defaultMargins: {
|
|
top: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
left: 0
|
|
},
|
|
|
|
|
|
onLayout : function() {
|
|
var me = this,
|
|
size,
|
|
item,
|
|
margins;
|
|
me.callParent();
|
|
|
|
if (me.owner.items.length) {
|
|
item = me.owner.items.get(0);
|
|
margins = item.margins || me.defaultMargins;
|
|
size = me.getLayoutTargetSize();
|
|
size.width -= margins.width;
|
|
size.height -= margins.height;
|
|
me.setItemBox(item, size);
|
|
|
|
|
|
|
|
if (margins.left || margins.top) {
|
|
item.setPosition(margins.left, margins.top);
|
|
}
|
|
}
|
|
},
|
|
|
|
getTargetBox : function() {
|
|
return this.getLayoutTargetSize();
|
|
},
|
|
|
|
setItemBox : function(item, box) {
|
|
var me = this;
|
|
if (item && box.height > 0) {
|
|
if (!me.owner.isFixedWidth()) {
|
|
box.width = undefined;
|
|
}
|
|
if (!me.owner.isFixedHeight()) {
|
|
box.height = undefined;
|
|
}
|
|
me.setItemSize(item, box.width, box.height);
|
|
}
|
|
},
|
|
|
|
configureItem: function(item) {
|
|
|
|
|
|
|
|
item.layoutManagedHeight = 0;
|
|
item.layoutManagedWidth = 0;
|
|
|
|
this.callParent(arguments);
|
|
}
|
|
}, function() {
|
|
|
|
|
|
this.prototype.renderItem = Ext.layout.container.Box.prototype.renderItem;
|
|
});
|
|
|
|
Ext.define('Ext.layout.container.AbstractCard', {
|
|
|
|
|
|
|
|
extend: 'Ext.layout.container.Fit',
|
|
|
|
|
|
|
|
type: 'card',
|
|
|
|
sizeAllCards: false,
|
|
|
|
hideInactive: true,
|
|
|
|
|
|
deferredRender : false,
|
|
|
|
beforeLayout: function() {
|
|
var me = this;
|
|
me.getActiveItem();
|
|
if (me.activeItem && me.deferredRender) {
|
|
me.renderItems([me.activeItem], me.getRenderTarget());
|
|
return true;
|
|
}
|
|
else {
|
|
return this.callParent(arguments);
|
|
}
|
|
},
|
|
|
|
renderChildren: function () {
|
|
if (!this.deferredRender) {
|
|
this.getActiveItem();
|
|
this.callParent();
|
|
}
|
|
},
|
|
|
|
onLayout: function() {
|
|
var me = this,
|
|
activeItem = me.activeItem,
|
|
items = me.getVisibleItems(),
|
|
ln = items.length,
|
|
targetBox = me.getTargetBox(),
|
|
i, item;
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
item = items[i];
|
|
me.setItemBox(item, targetBox);
|
|
}
|
|
|
|
if (!me.firstActivated && activeItem) {
|
|
if (activeItem.fireEvent('beforeactivate', activeItem) !== false) {
|
|
activeItem.fireEvent('activate', activeItem);
|
|
}
|
|
me.firstActivated = true;
|
|
}
|
|
},
|
|
|
|
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;
|
|
if (!me.activeItem && me.owner) {
|
|
me.activeItem = me.parseActiveItem(me.owner.activeItem);
|
|
}
|
|
|
|
if (me.activeItem && me.owner.items.indexOf(me.activeItem) != -1) {
|
|
return me.activeItem;
|
|
}
|
|
|
|
return null;
|
|
},
|
|
|
|
|
|
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, position) {
|
|
this.callParent([item, position]);
|
|
if (this.hideInactive && this.activeItem !== item) {
|
|
item.hide();
|
|
}
|
|
else {
|
|
item.show();
|
|
}
|
|
},
|
|
|
|
onRemove: function(component) {
|
|
if (component === this.activeItem) {
|
|
this.activeItem = null;
|
|
if (this.owner.items.getCount() === 0) {
|
|
this.firstActivated = false;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getAnimation: function(newCard, owner) {
|
|
var newAnim = (newCard || {}).cardSwitchAnimation;
|
|
if (newAnim === false) {
|
|
return false;
|
|
}
|
|
return newAnim || owner.cardSwitchAnimation;
|
|
},
|
|
|
|
|
|
getNext: function() {
|
|
|
|
|
|
var wrap = arguments[0];
|
|
var 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];
|
|
var 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);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.selection.Model', {
|
|
extend: 'Ext.util.Observable',
|
|
alternateClassName: 'Ext.AbstractSelectionModel',
|
|
requires: ['Ext.data.StoreManager'],
|
|
|
|
|
|
|
|
|
|
|
|
allowDeselect: false,
|
|
|
|
|
|
selected: null,
|
|
|
|
|
|
pruneRemoved: true,
|
|
|
|
constructor: function(cfg) {
|
|
var me = this;
|
|
|
|
cfg = cfg || {};
|
|
Ext.apply(me, cfg);
|
|
|
|
me.addEvents(
|
|
|
|
'selectionchange'
|
|
);
|
|
|
|
me.modes = {
|
|
SINGLE: true,
|
|
SIMPLE: true,
|
|
MULTI: true
|
|
};
|
|
|
|
|
|
me.setSelectionMode(cfg.mode || me.mode);
|
|
|
|
|
|
me.selected = Ext.create('Ext.util.MixedCollection');
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
bind : function(store, initial){
|
|
var me = this;
|
|
|
|
if(!initial && me.store){
|
|
if(store !== me.store && me.store.autoDestroy){
|
|
me.store.destroyStore();
|
|
}else{
|
|
me.store.un("add", me.onStoreAdd, me);
|
|
me.store.un("clear", me.onStoreClear, me);
|
|
me.store.un("remove", me.onStoreRemove, me);
|
|
me.store.un("update", me.onStoreUpdate, me);
|
|
}
|
|
}
|
|
if(store){
|
|
store = Ext.data.StoreManager.lookup(store);
|
|
store.on({
|
|
add: me.onStoreAdd,
|
|
clear: me.onStoreClear,
|
|
remove: me.onStoreRemove,
|
|
update: me.onStoreUpdate,
|
|
scope: me
|
|
});
|
|
}
|
|
me.store = store;
|
|
if(store && !initial) {
|
|
me.refresh();
|
|
}
|
|
},
|
|
|
|
|
|
selectAll: function(suppressEvent) {
|
|
var me = this,
|
|
selections = me.store.getRange(),
|
|
i = 0,
|
|
len = selections.length,
|
|
start = me.getSelection().length;
|
|
|
|
me.bulkChange = true;
|
|
for (; i < len; i++) {
|
|
me.doSelect(selections[i], true, suppressEvent);
|
|
}
|
|
delete me.bulkChange;
|
|
|
|
me.maybeFireSelectionChange(me.getSelection().length !== start);
|
|
},
|
|
|
|
|
|
deselectAll: function(suppressEvent) {
|
|
var me = this,
|
|
selections = me.getSelection(),
|
|
i = 0,
|
|
len = selections.length,
|
|
start = me.getSelection().length;
|
|
|
|
me.bulkChange = true;
|
|
for (; i < len; i++) {
|
|
me.doDeselect(selections[i], suppressEvent);
|
|
}
|
|
delete me.bulkChange;
|
|
|
|
me.maybeFireSelectionChange(me.getSelection().length !== start);
|
|
},
|
|
|
|
|
|
|
|
|
|
selectWithEvent: function(record, e, keepExisting) {
|
|
var me = this;
|
|
|
|
switch (me.selectionMode) {
|
|
case 'MULTI':
|
|
if (e.ctrlKey && me.isSelected(record)) {
|
|
me.doDeselect(record, false);
|
|
} else if (e.shiftKey && me.lastFocused) {
|
|
me.selectRange(me.lastFocused, record, e.ctrlKey);
|
|
} else if (e.ctrlKey) {
|
|
me.doSelect(record, true, false);
|
|
} else if (me.isSelected(record) && !e.shiftKey && !e.ctrlKey && me.selected.getCount() > 1) {
|
|
me.doSelect(record, keepExisting, false);
|
|
} else {
|
|
me.doSelect(record, false);
|
|
}
|
|
break;
|
|
case 'SIMPLE':
|
|
if (me.isSelected(record)) {
|
|
me.doDeselect(record);
|
|
} else {
|
|
me.doSelect(record, true);
|
|
}
|
|
break;
|
|
case 'SINGLE':
|
|
|
|
if (me.allowDeselect && me.isSelected(record)) {
|
|
me.doDeselect(record);
|
|
|
|
} else {
|
|
me.doSelect(record, false);
|
|
}
|
|
break;
|
|
}
|
|
},
|
|
|
|
|
|
selectRange : function(startRow, endRow, keepExisting, dir){
|
|
var me = this,
|
|
store = me.store,
|
|
selectedCount = 0,
|
|
i,
|
|
tmp,
|
|
dontDeselect,
|
|
records = [];
|
|
|
|
if (me.isLocked()){
|
|
return;
|
|
}
|
|
|
|
if (!keepExisting) {
|
|
me.deselectAll(true);
|
|
}
|
|
|
|
if (!Ext.isNumber(startRow)) {
|
|
startRow = store.indexOf(startRow);
|
|
}
|
|
if (!Ext.isNumber(endRow)) {
|
|
endRow = store.indexOf(endRow);
|
|
}
|
|
|
|
|
|
if (startRow > endRow){
|
|
tmp = endRow;
|
|
endRow = startRow;
|
|
startRow = tmp;
|
|
}
|
|
|
|
for (i = startRow; i <= endRow; i++) {
|
|
if (me.isSelected(store.getAt(i))) {
|
|
selectedCount++;
|
|
}
|
|
}
|
|
|
|
if (!dir) {
|
|
dontDeselect = -1;
|
|
} else {
|
|
dontDeselect = (dir == 'up') ? startRow : endRow;
|
|
}
|
|
|
|
for (i = startRow; i <= endRow; i++){
|
|
if (selectedCount == (endRow - startRow + 1)) {
|
|
if (i != dontDeselect) {
|
|
me.doDeselect(i, true);
|
|
}
|
|
} else {
|
|
records.push(store.getAt(i));
|
|
}
|
|
}
|
|
me.doMultiSelect(records, true);
|
|
},
|
|
|
|
|
|
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) {
|
|
return;
|
|
}
|
|
if (typeof records === "number") {
|
|
records = [me.store.getAt(records)];
|
|
}
|
|
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,
|
|
i = 0,
|
|
len, record;
|
|
|
|
if (me.locked) {
|
|
return;
|
|
}
|
|
|
|
|
|
records = !Ext.isArray(records) ? [records] : records;
|
|
len = records.length;
|
|
if (!keepExisting && selected.getCount() > 0) {
|
|
if (me.doDeselect(me.getSelection(), suppressEvent) === false) {
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
function commit () {
|
|
selected.add(record);
|
|
change = true;
|
|
}
|
|
|
|
for (; i < len; i++) {
|
|
record = records[i];
|
|
if (keepExisting && me.isSelected(record)) {
|
|
continue;
|
|
}
|
|
me.lastSelected = record;
|
|
|
|
me.onSelectChange(record, true, suppressEvent, commit);
|
|
}
|
|
me.setLastFocused(record, suppressEvent);
|
|
|
|
me.maybeFireSelectionChange(change && !suppressEvent);
|
|
},
|
|
|
|
|
|
doDeselect: function(records, suppressEvent) {
|
|
var me = this,
|
|
selected = me.selected,
|
|
i = 0,
|
|
len, record,
|
|
attempted = 0,
|
|
accepted = 0;
|
|
|
|
if (me.locked) {
|
|
return false;
|
|
}
|
|
|
|
if (typeof records === "number") {
|
|
records = [me.store.getAt(records)];
|
|
} else if (!Ext.isArray(records)) {
|
|
records = [records];
|
|
}
|
|
|
|
function commit () {
|
|
++accepted;
|
|
selected.remove(record);
|
|
}
|
|
|
|
len = records.length;
|
|
|
|
for (; i < len; i++) {
|
|
record = records[i];
|
|
if (me.isSelected(record)) {
|
|
if (me.lastSelected == record) {
|
|
me.lastSelected = selected.last();
|
|
}
|
|
++attempted;
|
|
me.onSelectChange(record, false, suppressEvent, commit);
|
|
}
|
|
}
|
|
|
|
|
|
me.maybeFireSelectionChange(accepted > 0 && !suppressEvent);
|
|
return accepted === attempted;
|
|
},
|
|
|
|
doSingleSelect: function(record, suppressEvent) {
|
|
var me = this,
|
|
changed = false,
|
|
selected = me.selected;
|
|
|
|
if (me.locked) {
|
|
return;
|
|
}
|
|
|
|
|
|
if (me.isSelected(record)) {
|
|
return;
|
|
}
|
|
|
|
function commit () {
|
|
me.bulkChange = true;
|
|
if (selected.getCount() > 0 && me.doDeselect(me.lastSelected, suppressEvent) === false) {
|
|
delete me.bulkChange;
|
|
return false;
|
|
}
|
|
delete me.bulkChange;
|
|
|
|
selected.add(record);
|
|
me.lastSelected = record;
|
|
changed = true;
|
|
}
|
|
|
|
me.onSelectChange(record, true, suppressEvent, commit);
|
|
|
|
if (changed) {
|
|
if (!suppressEvent) {
|
|
me.setLastFocused(record);
|
|
}
|
|
me.maybeFireSelectionChange(!suppressEvent);
|
|
}
|
|
},
|
|
|
|
|
|
setLastFocused: function(record, supressFocus) {
|
|
var me = this,
|
|
recordBeforeLast = me.lastFocused;
|
|
me.lastFocused = record;
|
|
me.onLastFocusChanged(recordBeforeLast, record, supressFocus);
|
|
},
|
|
|
|
|
|
isFocused: function(record) {
|
|
return record === this.getLastFocused();
|
|
},
|
|
|
|
|
|
|
|
|
|
maybeFireSelectionChange: function(fireEvent) {
|
|
var me = this;
|
|
if (fireEvent && !me.bulkChange) {
|
|
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;
|
|
},
|
|
|
|
|
|
isSelected: function(record) {
|
|
record = Ext.isNumber(record) ? this.store.getAt(record) : record;
|
|
return this.selected.indexOf(record) !== -1;
|
|
},
|
|
|
|
|
|
hasSelection: function() {
|
|
return this.selected.getCount() > 0;
|
|
},
|
|
|
|
refresh: function() {
|
|
var me = this,
|
|
toBeSelected = [],
|
|
oldSelections = me.getSelection(),
|
|
len = oldSelections.length,
|
|
selection,
|
|
change,
|
|
i = 0,
|
|
lastFocused = this.getLastFocused();
|
|
|
|
|
|
|
|
|
|
for (; i < len; i++) {
|
|
selection = oldSelections[i];
|
|
if (!this.pruneRemoved || me.store.indexOf(selection) !== -1) {
|
|
toBeSelected.push(selection);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (me.selected.getCount() != toBeSelected.length) {
|
|
change = true;
|
|
}
|
|
|
|
me.clearSelections();
|
|
|
|
if (me.store.indexOf(lastFocused) !== -1) {
|
|
|
|
this.setLastFocused(lastFocused, true);
|
|
}
|
|
|
|
if (toBeSelected.length) {
|
|
|
|
me.doSelect(toBeSelected, false, true);
|
|
}
|
|
|
|
me.maybeFireSelectionChange(change);
|
|
},
|
|
|
|
|
|
clearSelections: function() {
|
|
|
|
this.selected.clear();
|
|
this.lastSelected = null;
|
|
this.setLastFocused(null);
|
|
},
|
|
|
|
|
|
onStoreAdd: function() {
|
|
|
|
},
|
|
|
|
|
|
|
|
onStoreClear: function() {
|
|
if (this.selected.getCount > 0) {
|
|
this.clearSelections();
|
|
this.maybeFireSelectionChange(true);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
onStoreRemove: function(store, record) {
|
|
var me = this,
|
|
selected = me.selected;
|
|
|
|
if (me.locked || !me.pruneRemoved) {
|
|
return;
|
|
}
|
|
|
|
if (selected.remove(record)) {
|
|
if (me.lastSelected == record) {
|
|
me.lastSelected = null;
|
|
}
|
|
if (me.getLastFocused() == record) {
|
|
me.setLastFocused(null);
|
|
}
|
|
me.maybeFireSelectionChange(true);
|
|
}
|
|
},
|
|
|
|
|
|
getCount: function() {
|
|
return this.selected.getCount();
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
|
|
},
|
|
|
|
|
|
onStoreUpdate: function() {
|
|
|
|
},
|
|
|
|
|
|
onSelectChange: function(record, isSelected, suppressEvent) {
|
|
|
|
},
|
|
|
|
|
|
onLastFocusChanged: function(oldFocused, newFocused) {
|
|
|
|
},
|
|
|
|
|
|
onEditorKey: function(field, e) {
|
|
|
|
},
|
|
|
|
|
|
bindComponent: function(cmp) {
|
|
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.selection.DataViewModel', {
|
|
extend: 'Ext.selection.Model',
|
|
|
|
requires: ['Ext.util.KeyNav'],
|
|
|
|
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.bind(view.getStore());
|
|
|
|
view.on(view.triggerEvent, me.onItemClick, me);
|
|
view.on(view.triggerCtEvent, me.onContainerClick, me);
|
|
|
|
view.on(eventListeners);
|
|
|
|
if (me.enableKeyNav) {
|
|
me.initKeyNav(view);
|
|
}
|
|
},
|
|
|
|
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], 0), me, {single: true});
|
|
return;
|
|
}
|
|
|
|
view.el.set({
|
|
tabIndex: -1
|
|
});
|
|
me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
|
|
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 (isSelected) {
|
|
view.onItemSelect(record);
|
|
} else {
|
|
view.onItemDeselect(record);
|
|
}
|
|
|
|
if (!suppressEvent) {
|
|
me.fireEvent(eventName, me, record);
|
|
}
|
|
}
|
|
},
|
|
|
|
destroy: function(){
|
|
Ext.destroy(this.keyNav);
|
|
this.callParent();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.state.CookieProvider', {
|
|
extend: 'Ext.state.Provider',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor : function(config){
|
|
var me = this;
|
|
me.path = "/";
|
|
me.expires = new Date(new Date().getTime()+(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.state.LocalStorageProvider', {
|
|
|
|
|
|
extend: 'Ext.state.Provider',
|
|
|
|
alias: 'state.localstorage',
|
|
|
|
|
|
|
|
constructor: function(){
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
me.store = me.getStorageObject();
|
|
me.state = me.readLocalStorage();
|
|
},
|
|
|
|
readLocalStorage: function(){
|
|
var store = this.store,
|
|
i = 0,
|
|
len = store.length,
|
|
prefix = this.prefix,
|
|
prefixLen = prefix.length,
|
|
data = {},
|
|
key;
|
|
|
|
for (; i < len; ++i) {
|
|
key = store.key(i);
|
|
if (key.substring(0, prefixLen) == prefix) {
|
|
data[key.substr(prefixLen)] = this.decodeValue(store.getItem(key));
|
|
}
|
|
}
|
|
return data;
|
|
},
|
|
|
|
set : function(name, value){
|
|
var me = this;
|
|
|
|
me.clear(name);
|
|
if (typeof value == "undefined" || value === null) {
|
|
return;
|
|
}
|
|
me.store.setItem(me.prefix + name, me.encodeValue(value));
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
clear : function(name){
|
|
this.store.removeItem(this.prefix + name);
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
getStorageObject: function(){
|
|
try {
|
|
var supports = 'localStorage' in window && window['localStorage'] !== null;
|
|
if (supports) {
|
|
return window.localStorage;
|
|
}
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.util.Point', {
|
|
|
|
|
|
extend: 'Ext.util.Region',
|
|
|
|
statics: {
|
|
|
|
|
|
fromEvent: function(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);
|
|
},
|
|
|
|
|
|
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.LoadMask', {
|
|
|
|
extend: 'Ext.Component',
|
|
|
|
alias: 'widget.loadmask',
|
|
|
|
|
|
|
|
mixins: {
|
|
floating: 'Ext.util.Floating'
|
|
},
|
|
|
|
uses: ['Ext.data.StoreManager'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
msg : 'Loading...',
|
|
|
|
msgCls : Ext.baseCSSPrefix + 'mask-loading',
|
|
|
|
|
|
useMsg: true,
|
|
|
|
|
|
disabled: false,
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'mask-msg',
|
|
|
|
renderTpl: '<div style="position:relative" class="{msgCls}"></div>',
|
|
|
|
|
|
modal: true,
|
|
|
|
|
|
floating: {
|
|
shadow: 'frame'
|
|
},
|
|
|
|
|
|
focusOnToFront: false,
|
|
|
|
|
|
constructor : function(el, config) {
|
|
var me = this;
|
|
|
|
|
|
if (el.isComponent) {
|
|
me.ownerCt = el;
|
|
me.bindComponent(el);
|
|
}
|
|
|
|
else {
|
|
me.ownerCt = new Ext.Component({
|
|
el: Ext.get(el),
|
|
rendered: true,
|
|
componentLayoutCounter: 1
|
|
});
|
|
me.container = el;
|
|
}
|
|
me.callParent([config]);
|
|
|
|
if (me.store) {
|
|
me.bindStore(me.store, true);
|
|
}
|
|
me.renderData = {
|
|
msgCls: me.msgCls
|
|
};
|
|
me.renderSelectors = {
|
|
msgEl: 'div'
|
|
};
|
|
},
|
|
|
|
bindComponent: function(comp) {
|
|
this.mon(comp, {
|
|
resize: this.onComponentResize,
|
|
scope: this
|
|
});
|
|
},
|
|
|
|
afterRender: function() {
|
|
this.callParent(arguments);
|
|
this.container = this.floatParent.getContentTarget();
|
|
},
|
|
|
|
|
|
onComponentResize: function() {
|
|
var me = this;
|
|
if (me.rendered && me.isVisible()) {
|
|
me.toFront();
|
|
me.center();
|
|
}
|
|
},
|
|
|
|
|
|
bindStore : function(store, initial) {
|
|
var me = this;
|
|
|
|
if (!initial && me.store) {
|
|
me.mun(me.store, {
|
|
scope: me,
|
|
beforeload: me.onBeforeLoad,
|
|
load: me.onLoad,
|
|
exception: me.onLoad
|
|
});
|
|
if (!store) {
|
|
me.store = null;
|
|
}
|
|
}
|
|
if (store) {
|
|
store = Ext.data.StoreManager.lookup(store);
|
|
me.mon(store, {
|
|
scope: me,
|
|
beforeload: me.onBeforeLoad,
|
|
load: me.onLoad,
|
|
exception: me.onLoad
|
|
});
|
|
|
|
}
|
|
me.store = store;
|
|
if (store && store.isLoading()) {
|
|
me.onBeforeLoad();
|
|
}
|
|
},
|
|
|
|
onDisable : function() {
|
|
this.callParent(arguments);
|
|
if (this.loading) {
|
|
this.onLoad();
|
|
}
|
|
},
|
|
|
|
|
|
onBeforeLoad : function() {
|
|
var me = this,
|
|
owner = me.ownerCt || me.floatParent,
|
|
origin;
|
|
if (!this.disabled) {
|
|
|
|
|
|
if (owner.componentLayoutCounter) {
|
|
Ext.Component.prototype.show.call(me);
|
|
} else {
|
|
|
|
origin = owner.afterComponentLayout;
|
|
owner.afterComponentLayout = function() {
|
|
owner.afterComponentLayout = origin;
|
|
origin.apply(owner, arguments);
|
|
if(me.loading) {
|
|
Ext.Component.prototype.show.call(me);
|
|
}
|
|
};
|
|
}
|
|
}
|
|
},
|
|
|
|
onHide: function(){
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
me.showOnParentShow = true;
|
|
},
|
|
|
|
onShow: function() {
|
|
var me = this,
|
|
msgEl = me.msgEl;
|
|
|
|
me.callParent(arguments);
|
|
me.loading = true;
|
|
if (me.useMsg) {
|
|
msgEl.show().update(me.msg);
|
|
} else {
|
|
msgEl.parent().hide();
|
|
}
|
|
},
|
|
|
|
afterShow: function() {
|
|
this.callParent(arguments);
|
|
this.center();
|
|
},
|
|
|
|
|
|
onLoad : function() {
|
|
this.loading = false;
|
|
Ext.Component.prototype.hide.call(this);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.view.AbstractView', {
|
|
extend: 'Ext.Component',
|
|
alternateClassName: 'Ext.view.AbstractView',
|
|
requires: [
|
|
'Ext.LoadMask',
|
|
'Ext.data.StoreManager',
|
|
'Ext.CompositeElementLite',
|
|
'Ext.DomQuery',
|
|
'Ext.selection.DataViewModel'
|
|
],
|
|
|
|
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,
|
|
|
|
|
|
|
|
|
|
|
|
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('<tpl for="."><div class="{0}">{1}</div></tpl>', me.itemCls, itemTpl);
|
|
me.tpl = Ext.create('Ext.XTemplate', itemTpl, memberFn);
|
|
}
|
|
|
|
|
|
me.callParent();
|
|
if(Ext.isString(me.tpl) || Ext.isArray(me.tpl)){
|
|
me.tpl = Ext.create('Ext.XTemplate', me.tpl);
|
|
}
|
|
|
|
|
|
me.addEvents(
|
|
|
|
'beforerefresh',
|
|
|
|
'refresh',
|
|
|
|
'viewready',
|
|
|
|
'itemupdate',
|
|
|
|
'itemadd',
|
|
|
|
'itemremove'
|
|
);
|
|
|
|
me.addCmpEvents();
|
|
|
|
|
|
me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store');
|
|
me.all = new Ext.CompositeElementLite();
|
|
},
|
|
|
|
onRender: function() {
|
|
var me = this,
|
|
mask = me.loadMask,
|
|
cfg = {
|
|
msg: me.loadingText,
|
|
msgCls: me.loadingCls,
|
|
useMsg: me.loadingUseMsg
|
|
};
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (mask) {
|
|
|
|
if (Ext.isObject(mask)) {
|
|
cfg = Ext.apply(cfg, mask);
|
|
}
|
|
|
|
|
|
|
|
|
|
me.loadMask = Ext.create('Ext.LoadMask', me, cfg);
|
|
me.loadMask.on({
|
|
scope: me,
|
|
beforeshow: me.onMaskBeforeShow,
|
|
hide: me.onMaskHide
|
|
});
|
|
}
|
|
},
|
|
|
|
onMaskBeforeShow: function(){
|
|
var loadingHeight = this.loadingHeight;
|
|
|
|
this.getSelectionModel().deselectAll();
|
|
if (loadingHeight) {
|
|
this.setCalculatedSize(undefined, loadingHeight);
|
|
}
|
|
},
|
|
|
|
onMaskHide: function(){
|
|
var me = this;
|
|
|
|
if (!me.destroying && me.loadingHeight) {
|
|
me.setHeight(me.height);
|
|
}
|
|
},
|
|
|
|
afterRender: function() {
|
|
this.callParent(arguments);
|
|
|
|
|
|
|
|
|
|
this.getSelectionModel().bindComponent(this);
|
|
},
|
|
|
|
|
|
getSelectionModel: function(){
|
|
var me = this,
|
|
mode = 'SINGLE';
|
|
|
|
if (!me.selModel) {
|
|
me.selModel = {};
|
|
}
|
|
|
|
if (me.simpleSelect) {
|
|
mode = 'SIMPLE';
|
|
} else if (me.multiSelect) {
|
|
mode = 'MULTI';
|
|
}
|
|
|
|
Ext.applyIf(me.selModel, {
|
|
allowDeselect: me.allowDeselect,
|
|
mode: mode
|
|
});
|
|
|
|
if (!me.selModel.events) {
|
|
me.selModel = Ext.create('Ext.selection.DataViewModel', me.selModel);
|
|
}
|
|
|
|
if (!me.selModel.hasRelaySetup) {
|
|
me.relayEvents(me.selModel, [
|
|
'selectionchange', 'beforeselect', 'beforedeselect', 'select', 'deselect'
|
|
]);
|
|
me.selModel.hasRelaySetup = true;
|
|
}
|
|
|
|
|
|
|
|
if (me.disableSelection) {
|
|
me.selModel.locked = true;
|
|
}
|
|
|
|
return me.selModel;
|
|
},
|
|
|
|
|
|
refresh: function() {
|
|
var me = this,
|
|
el,
|
|
records;
|
|
|
|
if (!me.rendered || me.isDestroyed) {
|
|
return;
|
|
}
|
|
|
|
me.fireEvent('beforerefresh', me);
|
|
el = me.getTargetEl();
|
|
records = me.store.getRange();
|
|
|
|
el.update('');
|
|
if (records.length < 1) {
|
|
if (!me.deferEmptyText || me.hasSkippedEmptyText) {
|
|
el.update(me.emptyText);
|
|
}
|
|
me.all.clear();
|
|
} else {
|
|
me.tpl.overwrite(el, me.collectData(records, 0));
|
|
me.all.fill(Ext.query(me.getItemSelector(), el.dom));
|
|
me.updateIndexes(0);
|
|
}
|
|
|
|
me.selModel.refresh();
|
|
me.hasSkippedEmptyText = true;
|
|
me.fireEvent('refresh', me);
|
|
|
|
|
|
|
|
if (!me.viewReady) {
|
|
|
|
|
|
me.viewReady = true;
|
|
me.fireEvent('viewready', me);
|
|
}
|
|
},
|
|
|
|
|
|
prepareData: function(data, index, record) {
|
|
if (record) {
|
|
Ext.apply(data, record.getAssociatedData());
|
|
}
|
|
return data;
|
|
},
|
|
|
|
|
|
collectData : function(records, startIndex){
|
|
var r = [],
|
|
i = 0,
|
|
len = records.length,
|
|
record;
|
|
|
|
for(; i < len; i++){
|
|
record = records[i];
|
|
r[r.length] = this.prepareData(record[record.persistenceProperty], startIndex + i, record);
|
|
}
|
|
return r;
|
|
},
|
|
|
|
|
|
bufferRender : function(records, index){
|
|
var div = document.createElement('div');
|
|
this.tpl.overwrite(div, this.collectData(records, index));
|
|
return Ext.query(this.getItemSelector(), div);
|
|
},
|
|
|
|
|
|
onUpdate : function(ds, record){
|
|
var me = this,
|
|
index = me.store.indexOf(record),
|
|
node;
|
|
|
|
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.refresh();
|
|
me.fireEvent('itemupdate', record, index, node);
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
|
|
onAdd : function(ds, records, index) {
|
|
var me = this,
|
|
nodes;
|
|
|
|
if (me.all.getCount() === 0) {
|
|
me.refresh();
|
|
return;
|
|
}
|
|
|
|
nodes = me.bufferRender(records, index);
|
|
me.doAdd(nodes, records, index);
|
|
|
|
me.selModel.refresh();
|
|
me.updateIndexes(index);
|
|
me.fireEvent('itemadd', records, index, nodes);
|
|
},
|
|
|
|
doAdd: function(nodes, records, index) {
|
|
var all = this.all;
|
|
|
|
if (index < all.getCount()) {
|
|
all.item(index).insertSibling(nodes, 'before', true);
|
|
} else {
|
|
all.last().insertSibling(nodes, 'after', true);
|
|
}
|
|
|
|
Ext.Array.insert(all.elements, index, nodes);
|
|
},
|
|
|
|
|
|
onRemove : function(ds, record, index) {
|
|
var me = this;
|
|
|
|
me.doRemove(record, index);
|
|
me.updateIndexes(index);
|
|
if (me.store.getCount() === 0){
|
|
me.refresh();
|
|
}
|
|
me.fireEvent('itemremove', record, index);
|
|
},
|
|
|
|
doRemove: function(record, index) {
|
|
this.all.removeElement(index, true);
|
|
},
|
|
|
|
|
|
refreshNode : function(index){
|
|
this.onUpdate(this.store, this.store.getAt(index));
|
|
},
|
|
|
|
|
|
updateIndexes : function(startIndex, endIndex) {
|
|
var ns = this.all.elements,
|
|
records = this.store.getRange(),
|
|
i;
|
|
|
|
startIndex = startIndex || 0;
|
|
endIndex = endIndex || ((endIndex === 0) ? 0 : (ns.length - 1));
|
|
for(i = startIndex; i <= endIndex; i++){
|
|
ns[i].viewIndex = i;
|
|
ns[i].viewRecordId = records[i].internalId;
|
|
if (!ns[i].boundView) {
|
|
ns[i].boundView = this.id;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getStore : function(){
|
|
return this.store;
|
|
},
|
|
|
|
|
|
bindStore : function(store, initial) {
|
|
var me = this,
|
|
maskStore;
|
|
|
|
if (!initial && me.store) {
|
|
if (store !== me.store && me.store.autoDestroy) {
|
|
me.store.destroyStore();
|
|
}
|
|
else {
|
|
me.mun(me.store, {
|
|
scope: me,
|
|
datachanged: me.onDataChanged,
|
|
add: me.onAdd,
|
|
remove: me.onRemove,
|
|
update: me.onUpdate,
|
|
clear: me.refresh
|
|
});
|
|
}
|
|
if (!store) {
|
|
|
|
if (me.loadMask && me.loadMask.bindStore) {
|
|
me.loadMask.bindStore(null);
|
|
}
|
|
me.store = null;
|
|
}
|
|
}
|
|
if (store) {
|
|
store = Ext.data.StoreManager.lookup(store);
|
|
me.mon(store, {
|
|
scope: me,
|
|
datachanged: me.onDataChanged,
|
|
add: me.onAdd,
|
|
remove: me.onRemove,
|
|
update: me.onUpdate,
|
|
clear: me.refresh
|
|
});
|
|
|
|
if (me.loadMask && me.loadMask.bindStore) {
|
|
|
|
if (Ext.Array.contains(store.alias, 'store.node')) {
|
|
maskStore = this.ownerCt.store;
|
|
} else {
|
|
maskStore = store;
|
|
}
|
|
me.loadMask.bindStore(maskStore);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
me.viewReady = false;
|
|
|
|
me.store = store;
|
|
|
|
me.getSelectionModel().bind(store);
|
|
|
|
|
|
if (store) {
|
|
if (initial && me.deferInitialRefresh) {
|
|
Ext.Function.defer(function () {
|
|
if (!me.isDestroyed) {
|
|
me.refresh(true);
|
|
}
|
|
}, 1);
|
|
} else {
|
|
me.refresh(true);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onDataChanged: function() {
|
|
if (this.blockRefresh !== true) {
|
|
this.refresh.apply(this, arguments);
|
|
}
|
|
},
|
|
|
|
|
|
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.store.data;
|
|
|
|
for (; i < len; i++) {
|
|
records[records.length] = data.getByKey(nodes[i].viewRecordId);
|
|
}
|
|
|
|
return records;
|
|
},
|
|
|
|
|
|
getRecord: function(node){
|
|
return this.store.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 (!this.rendered) {
|
|
return null;
|
|
}
|
|
if (Ext.isString(nodeInfo)) {
|
|
return document.getElementById(nodeInfo);
|
|
}
|
|
if (Ext.isNumber(nodeInfo)) {
|
|
return this.all.elements[nodeInfo];
|
|
}
|
|
if (nodeInfo instanceof Ext.data.Model) {
|
|
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 ns = this.all.elements,
|
|
nodes = [],
|
|
i;
|
|
|
|
start = start || 0;
|
|
end = !Ext.isDefined(end) ? Math.max(ns.length - 1, 0) : end;
|
|
if (start <= end) {
|
|
for (i = start; i <= end && ns[i]; i++) {
|
|
nodes.push(ns[i]);
|
|
}
|
|
} else {
|
|
for (i = start; i >= end && ns[i]; i--) {
|
|
nodes.push(ns[i]);
|
|
}
|
|
}
|
|
return nodes;
|
|
},
|
|
|
|
|
|
indexOf: function(node) {
|
|
node = this.getNode(node);
|
|
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.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;
|
|
|
|
for(; i < len; i++){
|
|
items[i][fnName].apply(items[i], args);
|
|
}
|
|
},
|
|
|
|
|
|
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.layout.component.Editor', {
|
|
|
|
|
|
|
|
alias: ['layout.editor'],
|
|
|
|
extend: 'Ext.layout.component.Component',
|
|
|
|
|
|
|
|
onLayout: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
autoSize = owner.autoSize;
|
|
|
|
if (autoSize === true) {
|
|
autoSize = {
|
|
width: 'field',
|
|
height: 'field'
|
|
};
|
|
}
|
|
|
|
if (autoSize) {
|
|
width = me.getDimension(owner, autoSize.width, 'Width', width);
|
|
height = me.getDimension(owner, autoSize.height, 'Height', height);
|
|
}
|
|
me.setTargetSize(width, height);
|
|
owner.field.setSize(width, height);
|
|
},
|
|
|
|
getDimension: function(owner, type, dimension, actual){
|
|
var method = 'get' + dimension;
|
|
switch (type) {
|
|
case 'boundEl':
|
|
return owner.boundEl[method]();
|
|
case 'field':
|
|
return owner.field[method]();
|
|
default:
|
|
return actual;
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.Editor', {
|
|
|
|
|
|
|
|
extend: 'Ext.Component',
|
|
|
|
alias: 'widget.editor',
|
|
|
|
requires: ['Ext.layout.component.Editor'],
|
|
|
|
|
|
|
|
componentLayout: 'editor',
|
|
|
|
|
|
|
|
|
|
allowBlur: true,
|
|
|
|
|
|
|
|
|
|
revertInvalid: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
value : '',
|
|
|
|
|
|
alignment: 'c-c?',
|
|
|
|
|
|
offsets: [0, 0],
|
|
|
|
|
|
shadow : 'frame',
|
|
|
|
|
|
constrain : false,
|
|
|
|
|
|
swallowKeys : true,
|
|
|
|
|
|
completeOnEnter : true,
|
|
|
|
|
|
cancelOnEsc : true,
|
|
|
|
|
|
updateEl : false,
|
|
|
|
|
|
|
|
|
|
hidden: true,
|
|
baseCls: Ext.baseCSSPrefix + 'editor',
|
|
|
|
initComponent : function() {
|
|
var me = this,
|
|
field = me.field = Ext.ComponentManager.create(me.field, 'textfield');
|
|
|
|
Ext.apply(field, {
|
|
inEditor: true,
|
|
msgTarget: field.msgTarget == 'title' ? 'title' : 'qtip'
|
|
});
|
|
me.mon(field, {
|
|
scope: me,
|
|
blur: {
|
|
fn: me.onBlur,
|
|
|
|
delay: 1
|
|
},
|
|
specialkey: me.onSpecialKey
|
|
});
|
|
|
|
if (field.grow) {
|
|
me.mon(field, 'autosize', me.onAutoSize, me, {delay: 1});
|
|
}
|
|
me.floating = {
|
|
constrain: me.constrain
|
|
};
|
|
|
|
me.callParent(arguments);
|
|
|
|
me.addEvents(
|
|
|
|
'beforestartedit',
|
|
|
|
|
|
'startedit',
|
|
|
|
|
|
'beforecomplete',
|
|
|
|
'complete',
|
|
|
|
'canceledit',
|
|
|
|
'specialkey'
|
|
);
|
|
},
|
|
|
|
|
|
onAutoSize: function(){
|
|
this.doComponentLayout();
|
|
},
|
|
|
|
|
|
onRender : function(ct, position) {
|
|
var me = this,
|
|
field = me.field,
|
|
inputEl = field.inputEl;
|
|
|
|
me.callParent(arguments);
|
|
|
|
field.render(me.el);
|
|
|
|
|
|
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();
|
|
}
|
|
if (field.triggerBlur) {
|
|
field.triggerBlur();
|
|
}
|
|
}, 10);
|
|
}
|
|
|
|
this.fireEvent('specialkey', this, field, event);
|
|
},
|
|
|
|
|
|
startEdit : function(el, value) {
|
|
var me = this,
|
|
field = me.field;
|
|
|
|
me.completeEdit();
|
|
me.boundEl = Ext.get(el);
|
|
value = Ext.isDefined(value) ? value : me.boundEl.dom.innerHTML;
|
|
|
|
if (!me.rendered) {
|
|
me.render(me.parentEl || document.body);
|
|
}
|
|
|
|
if (me.fireEvent('beforestartedit', me, me.boundEl, value) !== false) {
|
|
me.startValue = value;
|
|
me.show();
|
|
field.reset();
|
|
field.setValue(value);
|
|
me.realign(true);
|
|
field.focus(false, 10);
|
|
if (field.autoSize) {
|
|
field.autoSize();
|
|
}
|
|
me.editing = true;
|
|
}
|
|
},
|
|
|
|
|
|
realign : function(autoSize) {
|
|
var me = this;
|
|
if (autoSize === true) {
|
|
me.doComponentLayout();
|
|
}
|
|
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.boundEl, me.startValue);
|
|
},
|
|
|
|
|
|
cancelEdit : function(remainVisible) {
|
|
var me = this,
|
|
startValue = me.startValue,
|
|
value;
|
|
|
|
if (me.editing) {
|
|
value = me.getValue();
|
|
me.setValue(startValue);
|
|
me.hideEdit(remainVisible);
|
|
me.fireEvent('canceledit', me, value, startValue);
|
|
}
|
|
},
|
|
|
|
|
|
hideEdit: function(remainVisible) {
|
|
if (remainVisible !== true) {
|
|
this.editing = false;
|
|
this.hide();
|
|
}
|
|
},
|
|
|
|
|
|
onBlur : function() {
|
|
var me = this;
|
|
|
|
|
|
if(me.allowBlur === true && me.editing && me.selectSameEditor !== true) {
|
|
me.completeEdit();
|
|
}
|
|
},
|
|
|
|
|
|
onHide : function() {
|
|
var me = this,
|
|
field = me.field;
|
|
|
|
if (me.editing) {
|
|
me.completeEdit();
|
|
return;
|
|
}
|
|
field.blur();
|
|
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.Img', {
|
|
extend: 'Ext.Component',
|
|
alias: ['widget.image', 'widget.imagecomponent'],
|
|
|
|
src: '',
|
|
|
|
getElConfig: function() {
|
|
return {
|
|
tag: 'img',
|
|
src: this.src
|
|
};
|
|
},
|
|
|
|
|
|
initRenderTpl: Ext.emptyFn,
|
|
|
|
|
|
setSrc: function(src) {
|
|
var me = this,
|
|
img = me.el;
|
|
me.src = src;
|
|
if (img) {
|
|
img.dom.src = src;
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.Layer', {
|
|
uses: ['Ext.Shadow'],
|
|
|
|
|
|
statics: {
|
|
shims: []
|
|
},
|
|
|
|
extend: 'Ext.Element',
|
|
|
|
|
|
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;
|
|
|
|
if (existingEl) {
|
|
me.dom = Ext.getDom(existingEl);
|
|
}
|
|
if (!me.dom) {
|
|
me.dom = dh.append(pel, config.dh || {
|
|
tag: 'div',
|
|
cls: Ext.baseCSSPrefix + 'layer'
|
|
});
|
|
} else {
|
|
me.addCls(Ext.baseCSSPrefix + 'layer');
|
|
if (!me.dom.parentNode) {
|
|
pel.appendChild(me.dom);
|
|
}
|
|
}
|
|
|
|
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.id) {
|
|
me.id = me.dom.id = config.id;
|
|
} else {
|
|
me.id = Ext.id(me.dom);
|
|
}
|
|
me.position('absolute');
|
|
if (config.shadow) {
|
|
me.shadowOffset = config.shadowOffset || 4;
|
|
me.shadow = Ext.create('Ext.Shadow', {
|
|
offset: me.shadowOffset,
|
|
mode: config.shadow
|
|
});
|
|
me.disableShadow();
|
|
} else {
|
|
me.shadowOffset = 0;
|
|
}
|
|
me.useShim = config.shim !== false && Ext.useShims;
|
|
if (config.hidden === true) {
|
|
me.hide();
|
|
} else {
|
|
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;
|
|
|
|
if (!me.updating && me.isVisible() && (shadow || me.useShim)) {
|
|
var shim = me.getShim(),
|
|
l = me.getLeft(true),
|
|
t = me.getTop(true),
|
|
w = me.dom.offsetWidth,
|
|
h = me.dom.offsetHeight,
|
|
shimIndex;
|
|
|
|
if (shadow && !me.shadowDisabled) {
|
|
if (doShow && !shadow.isVisible()) {
|
|
shadow.show(me);
|
|
} else {
|
|
shadow.realign(l, t, 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.setLeftTop(l, t);
|
|
}
|
|
}
|
|
} 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.setLeftTop(l, t);
|
|
}
|
|
}
|
|
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();
|
|
},
|
|
|
|
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);
|
|
},
|
|
|
|
setOpacity: function(opacity){
|
|
if (this.shadow) {
|
|
this.shadow.setOpacity(opacity);
|
|
}
|
|
return this.callParent(arguments);
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.layout.component.ProgressBar', {
|
|
|
|
|
|
|
|
alias: ['layout.progressbar'],
|
|
|
|
extend: 'Ext.layout.component.Component',
|
|
|
|
|
|
|
|
type: 'progressbar',
|
|
|
|
onLayout: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
textEl = owner.textEl;
|
|
|
|
me.setElementSize(owner.el, width, height);
|
|
textEl.setWidth(owner.el.getWidth(true));
|
|
|
|
me.callParent([width, height]);
|
|
|
|
owner.updateProgress(owner.value);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.ProgressBar', {
|
|
extend: 'Ext.Component',
|
|
alias: 'widget.progressbar',
|
|
|
|
requires: [
|
|
'Ext.Template',
|
|
'Ext.CompositeElement',
|
|
'Ext.TaskManager',
|
|
'Ext.layout.component.ProgressBar'
|
|
],
|
|
|
|
uses: ['Ext.fx.Anim'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'progress',
|
|
|
|
config: {
|
|
|
|
animate: false,
|
|
|
|
|
|
text: ''
|
|
},
|
|
|
|
|
|
waitTimer: null,
|
|
|
|
renderTpl: [
|
|
'<div class="{baseCls}-text {baseCls}-text-back">',
|
|
'<div> </div>',
|
|
'</div>',
|
|
'<div id="{id}-bar" class="{baseCls}-bar">',
|
|
'<div class="{baseCls}-text">',
|
|
'<div> </div>',
|
|
'</div>',
|
|
'</div>'
|
|
],
|
|
|
|
componentLayout: 'progressbar',
|
|
|
|
|
|
initComponent: function() {
|
|
this.callParent();
|
|
|
|
this.addChildEls('bar');
|
|
|
|
this.addEvents(
|
|
|
|
"update"
|
|
);
|
|
},
|
|
|
|
afterRender : function() {
|
|
var me = this;
|
|
|
|
|
|
|
|
me.textEl = me.textEl ? Ext.get(me.textEl) : me.el.select('.' + me.baseCls + '-text');
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (me.value) {
|
|
me.updateProgress(me.value, me.text);
|
|
}
|
|
else {
|
|
me.updateText(me.text);
|
|
}
|
|
},
|
|
|
|
|
|
updateProgress: function(value, text, animate) {
|
|
var me = this,
|
|
newWidth;
|
|
|
|
me.value = value || 0;
|
|
if (text) {
|
|
me.updateText(text);
|
|
}
|
|
if (me.rendered && !me.isDestroyed) {
|
|
if (me.isVisible(true)) {
|
|
newWidth = Math.floor(me.value * me.el.getWidth(true));
|
|
if (Ext.isForcedBorderBox) {
|
|
newWidth += me.bar.getBorderWidth("lr");
|
|
}
|
|
if (animate === true || (animate !== false && me.animate)) {
|
|
me.bar.stopAnimation();
|
|
me.bar.animate(Ext.apply({
|
|
to: {
|
|
width: newWidth + 'px'
|
|
}
|
|
}, me.animate));
|
|
} else {
|
|
me.bar.setWidth(newWidth);
|
|
}
|
|
} else {
|
|
|
|
me.doComponentLayout();
|
|
}
|
|
}
|
|
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);
|
|
},
|
|
|
|
|
|
wait: function(o) {
|
|
var me = this;
|
|
|
|
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;
|
|
|
|
me.clearTimer();
|
|
if (me.rendered) {
|
|
if (me.textEl.isComposite) {
|
|
me.textEl.clear();
|
|
}
|
|
Ext.destroyMembers(me, 'textEl', 'progressBar');
|
|
}
|
|
me.callParent();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.ShadowPool', {
|
|
singleton: true,
|
|
requires: ['Ext.DomHelper'],
|
|
|
|
markup: function() {
|
|
if (Ext.supports.CSS3BoxShadow) {
|
|
return '<div class="' + Ext.baseCSSPrefix + 'css-shadow" role="presentation"></div>';
|
|
} else if (Ext.isIE) {
|
|
return '<div class="' + Ext.baseCSSPrefix + 'ie-shadow" role="presentation"></div>';
|
|
} else {
|
|
return '<div class="' + Ext.baseCSSPrefix + 'frame-shadow" role="presentation">' +
|
|
'<div class="xst" role="presentation">' +
|
|
'<div class="xstl" role="presentation"></div>' +
|
|
'<div class="xstc" role="presentation"></div>' +
|
|
'<div class="xstr" role="presentation"></div>' +
|
|
'</div>' +
|
|
'<div class="xsc" role="presentation">' +
|
|
'<div class="xsml" role="presentation"></div>' +
|
|
'<div class="xsmc" role="presentation"></div>' +
|
|
'<div class="xsmr" role="presentation"></div>' +
|
|
'</div>' +
|
|
'<div class="xsb" role="presentation">' +
|
|
'<div class="xsbl" role="presentation"></div>' +
|
|
'<div class="xsbc" role="presentation"></div>' +
|
|
'<div class="xsbr" role="presentation"></div>' +
|
|
'</div>' +
|
|
'</div>';
|
|
}
|
|
}(),
|
|
|
|
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() {
|
|
Ext.Array.each(this.shadows, function(shadow) {
|
|
shadow.remove();
|
|
});
|
|
this.shadows = [];
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.Shadow', {
|
|
requires: ['Ext.ShadowPool'],
|
|
|
|
|
|
constructor: function(config) {
|
|
var me = this,
|
|
adjusts = {
|
|
h: 0
|
|
},
|
|
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.w = adjusts.h = -offset;
|
|
adjusts.l = adjusts.t = offset;
|
|
} else {
|
|
adjusts.w = 0;
|
|
adjusts.l = adjusts.t = offset;
|
|
adjusts.t -= 1;
|
|
if (Ext.isIE) {
|
|
adjusts.l -= offset + rad;
|
|
adjusts.t -= offset + rad;
|
|
adjusts.w -= rad;
|
|
adjusts.h -= rad;
|
|
adjusts.t += 1;
|
|
}
|
|
}
|
|
break;
|
|
case "sides":
|
|
if (Ext.supports.CSS3BoxShadow) {
|
|
adjusts.h -= offset;
|
|
adjusts.t = offset;
|
|
adjusts.l = adjusts.w = 0;
|
|
} else {
|
|
adjusts.w = (offset * 2);
|
|
adjusts.l = -offset;
|
|
adjusts.t = offset - 1;
|
|
if (Ext.isIE) {
|
|
adjusts.l -= (offset - rad);
|
|
adjusts.t -= offset + rad;
|
|
adjusts.l += 1;
|
|
adjusts.w -= (offset - rad) * 2;
|
|
adjusts.w -= rad + 1;
|
|
adjusts.h -= 1;
|
|
}
|
|
}
|
|
break;
|
|
case "frame":
|
|
if (Ext.supports.CSS3BoxShadow) {
|
|
adjusts.l = adjusts.w = adjusts.t = 0;
|
|
} else {
|
|
adjusts.w = adjusts.h = (offset * 2);
|
|
adjusts.l = adjusts.t = -offset;
|
|
adjusts.t += 1;
|
|
adjusts.h -= 2;
|
|
if (Ext.isIE) {
|
|
adjusts.l -= (offset - rad);
|
|
adjusts.t -= (offset - rad);
|
|
adjusts.l += 1;
|
|
adjusts.w -= (offset + rad + 1);
|
|
adjusts.h -= (offset + rad);
|
|
adjusts.h += 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
me.adjusts = adjusts;
|
|
},
|
|
|
|
|
|
|
|
offset: 4,
|
|
|
|
|
|
defaultMode: "drop",
|
|
|
|
|
|
show: function(target) {
|
|
var me = this,
|
|
index;
|
|
|
|
target = Ext.get(target);
|
|
if (!me.el) {
|
|
me.el = Ext.ShadowPool.pull();
|
|
if (me.el.dom.nextSibling != target.dom) {
|
|
me.el.insertBefore(target);
|
|
}
|
|
}
|
|
index = (parseInt(target.getStyle("z-index"), 10) - 1) || 0;
|
|
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(
|
|
target.getLeft(true),
|
|
target.getTop(true),
|
|
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,
|
|
d = this.el.dom,
|
|
targetStyle = d.style,
|
|
shadowWidth,
|
|
shadowHeight,
|
|
cn,
|
|
sww,
|
|
sws,
|
|
shs;
|
|
|
|
targetStyle.left = (l + adjusts.l) + "px";
|
|
targetStyle.top = (t + adjusts.t) + "px";
|
|
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.boxShadow = '0 0 ' + this.offset + 'px 0 #888';
|
|
} else {
|
|
|
|
|
|
if (!Ext.isIE) {
|
|
cn = d.childNodes;
|
|
sww = Math.max(0, (shadowWidth - 12)) + "px";
|
|
cn[0].childNodes[1].style.width = sww;
|
|
cn[1].childNodes[1].style.width = sww;
|
|
cn[2].childNodes[1].style.width = sww;
|
|
cn[1].style.height = Math.max(0, (shadowHeight - 12)) + "px";
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
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.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, t) {
|
|
var me = this;
|
|
|
|
e.preventDefault();
|
|
if (!me.disabled) {
|
|
if (me.overMenuTrigger) {
|
|
me.maybeShowMenu();
|
|
me.fireEvent("arrowclick", me, e);
|
|
if (me.arrowHandler) {
|
|
me.arrowHandler.call(me.scope || me, me, e);
|
|
}
|
|
} else {
|
|
me.doToggle();
|
|
me.fireHandler();
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
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;
|
|
} else {
|
|
me.setText(me.getButtonText(item));
|
|
me.setIconCls(item.iconCls);
|
|
}
|
|
me.activeItem = item;
|
|
if (!item.checked) {
|
|
item.setChecked(true, false);
|
|
}
|
|
if (me.forceIcon) {
|
|
me.setIconCls(me.forceIcon);
|
|
}
|
|
if (!suppressEvent) {
|
|
me.fireEvent('change', me, item);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getActiveItem: function() {
|
|
return this.activeItem;
|
|
},
|
|
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
checked = 0,
|
|
items;
|
|
|
|
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);
|
|
|
|
|
|
Ext.each(items, function(item, 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.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,
|
|
|
|
internalDefaults: {removeMode: 'container', hideParent: true},
|
|
|
|
initComponent : function(){
|
|
|
|
var me = this,
|
|
cols = me.columns;
|
|
|
|
me.noTitleCls = me.baseCls + '-notitle';
|
|
if (cols) {
|
|
me.layout = Ext.apply({}, {columns: cols}, me.layout);
|
|
}
|
|
|
|
if (!me.title) {
|
|
me.addCls(me.noTitleCls);
|
|
}
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
afterLayout: function() {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
|
|
if (me.layout.table && (Ext.isIEQuirks || Ext.isIE6) && !me.width) {
|
|
var t = me.getTargetEl();
|
|
t.setWidth(me.layout.table.offsetWidth + t.getPadding('lr'));
|
|
}
|
|
|
|
|
|
if (Ext.isIE7) {
|
|
me.el.repaint();
|
|
}
|
|
},
|
|
|
|
afterRender: function() {
|
|
var me = this;
|
|
|
|
|
|
if (me.header) {
|
|
|
|
delete me.header.items.items[0].flex;
|
|
|
|
|
|
me.suspendLayout = true;
|
|
me.header.insert(1, {
|
|
xtype: 'component',
|
|
ui : me.ui,
|
|
flex : 1
|
|
});
|
|
me.header.insert(0, {
|
|
xtype: 'component',
|
|
ui : me.ui,
|
|
flex : 1
|
|
});
|
|
me.suspendLayout = false;
|
|
}
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
onBeforeAdd: function(component) {
|
|
if (component.is('button')) {
|
|
component.ui = component.ui + '-toolbar';
|
|
}
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
applyDefaults: function(c) {
|
|
if (!Ext.isString(c)) {
|
|
c = this.callParent(arguments);
|
|
var d = this.internalDefaults;
|
|
if (c.events) {
|
|
Ext.applyIf(c.initialConfig, d);
|
|
Ext.apply(c, d);
|
|
} else {
|
|
Ext.applyIf(c, d);
|
|
}
|
|
}
|
|
return c;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.container.Viewport', {
|
|
extend: 'Ext.container.Container',
|
|
alias: 'widget.viewport',
|
|
requires: ['Ext.EventManager'],
|
|
alternateClassName: 'Ext.Viewport',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isViewport: true,
|
|
|
|
ariaRole: 'application',
|
|
|
|
initComponent : function() {
|
|
var me = this,
|
|
html = Ext.fly(document.body.parentNode),
|
|
el;
|
|
me.callParent(arguments);
|
|
html.addCls(Ext.baseCSSPrefix + 'viewport');
|
|
if (me.autoScroll) {
|
|
html.setStyle('overflow', 'auto');
|
|
}
|
|
me.el = el = Ext.getBody();
|
|
el.setHeight = Ext.emptyFn;
|
|
el.setWidth = Ext.emptyFn;
|
|
el.setSize = Ext.emptyFn;
|
|
el.dom.scroll = 'no';
|
|
me.allowDomMove = false;
|
|
Ext.EventManager.onWindowResize(me.fireResize, me);
|
|
me.renderTo = me.el;
|
|
me.width = Ext.Element.getViewportWidth();
|
|
me.height = Ext.Element.getViewportHeight();
|
|
},
|
|
|
|
fireResize : function(w, h){
|
|
|
|
this.setSize(w, h);
|
|
}
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
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', {
|
|
|
|
uses: ['Ext.util.Region'],
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
|
|
active: false,
|
|
|
|
|
|
|
|
|
|
trackOver: false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tolerance: 5,
|
|
|
|
|
|
autoStart: false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor : function(config){
|
|
Ext.apply(this, config);
|
|
this.addEvents(
|
|
|
|
'mouseover',
|
|
|
|
|
|
'mouseout',
|
|
|
|
|
|
'mousedown',
|
|
|
|
|
|
'mouseup',
|
|
|
|
|
|
'mousemove',
|
|
|
|
|
|
'beforedragstart',
|
|
|
|
|
|
'dragstart',
|
|
|
|
|
|
'dragend',
|
|
|
|
|
|
'drag'
|
|
);
|
|
|
|
this.dragRegion = Ext.create('Ext.util.Region', 0,0,0,0);
|
|
|
|
if (this.el) {
|
|
this.initEl(this.el);
|
|
}
|
|
|
|
|
|
this.mixins.observable.constructor.call(this);
|
|
if (this.disabled) {
|
|
this.disable();
|
|
}
|
|
|
|
},
|
|
|
|
|
|
initEl: function(el) {
|
|
this.el = Ext.get(el);
|
|
|
|
|
|
this.handle = Ext.get(this.delegate);
|
|
|
|
|
|
this.delegate = this.handle ? undefined : this.delegate;
|
|
|
|
if (!this.handle) {
|
|
this.handle = this.el;
|
|
}
|
|
|
|
|
|
|
|
this.mon(this.handle, {
|
|
mousedown: this.onMouseDown,
|
|
delegate: this.delegate,
|
|
scope: this
|
|
});
|
|
|
|
|
|
|
|
|
|
if (this.trackOver || this.overCls) {
|
|
this.mon(this.handle, {
|
|
mouseover: this.onMouseOver,
|
|
mouseout: this.onMouseOut,
|
|
delegate: this.delegate,
|
|
scope: this
|
|
});
|
|
}
|
|
},
|
|
|
|
disable: function() {
|
|
this.disabled = true;
|
|
},
|
|
|
|
enable: function() {
|
|
this.disabled = false;
|
|
},
|
|
|
|
destroy : function() {
|
|
this.clearListeners();
|
|
delete this.el;
|
|
},
|
|
|
|
|
|
|
|
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) {
|
|
if (this.mouseIsDown) {
|
|
this.mouseIsOut = true;
|
|
} else {
|
|
if (this.overCls) {
|
|
this.el.removeCls(this.overCls);
|
|
}
|
|
this.fireEvent('mouseout', this, e);
|
|
}
|
|
},
|
|
|
|
onMouseDown: function(e, target){
|
|
|
|
if (this.disabled ||e.dragTracked) {
|
|
return;
|
|
}
|
|
|
|
|
|
this.dragTarget = this.delegate ? target : this.handle.dom;
|
|
this.startXY = this.lastXY = e.getXY();
|
|
this.startRegion = Ext.fly(this.dragTarget).getRegion();
|
|
|
|
if (this.fireEvent('mousedown', this, e) === false ||
|
|
this.fireEvent('beforedragstart', this, e) === false ||
|
|
this.onBeforeStart(e) === false) {
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
this.mouseIsDown = true;
|
|
|
|
|
|
e.dragTracked = true;
|
|
|
|
if (this.preventDefault !== false) {
|
|
e.preventDefault();
|
|
}
|
|
Ext.getDoc().on({
|
|
scope: this,
|
|
mouseup: this.onMouseUp,
|
|
mousemove: this.onMouseMove,
|
|
selectstart: this.stopSelect
|
|
});
|
|
if (this.autoStart) {
|
|
this.timer = Ext.defer(this.triggerStart, this.autoStart === true ? 1000 : this.autoStart, this, [e]);
|
|
}
|
|
},
|
|
|
|
onMouseMove: function(e, target){
|
|
|
|
|
|
if (this.active && Ext.isIE && !e.browserEvent.button) {
|
|
e.preventDefault();
|
|
this.onMouseUp(e);
|
|
return;
|
|
}
|
|
|
|
e.preventDefault();
|
|
var xy = e.getXY(),
|
|
s = this.startXY;
|
|
|
|
this.lastXY = xy;
|
|
if (!this.active) {
|
|
if (Math.max(Math.abs(s[0]-xy[0]), Math.abs(s[1]-xy[1])) > this.tolerance) {
|
|
this.triggerStart(e);
|
|
} else {
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
if (this.fireEvent('mousemove', this, e) === false) {
|
|
this.onMouseUp(e);
|
|
} else {
|
|
this.onDrag(e);
|
|
this.fireEvent('drag', this, e);
|
|
}
|
|
},
|
|
|
|
onMouseUp: function(e) {
|
|
|
|
|
|
this.mouseIsDown = false;
|
|
|
|
|
|
if (this.mouseIsOut) {
|
|
this.mouseIsOut = false;
|
|
this.onMouseOut(e);
|
|
}
|
|
e.preventDefault();
|
|
this.fireEvent('mouseup', this, e);
|
|
this.endDrag(e);
|
|
},
|
|
|
|
|
|
endDrag: function(e) {
|
|
var doc = Ext.getDoc(),
|
|
wasActive = this.active;
|
|
|
|
doc.un('mousemove', this.onMouseMove, this);
|
|
doc.un('mouseup', this.onMouseUp, this);
|
|
doc.un('selectstart', this.stopSelect, this);
|
|
this.clearStart();
|
|
this.active = false;
|
|
if (wasActive) {
|
|
this.onEnd(e);
|
|
this.fireEvent('dragend', this, e);
|
|
}
|
|
|
|
delete this._constrainRegion;
|
|
|
|
|
|
delete Ext.EventObject.dragTracked;
|
|
},
|
|
|
|
triggerStart: function(e) {
|
|
this.clearStart();
|
|
this.active = true;
|
|
this.onStart(e);
|
|
this.fireEvent('dragstart', this, e);
|
|
},
|
|
|
|
clearStart : function() {
|
|
if (this.timer) {
|
|
clearTimeout(this.timer);
|
|
delete this.timer;
|
|
}
|
|
},
|
|
|
|
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() {
|
|
if (this.constrainTo) {
|
|
if (this.constrainTo instanceof Ext.util.Region) {
|
|
return this.constrainTo;
|
|
}
|
|
if (!this._constrainRegion) {
|
|
this._constrainRegion = Ext.fly(this.constrainTo).getViewRegion();
|
|
}
|
|
} else {
|
|
if (!this._constrainRegion) {
|
|
this._constrainRegion = this.getDragCt().getViewRegion();
|
|
}
|
|
}
|
|
return this._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){
|
|
this.callParent([el, config]);
|
|
if (this.containerScroll) {
|
|
Ext.dd.ScrollManager.register(this.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;
|
|
},
|
|
|
|
|
|
afterRepair : function(){
|
|
var me = this;
|
|
if (Ext.enableFx) {
|
|
Ext.fly(me.dragData.ddel).highlight(me.repairHighlightColor);
|
|
}
|
|
me.dragging = false;
|
|
},
|
|
|
|
|
|
getRepairXY : function(e){
|
|
return Ext.Element.fly(this.dragData.ddel).getXY();
|
|
},
|
|
|
|
destroy : function(){
|
|
this.callParent();
|
|
if (this.containerScroll) {
|
|
Ext.dd.ScrollManager.unregister(this.el);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.dd.ScrollManager', {
|
|
singleton: true,
|
|
requires: [
|
|
'Ext.dd.DragDropManager'
|
|
],
|
|
|
|
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 : this.increment;
|
|
|
|
if (!this.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 xy = e.getXY(),
|
|
pt = e.getPoint(),
|
|
proc = this.proc,
|
|
els = this.els;
|
|
|
|
for (var id in els) {
|
|
var el = els[id], r = el._region;
|
|
var 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, "left");
|
|
}
|
|
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, "right");
|
|
}
|
|
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',
|
|
requires: ['Ext.dd.ScrollManager'],
|
|
|
|
|
|
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;
|
|
for (var i = 0, len = hs.length; i < len; i++) {
|
|
this.handles[this.getId(hs[i])] = data;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
unregister : function(el){
|
|
var id = this.getId(el, false);
|
|
var data = this.elements[id];
|
|
if(data){
|
|
delete this.elements[id];
|
|
if(data.handles){
|
|
var hs = data.handles;
|
|
for (var 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',
|
|
requires: ['Ext.dd.Registry'],
|
|
|
|
|
|
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){
|
|
if(this.lastOverNode){
|
|
this.onNodeOut(this.lastOverNode, dd, e, data);
|
|
this.lastOverNode = null;
|
|
}
|
|
var n = this.getTargetFromEvent(e);
|
|
return n ?
|
|
this.onNodeDrop(n, dd, e, data) :
|
|
this.onContainerDrop(dd, e, data);
|
|
},
|
|
|
|
|
|
triggerCacheRefresh : function() {
|
|
Ext.dd.DDM.refreshCache(this.groups);
|
|
}
|
|
});
|
|
|
|
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: ['<div id="{swfId}"></div>'],
|
|
|
|
initComponent: function() {
|
|
|
|
this.callParent();
|
|
this.addEvents(
|
|
|
|
'success',
|
|
|
|
|
|
'failure'
|
|
);
|
|
},
|
|
|
|
onRender: function() {
|
|
var me = this,
|
|
params, vars, undef,
|
|
swfId = me.getSwfId();
|
|
|
|
me.renderData.swfId = swfId;
|
|
|
|
me.callParent(arguments);
|
|
|
|
params = Ext.apply({
|
|
allowScriptAccess: 'always',
|
|
bgcolor: me.backgroundColor,
|
|
wmode: me.wmode
|
|
}, me.flashParams);
|
|
|
|
vars = Ext.apply({
|
|
allowedDomain: document.location.hostname
|
|
}, me.flashVars);
|
|
|
|
new swfobject.embedSWF(
|
|
me.url,
|
|
swfId,
|
|
me.swfWidth,
|
|
me.swfHeight,
|
|
me.flashVersion,
|
|
me.expressInstall ? me.statics.EXPRESS_INSTALL_URL : undef,
|
|
vars,
|
|
params,
|
|
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.Submit', {
|
|
extend:'Ext.form.action.Action',
|
|
alternateClassName: 'Ext.form.Action.Submit',
|
|
alias: 'formaction.submit',
|
|
|
|
type: 'submit',
|
|
|
|
|
|
|
|
|
|
run : function(){
|
|
var form = this.form;
|
|
if (this.clientValidation === false || form.isValid()) {
|
|
this.doSubmit();
|
|
} else {
|
|
|
|
this.failureType = Ext.form.action.Action.CLIENT_INVALID;
|
|
form.afterAction(this, false);
|
|
}
|
|
},
|
|
|
|
|
|
doSubmit: function() {
|
|
var formEl,
|
|
ajaxOptions = Ext.apply(this.createCallback(), {
|
|
url: this.getUrl(),
|
|
method: this.getMethod(),
|
|
headers: this.headers
|
|
});
|
|
|
|
|
|
|
|
if (this.form.hasUpload()) {
|
|
formEl = ajaxOptions.form = this.buildForm();
|
|
ajaxOptions.isUpload = true;
|
|
} else {
|
|
ajaxOptions.params = this.getParams();
|
|
}
|
|
|
|
Ext.Ajax.request(ajaxOptions);
|
|
|
|
if (formEl) {
|
|
Ext.removeNode(formEl);
|
|
}
|
|
},
|
|
|
|
|
|
getParams: function() {
|
|
var nope = false,
|
|
configParams = this.callParent(),
|
|
fieldParams = this.form.getValues(nope, nope, this.submitEmptyText !== nope);
|
|
return Ext.apply({}, fieldParams, configParams);
|
|
},
|
|
|
|
|
|
buildForm: function() {
|
|
var fieldsSpec = [],
|
|
formSpec,
|
|
formEl,
|
|
basicForm = this.form,
|
|
params = this.getParams(),
|
|
uploadFields = [];
|
|
|
|
basicForm.getFields().each(function(field) {
|
|
if (field.isFileUpload()) {
|
|
uploadFields.push(field);
|
|
}
|
|
});
|
|
|
|
function addField(name, val) {
|
|
fieldsSpec.push({
|
|
tag: 'input',
|
|
type: 'hidden',
|
|
name: name,
|
|
value: Ext.String.htmlEncode(val)
|
|
});
|
|
}
|
|
|
|
|
|
Ext.iterate(params, function(key, val) {
|
|
if (Ext.isArray(val)) {
|
|
Ext.each(val, function(v) {
|
|
addField(key, v);
|
|
});
|
|
} else {
|
|
addField(key, val);
|
|
}
|
|
});
|
|
|
|
formSpec = {
|
|
tag: 'form',
|
|
action: this.getUrl(),
|
|
method: this.getMethod(),
|
|
target: this.target || '_self',
|
|
style: 'display:none',
|
|
cn: fieldsSpec
|
|
};
|
|
|
|
|
|
if (uploadFields.length) {
|
|
formSpec.encoding = formSpec.enctype = 'multipart/form-data';
|
|
}
|
|
|
|
|
|
formEl = Ext.DomHelper.append(Ext.getBody(), formSpec);
|
|
|
|
|
|
|
|
|
|
Ext.Array.each(uploadFields, function(field) {
|
|
if (field.rendered) {
|
|
formEl.appendChild(field.extractFileInput());
|
|
}
|
|
});
|
|
|
|
return formEl;
|
|
},
|
|
|
|
|
|
|
|
|
|
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;
|
|
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;
|
|
}
|
|
return {
|
|
success : rs.success,
|
|
errors : errors
|
|
};
|
|
}
|
|
return Ext.decode(response.responseText);
|
|
}
|
|
});
|
|
|
|
|
|
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;
|
|
|
|
|
|
this.startPosition = comp.getPosition();
|
|
|
|
|
|
|
|
if (comp.ghost && !comp.liveDrag) {
|
|
me.proxy = comp.ghost();
|
|
me.dragTarget = me.proxy.header.el;
|
|
}
|
|
|
|
|
|
if (me.constrain || me.constrainDelegate) {
|
|
me.constrainTo = me.calculateConstrainRegion();
|
|
}
|
|
},
|
|
|
|
calculateConstrainRegion: function() {
|
|
var me = this,
|
|
comp = me.comp,
|
|
c = me.initialConstrainTo,
|
|
delegateRegion,
|
|
elRegion,
|
|
shadowSize = comp.el.shadow ? comp.el.shadow.offset : 0;
|
|
|
|
|
|
if (!(c instanceof Ext.util.Region)) {
|
|
c = Ext.fly(c).getViewRegion();
|
|
}
|
|
|
|
|
|
if (shadowSize) {
|
|
c.adjust(0, -shadowSize, -shadowSize, shadowSize);
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!me.constrainDelegate) {
|
|
delegateRegion = Ext.fly(me.dragTarget).getRegion();
|
|
elRegion = me.proxy ? me.proxy.el.getRegion() : comp.el.getRegion();
|
|
|
|
c.adjust(
|
|
delegateRegion.top - elRegion.top,
|
|
delegateRegion.right - elRegion.right,
|
|
delegateRegion.bottom - elRegion.bottom,
|
|
delegateRegion.left - elRegion.left
|
|
);
|
|
}
|
|
return c;
|
|
},
|
|
|
|
|
|
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.setPosition(me.startPosition[0] + offset[0], me.startPosition[1] + offset[1]);
|
|
},
|
|
|
|
onEnd: function(e) {
|
|
if (this.proxy && !this.comp.liveDrag) {
|
|
this.comp.unghost();
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define("Ext.form.Labelable", {
|
|
requires: ['Ext.XTemplate'],
|
|
|
|
|
|
labelableRenderTpl: [
|
|
'<tpl if="!hideLabel && !(!fieldLabel && hideEmptyLabel)">',
|
|
'<label id="{id}-labelEl"<tpl if="inputId"> for="{inputId}"</tpl> class="{labelCls}"',
|
|
'<tpl if="labelStyle"> style="{labelStyle}"</tpl>>',
|
|
'<tpl if="fieldLabel">{fieldLabel}{labelSeparator}</tpl>',
|
|
'</label>',
|
|
'</tpl>',
|
|
'<div class="{baseBodyCls} {fieldBodyCls}" id="{id}-bodyEl" role="presentation">{subTplMarkup}</div>',
|
|
'<div id="{id}-errorEl" class="{errorMsgCls}" style="display:none"></div>',
|
|
'<div class="{clearCls}" role="presentation"><!-- --></div>',
|
|
{
|
|
compiled: true,
|
|
disableFormats: true
|
|
}
|
|
],
|
|
|
|
|
|
activeErrorsTpl: [
|
|
'<tpl if="errors && errors.length">',
|
|
'<ul><tpl for="errors"><li<tpl if="xindex == xcount"> class="last"</tpl>>{.}</li></tpl></ul>',
|
|
'</tpl>'
|
|
],
|
|
|
|
|
|
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',
|
|
|
|
|
|
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',
|
|
|
|
|
|
|
|
|
|
|
|
initLabelable: function() {
|
|
this.addCls(this.formItemCls);
|
|
|
|
this.addEvents(
|
|
|
|
'errorchange'
|
|
);
|
|
},
|
|
|
|
|
|
getFieldLabel: function() {
|
|
return this.fieldLabel || '';
|
|
},
|
|
|
|
|
|
getLabelableRenderData: function() {
|
|
var me = this,
|
|
labelAlign = me.labelAlign,
|
|
labelCls = me.labelCls,
|
|
labelClsExtra = me.labelClsExtra,
|
|
labelPad = me.labelPad,
|
|
labelStyle;
|
|
|
|
|
|
|
|
if (labelAlign === 'top') {
|
|
labelStyle = 'margin-bottom:' + labelPad + 'px;';
|
|
} else {
|
|
labelStyle = 'margin-right:' + labelPad + 'px;';
|
|
|
|
if (Ext.isBorderBox) {
|
|
labelStyle += 'width:' + me.labelWidth + 'px;';
|
|
}
|
|
}
|
|
|
|
return Ext.copyTo(
|
|
{
|
|
inputId: me.getInputId(),
|
|
fieldLabel: me.getFieldLabel(),
|
|
labelCls: labelClsExtra ? labelCls + ' ' + labelClsExtra : labelCls,
|
|
labelStyle: labelStyle + (me.labelStyle || ''),
|
|
subTplMarkup: me.getSubTplMarkup()
|
|
},
|
|
me,
|
|
'hideLabel,hideEmptyLabel,fieldBodyCls,baseBodyCls,errorMsgCls,clearCls,labelSeparator',
|
|
true
|
|
);
|
|
},
|
|
|
|
onLabelableRender: function () {
|
|
this.addChildEls(
|
|
|
|
'labelEl',
|
|
|
|
|
|
'bodyEl',
|
|
|
|
|
|
'errorEl'
|
|
);
|
|
},
|
|
|
|
|
|
getSubTplMarkup: function() {
|
|
return '';
|
|
},
|
|
|
|
|
|
getInputId: function() {
|
|
return '';
|
|
},
|
|
|
|
|
|
getActiveError : function() {
|
|
return this.activeError || '';
|
|
},
|
|
|
|
|
|
hasActiveError: function() {
|
|
return !!this.getActiveError();
|
|
},
|
|
|
|
|
|
setActiveError: function(msg) {
|
|
this.activeError = msg;
|
|
this.activeErrors = [msg];
|
|
this.renderActiveError();
|
|
},
|
|
|
|
|
|
getActiveErrors: function() {
|
|
return this.activeErrors || [];
|
|
},
|
|
|
|
|
|
setActiveErrors: function(errors) {
|
|
this.activeErrors = errors;
|
|
this.activeError = this.getTpl('activeErrorsTpl').apply({errors: errors});
|
|
this.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);
|
|
|
|
|
|
me.getActionEl().dom.setAttribute('aria-invalid', hasError);
|
|
|
|
|
|
me.errorEl.dom.innerHTML = activeError;
|
|
}
|
|
},
|
|
|
|
|
|
setFieldDefaults: function(defaults) {
|
|
var me = this;
|
|
Ext.iterate(defaults, function(key, val) {
|
|
if (!me.hasOwnProperty(key)) {
|
|
me[key] = val;
|
|
}
|
|
});
|
|
},
|
|
|
|
|
|
getBodyNaturalWidth: function() {
|
|
return this.bodyEl.getWidth();
|
|
}
|
|
|
|
});
|
|
|
|
|
|
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.originalValue = me.lastValue = me.value;
|
|
|
|
|
|
me.suspendCheckChange++;
|
|
me.setValue(me.value);
|
|
me.suspendCheckChange--;
|
|
},
|
|
|
|
|
|
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 && !me.isFileUpload()) {
|
|
data = {};
|
|
data[me.getName()] = '' + me.getValue();
|
|
}
|
|
return data;
|
|
},
|
|
|
|
|
|
getModelData: function() {
|
|
var me = this,
|
|
data = null;
|
|
if (!me.disabled && !me.isFileUpload()) {
|
|
data = {};
|
|
data[me.getName()] = me.getValue();
|
|
}
|
|
return data;
|
|
},
|
|
|
|
|
|
reset : function(){
|
|
var me = this;
|
|
|
|
me.setValue(me.originalValue);
|
|
me.clearInvalid();
|
|
|
|
delete me.wasValid;
|
|
},
|
|
|
|
|
|
resetOriginalValue: function() {
|
|
this.originalValue = this.getValue();
|
|
this.checkDirty();
|
|
},
|
|
|
|
|
|
checkChange: function() {
|
|
if (!this.suspendCheckChange) {
|
|
var me = this,
|
|
newVal = me.getValue(),
|
|
oldVal = me.lastValue;
|
|
if (!me.isEqual(newVal, oldVal) && !me.isDestroyed) {
|
|
me.lastValue = newVal;
|
|
me.fireEvent('change', me, newVal, oldVal);
|
|
me.onChange(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', {
|
|
|
|
|
|
|
|
alias: ['layout.field'],
|
|
|
|
extend: 'Ext.layout.component.Component',
|
|
|
|
uses: ['Ext.tip.QuickTip', 'Ext.util.TextMetrics'],
|
|
|
|
|
|
|
|
type: 'field',
|
|
|
|
beforeLayout: function(width, height) {
|
|
var me = this;
|
|
return me.callParent(arguments) || (!me.owner.preventMark && me.activeError !== me.owner.getActiveError());
|
|
},
|
|
|
|
onLayout: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
labelStrategy = me.getLabelStrategy(),
|
|
errorStrategy = me.getErrorStrategy(),
|
|
isDefined = Ext.isDefined,
|
|
isNumber = Ext.isNumber,
|
|
lastSize, autoWidth, autoHeight, info, undef;
|
|
|
|
lastSize = me.lastComponentSize || {};
|
|
if (!isDefined(width)) {
|
|
width = lastSize.width;
|
|
if (width < 0) {
|
|
width = undef;
|
|
}
|
|
}
|
|
if (!isDefined(height)) {
|
|
height = lastSize.height;
|
|
if (height < 0) {
|
|
height = undef;
|
|
}
|
|
}
|
|
autoWidth = !isNumber(width);
|
|
autoHeight = !isNumber(height);
|
|
|
|
info = {
|
|
autoWidth: autoWidth,
|
|
autoHeight: autoHeight,
|
|
width: autoWidth ? owner.getBodyNaturalWidth() : width,
|
|
height: height,
|
|
setOuterWidth: false,
|
|
|
|
|
|
insets: {
|
|
top: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
left: 0
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
labelStrategy.prepare(owner, info);
|
|
errorStrategy.prepare(owner, info);
|
|
|
|
|
|
labelStrategy.adjustHorizInsets(owner, info);
|
|
errorStrategy.adjustHorizInsets(owner, info);
|
|
|
|
|
|
labelStrategy.layoutHoriz(owner, info);
|
|
errorStrategy.layoutHoriz(owner, info);
|
|
|
|
|
|
labelStrategy.adjustVertInsets(owner, info);
|
|
errorStrategy.adjustVertInsets(owner, info);
|
|
|
|
|
|
labelStrategy.layoutVert(owner, info);
|
|
errorStrategy.layoutVert(owner, info);
|
|
|
|
|
|
if (autoWidth && autoHeight) {
|
|
|
|
me.setElementSize(owner.el, (info.setOuterWidth ? info.width : undef), info.height);
|
|
} else {
|
|
me.setTargetSize((!autoWidth || info.setOuterWidth ? info.width : undef), info.height);
|
|
}
|
|
me.sizeBody(info);
|
|
|
|
me.activeError = owner.getActiveError();
|
|
},
|
|
|
|
onFocus: function(){
|
|
this.getErrorStrategy().onFocus(this.owner);
|
|
},
|
|
|
|
|
|
|
|
sizeBody: function(info) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
insets = info.insets,
|
|
totalWidth = info.width,
|
|
totalHeight = info.height,
|
|
width = Ext.isNumber(totalWidth) ? totalWidth - insets.left - insets.right : totalWidth,
|
|
height = Ext.isNumber(totalHeight) ? totalHeight - insets.top - insets.bottom : totalHeight;
|
|
|
|
|
|
me.setElementSize(owner.bodyEl, width, height);
|
|
|
|
|
|
me.sizeBodyContents(width, height);
|
|
},
|
|
|
|
|
|
sizeBodyContents: Ext.emptyFn,
|
|
|
|
|
|
|
|
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 applyIf = Ext.applyIf,
|
|
emptyFn = Ext.emptyFn,
|
|
base = {
|
|
prepare: function(owner, info) {
|
|
var cls = owner.labelCls + '-' + owner.labelAlign,
|
|
labelEl = owner.labelEl;
|
|
if (labelEl && !labelEl.hasCls(cls)) {
|
|
labelEl.addCls(cls);
|
|
}
|
|
},
|
|
adjustHorizInsets: emptyFn,
|
|
adjustVertInsets: emptyFn,
|
|
layoutHoriz: emptyFn,
|
|
layoutVert: emptyFn
|
|
},
|
|
left = applyIf({
|
|
prepare: function(owner, info) {
|
|
base.prepare(owner, info);
|
|
|
|
if (info.autoWidth) {
|
|
info.width += (!owner.labelEl ? 0 : owner.labelWidth + owner.labelPad);
|
|
}
|
|
|
|
info.setOuterWidth = true;
|
|
},
|
|
adjustHorizInsets: function(owner, info) {
|
|
if (owner.labelEl) {
|
|
info.insets.left += owner.labelWidth + owner.labelPad;
|
|
}
|
|
},
|
|
layoutHoriz: function(owner, info) {
|
|
|
|
|
|
|
|
|
|
|
|
var labelEl = owner.labelEl;
|
|
if (labelEl && !owner.isLabelSized && !Ext.isBorderBox) {
|
|
labelEl.setWidth(owner.labelWidth);
|
|
owner.isLabelSized = true;
|
|
}
|
|
}
|
|
}, base);
|
|
|
|
|
|
return {
|
|
base: base,
|
|
|
|
|
|
top: applyIf({
|
|
adjustVertInsets: function(owner, info) {
|
|
var labelEl = owner.labelEl;
|
|
if (labelEl) {
|
|
info.insets.top += Ext.util.TextMetrics.measure(labelEl, owner.fieldLabel, info.width).height +
|
|
labelEl.getFrameWidth('tb') + owner.labelPad;
|
|
}
|
|
}
|
|
}, base),
|
|
|
|
|
|
left: left,
|
|
|
|
|
|
right: left
|
|
};
|
|
})(),
|
|
|
|
|
|
|
|
|
|
errorStrategies: (function() {
|
|
function setDisplayed(el, displayed) {
|
|
var wasDisplayed = el.getStyle('display') !== 'none';
|
|
if (displayed !== wasDisplayed) {
|
|
el.setDisplayed(displayed);
|
|
}
|
|
}
|
|
|
|
function setStyle(el, name, value) {
|
|
if (el.getStyle(name) !== value) {
|
|
el.setStyle(name, value);
|
|
}
|
|
}
|
|
|
|
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,
|
|
base = {
|
|
prepare: function(owner) {
|
|
setDisplayed(owner.errorEl, false);
|
|
},
|
|
adjustHorizInsets: emptyFn,
|
|
adjustVertInsets: emptyFn,
|
|
layoutHoriz: emptyFn,
|
|
layoutVert: emptyFn,
|
|
onFocus: emptyFn
|
|
};
|
|
|
|
return {
|
|
none: base,
|
|
|
|
|
|
side: applyIf({
|
|
prepare: function(owner) {
|
|
var errorEl = owner.errorEl;
|
|
errorEl.addCls(Ext.baseCSSPrefix + 'form-invalid-icon');
|
|
Ext.layout.component.field.Field.initTip();
|
|
errorEl.dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
|
|
setDisplayed(errorEl, owner.hasActiveError());
|
|
},
|
|
adjustHorizInsets: function(owner, info) {
|
|
if (owner.autoFitErrors && owner.hasActiveError()) {
|
|
info.insets.right += owner.errorEl.getWidth();
|
|
}
|
|
},
|
|
layoutHoriz: function(owner, info) {
|
|
if (owner.hasActiveError()) {
|
|
setStyle(owner.errorEl, 'left', info.width - info.insets.right + 'px');
|
|
}
|
|
},
|
|
layoutVert: function(owner, info) {
|
|
if (owner.hasActiveError()) {
|
|
setStyle(owner.errorEl, 'top', info.insets.top + 'px');
|
|
}
|
|
},
|
|
onFocus: showTip
|
|
}, base),
|
|
|
|
|
|
under: applyIf({
|
|
prepare: function(owner) {
|
|
var errorEl = owner.errorEl,
|
|
cls = Ext.baseCSSPrefix + 'form-invalid-under';
|
|
if (!errorEl.hasCls(cls)) {
|
|
errorEl.addCls(cls);
|
|
}
|
|
setDisplayed(errorEl, owner.hasActiveError());
|
|
},
|
|
adjustVertInsets: function(owner, info) {
|
|
if (owner.autoFitErrors) {
|
|
info.insets.bottom += owner.errorEl.getHeight();
|
|
}
|
|
},
|
|
layoutHoriz: function(owner, info) {
|
|
var errorEl = owner.errorEl,
|
|
insets = info.insets;
|
|
|
|
setStyle(errorEl, 'width', info.width - insets.right - insets.left + 'px');
|
|
setStyle(errorEl, 'marginLeft', insets.left + 'px');
|
|
}
|
|
}, base),
|
|
|
|
|
|
qtip: applyIf({
|
|
prepare: function(owner) {
|
|
setDisplayed(owner.errorEl, false);
|
|
Ext.layout.component.field.Field.initTip();
|
|
owner.getActionEl().dom.setAttribute('data-errorqtip', owner.getActiveError() || '');
|
|
},
|
|
onFocus: showTip
|
|
}, base),
|
|
|
|
|
|
title: applyIf({
|
|
prepare: function(owner) {
|
|
setDisplayed(owner.errorEl, false);
|
|
owner.el.dom.title = owner.getActiveError() || '';
|
|
}
|
|
}, base),
|
|
|
|
|
|
elementId: applyIf({
|
|
prepare: function(owner) {
|
|
setDisplayed(owner.errorEl, false);
|
|
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', {
|
|
baseCls: Ext.baseCSSPrefix + 'form-invalid-tip',
|
|
renderTo: Ext.getBody()
|
|
});
|
|
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.VTypes', (function(){
|
|
|
|
var alpha = /^[a-zA-Z_]+$/,
|
|
alphanum = /^[a-zA-Z0-9_]+$/,
|
|
email = /^(\w+)([\-+.][\w]+)*@(\w[\-\w]*\.){1,5}([A-Za-z]){2,6}$/,
|
|
url = /(((^https?)|(^ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/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 "user@example.com"',
|
|
|
|
'emailMask' : /[a-z0-9_\.\-@\+]/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',
|
|
requires: ['Ext.util.TextMetrics'],
|
|
|
|
type: 'textfield',
|
|
|
|
|
|
|
|
beforeLayout: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
lastValue = this.lastValue,
|
|
value = owner.getRawValue();
|
|
this.lastValue = value;
|
|
return me.callParent(arguments) || (owner.grow && value !== lastValue);
|
|
},
|
|
|
|
|
|
|
|
sizeBodyContents: function(width, height) {
|
|
var size = this.adjustForGrow(width, height);
|
|
this.setElementSize(this.owner.inputEl, size[0], size[1]);
|
|
},
|
|
|
|
|
|
|
|
adjustForGrow: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
inputEl, value, calcWidth,
|
|
result = [width, height];
|
|
|
|
if (owner.grow) {
|
|
inputEl = owner.inputEl;
|
|
|
|
|
|
value = (inputEl.dom.value || (owner.hasFocus ? '' : owner.emptyText) || '') + owner.growAppend;
|
|
calcWidth = inputEl.getTextWidth(value) + inputEl.getBorderWidth("lr") + inputEl.getPadding("lr");
|
|
|
|
|
|
result[0] = Ext.Number.constrain(calcWidth, owner.growMin,
|
|
Math.max(owner.growMin, Math.min(owner.growMax, Ext.isNumber(width) ? width : Infinity)));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.component.field.TextArea', {
|
|
extend: 'Ext.layout.component.field.Text',
|
|
alias: 'layout.textareafield',
|
|
|
|
type: 'textareafield',
|
|
|
|
|
|
|
|
adjustForGrow: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
inputEl, value, max,
|
|
curWidth, curHeight, calcHeight,
|
|
result = [width, height];
|
|
|
|
if (owner.grow) {
|
|
inputEl = owner.inputEl;
|
|
curWidth = inputEl.getWidth(true);
|
|
curHeight = inputEl.getHeight();
|
|
|
|
|
|
value = inputEl.dom.value || ' ';
|
|
value += owner.growAppend;
|
|
|
|
|
|
value = value.replace(/\n/g, '<br>');
|
|
|
|
|
|
calcHeight = Ext.util.TextMetrics.measure(inputEl, value, curWidth).height +
|
|
inputEl.getBorderWidth("tb") + inputEl.getPadding("tb");
|
|
|
|
|
|
max = owner.growMax;
|
|
if (Ext.isNumber(height)) {
|
|
max = Math.min(max, height);
|
|
}
|
|
result[1] = Ext.Number.constrain(calcHeight, owner.growMin, max);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
});
|
|
|
|
Ext.define('Ext.layout.container.Anchor', {
|
|
|
|
|
|
|
|
alias: 'layout.anchor',
|
|
extend: 'Ext.layout.container.Container',
|
|
alternateClassName: 'Ext.layout.AnchorLayout',
|
|
|
|
|
|
|
|
|
|
type: 'anchor',
|
|
|
|
|
|
defaultAnchor: '100%',
|
|
|
|
parseAnchorRE: /^(r|right|b|bottom)$/i,
|
|
|
|
|
|
onLayout: function() {
|
|
this.callParent(arguments);
|
|
|
|
var me = this,
|
|
size = me.getLayoutTargetSize(),
|
|
owner = me.owner,
|
|
target = me.getTarget(),
|
|
ownerWidth = size.width,
|
|
ownerHeight = size.height,
|
|
overflow = target.getStyle('overflow'),
|
|
components = me.getVisibleItems(owner),
|
|
len = components.length,
|
|
boxes = [],
|
|
box, newTargetSize, component, anchorSpec, calcWidth, calcHeight,
|
|
i, el, cleaner;
|
|
|
|
if (ownerWidth < 20 && ownerHeight < 20) {
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!me.clearEl) {
|
|
me.clearEl = target.createChild({
|
|
cls: Ext.baseCSSPrefix + 'clear',
|
|
role: 'presentation'
|
|
});
|
|
}
|
|
|
|
|
|
if (!Ext.supports.RightMargin) {
|
|
cleaner = Ext.Element.getRightMarginFixCleaner(target);
|
|
target.addCls(Ext.baseCSSPrefix + 'inline-children');
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
component = components[i];
|
|
el = component.el;
|
|
|
|
anchorSpec = component.anchorSpec;
|
|
if (anchorSpec) {
|
|
if (anchorSpec.right) {
|
|
calcWidth = me.adjustWidthAnchor(anchorSpec.right(ownerWidth) - el.getMargin('lr'), component);
|
|
} else {
|
|
calcWidth = undefined;
|
|
}
|
|
if (anchorSpec.bottom) {
|
|
calcHeight = me.adjustHeightAnchor(anchorSpec.bottom(ownerHeight) - el.getMargin('tb'), component);
|
|
} else {
|
|
calcHeight = undefined;
|
|
}
|
|
|
|
boxes.push({
|
|
component: component,
|
|
anchor: true,
|
|
width: calcWidth || undefined,
|
|
height: calcHeight || undefined
|
|
});
|
|
} else {
|
|
boxes.push({
|
|
component: component,
|
|
anchor: false
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
if (!Ext.supports.RightMargin) {
|
|
target.removeCls(Ext.baseCSSPrefix + 'inline-children');
|
|
cleaner();
|
|
}
|
|
|
|
for (i = 0; i < len; i++) {
|
|
box = boxes[i];
|
|
me.setItemSize(box.component, box.width, box.height);
|
|
}
|
|
|
|
if (overflow && overflow != 'hidden' && !me.adjustmentPass) {
|
|
newTargetSize = me.getLayoutTargetSize();
|
|
if (newTargetSize.width != size.width || newTargetSize.height != size.height) {
|
|
me.adjustmentPass = true;
|
|
me.onLayout();
|
|
}
|
|
}
|
|
|
|
delete me.adjustmentPass;
|
|
},
|
|
|
|
|
|
parseAnchor: function(a, start, cstart) {
|
|
if (a && a != 'none') {
|
|
var ratio;
|
|
|
|
if (this.parseAnchorRE.test(a)) {
|
|
var diff = cstart - start;
|
|
return function(v) {
|
|
return v - diff;
|
|
};
|
|
}
|
|
|
|
else if (a.indexOf('%') != -1) {
|
|
ratio = parseFloat(a.replace('%', '')) * 0.01;
|
|
return function(v) {
|
|
return Math.floor(v * ratio);
|
|
};
|
|
}
|
|
|
|
else {
|
|
a = parseInt(a, 10);
|
|
if (!isNaN(a)) {
|
|
return function(v) {
|
|
return v + a;
|
|
};
|
|
}
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
|
|
adjustWidthAnchor: function(value, comp) {
|
|
return value;
|
|
},
|
|
|
|
|
|
adjustHeightAnchor: function(value, comp) {
|
|
return value;
|
|
},
|
|
|
|
configureItem: function(item) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
anchor= item.anchor,
|
|
anchorsArray,
|
|
anchorSpec,
|
|
anchorWidth,
|
|
anchorHeight;
|
|
|
|
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 = anchorSpec = {
|
|
right: me.parseAnchor(anchorsArray[0], item.initialConfig.width, anchorWidth),
|
|
bottom: me.parseAnchor(anchorsArray[1], item.initialConfig.height, anchorHeight)
|
|
};
|
|
|
|
if (anchorSpec.right) {
|
|
item.layoutManagedWidth = 1;
|
|
} else {
|
|
item.layoutManagedWidth = 2;
|
|
}
|
|
|
|
if (anchorSpec.bottom) {
|
|
item.layoutManagedHeight = 1;
|
|
} else {
|
|
item.layoutManagedHeight = 2;
|
|
}
|
|
} else {
|
|
item.layoutManagedWidth = 2;
|
|
item.layoutManagedHeight = 2;
|
|
}
|
|
this.callParent(arguments);
|
|
}
|
|
|
|
});
|
|
|
|
Ext.define('Ext.form.action.Load', {
|
|
extend:'Ext.form.action.Action',
|
|
requires: ['Ext.data.Connection'],
|
|
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.window.Window', {
|
|
extend: 'Ext.panel.Panel',
|
|
|
|
alternateClassName: 'Ext.Window',
|
|
|
|
requires: ['Ext.util.ComponentDragger', 'Ext.util.Region', 'Ext.EventManager'],
|
|
|
|
alias: 'widget.window',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'window',
|
|
|
|
|
|
resizable: true,
|
|
|
|
|
|
draggable: true,
|
|
|
|
|
|
constrain: false,
|
|
|
|
|
|
constrainHeader: false,
|
|
|
|
|
|
plain: false,
|
|
|
|
|
|
minimizable: false,
|
|
|
|
|
|
maximizable: false,
|
|
|
|
|
|
minHeight: 100,
|
|
|
|
|
|
minWidth: 200,
|
|
|
|
|
|
expandOnShow: true,
|
|
|
|
|
|
collapsible: false,
|
|
|
|
|
|
closable: true,
|
|
|
|
|
|
hidden: true,
|
|
|
|
|
|
autoRender: true,
|
|
|
|
|
|
hideMode: 'visibility',
|
|
|
|
|
|
floating: true,
|
|
|
|
ariaRole: 'alertdialog',
|
|
|
|
itemCls: 'x-window-item',
|
|
|
|
overlapHeader: true,
|
|
|
|
ignoreHeaderBorderManagement: true,
|
|
|
|
|
|
initComponent: function() {
|
|
var me = this;
|
|
me.callParent();
|
|
me.addEvents(
|
|
|
|
|
|
|
|
|
|
|
|
'resize',
|
|
|
|
|
|
'maximize',
|
|
|
|
|
|
'minimize',
|
|
|
|
|
|
'restore'
|
|
);
|
|
|
|
if (me.plain) {
|
|
me.addClsWithUI('plain');
|
|
}
|
|
|
|
if (me.modal) {
|
|
me.ariaRole = 'dialog';
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
initStateEvents: function(){
|
|
var events = this.stateEvents;
|
|
|
|
Ext.each(['maximize', 'restore', 'resize', 'dragend'], function(event){
|
|
if (Ext.Array.indexOf(events, event)) {
|
|
events.push(event);
|
|
}
|
|
});
|
|
this.callParent();
|
|
},
|
|
|
|
getState: function() {
|
|
var me = this,
|
|
state = me.callParent() || {},
|
|
maximized = !!me.maximized;
|
|
|
|
state.maximized = maximized;
|
|
Ext.apply(state, {
|
|
size: maximized ? me.restoreSize : me.getSize(),
|
|
pos: maximized ? me.restorePos : me.getPosition()
|
|
});
|
|
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]
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onMouseDown: function (e) {
|
|
var preventFocus;
|
|
|
|
if (this.floating) {
|
|
if (Ext.fly(e.getTarget()).focusable()) {
|
|
preventFocus = true;
|
|
}
|
|
this.toFront(preventFocus);
|
|
}
|
|
},
|
|
|
|
|
|
onRender: function(ct, position) {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
me.focusEl = me.el;
|
|
|
|
|
|
if (me.maximizable) {
|
|
me.header.on({
|
|
dblclick: {
|
|
fn: me.toggleMaximize,
|
|
element: 'el',
|
|
scope: me
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
afterRender: function() {
|
|
var me = this,
|
|
hidden = me.hidden,
|
|
keyMap;
|
|
|
|
me.hidden = false;
|
|
|
|
me.callParent();
|
|
me.hidden = hidden;
|
|
|
|
|
|
me.proxy = me.getProxy();
|
|
|
|
|
|
me.mon(me.el, 'mousedown', me.onMouseDown, me);
|
|
|
|
|
|
me.el.set({
|
|
tabIndex: -1
|
|
});
|
|
|
|
|
|
if (me.maximized) {
|
|
me.maximized = false;
|
|
me.maximize();
|
|
}
|
|
|
|
if (me.closable) {
|
|
keyMap = me.getKeyMap();
|
|
keyMap.on(27, me.onEsc, me);
|
|
|
|
|
|
keyMap.disable();
|
|
|
|
}
|
|
|
|
if (!hidden) {
|
|
me.syncMonitorWindowResize();
|
|
me.doConstrain();
|
|
}
|
|
},
|
|
|
|
|
|
initDraggable: function() {
|
|
var me = this,
|
|
ddConfig;
|
|
|
|
if (!me.header) {
|
|
me.updateHeader(true);
|
|
}
|
|
|
|
|
|
if (me.header) {
|
|
ddConfig = Ext.applyIf({
|
|
el: me.el,
|
|
delegate: '#' + me.header.id
|
|
}, me.draggable);
|
|
|
|
|
|
if (me.constrain || me.constrainHeader) {
|
|
ddConfig.constrain = me.constrain;
|
|
ddConfig.constrainDelegate = me.constrainHeader;
|
|
ddConfig.constrainTo = me.constrainTo || me.container;
|
|
}
|
|
|
|
|
|
me.dd = Ext.create('Ext.util.ComponentDragger', this, ddConfig);
|
|
me.relayEvents(me.dd, ['dragstart', 'drag', 'dragend']);
|
|
}
|
|
},
|
|
|
|
|
|
onEsc: function(k, e) {
|
|
e.stopEvent();
|
|
this[this.closeAction]();
|
|
},
|
|
|
|
|
|
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() {
|
|
var me = this,
|
|
f = me.focusEl,
|
|
defaultComp = me.defaultButton || me.defaultFocus,
|
|
t = typeof db,
|
|
el,
|
|
ct;
|
|
|
|
if (Ext.isDefined(defaultComp)) {
|
|
if (Ext.isNumber(defaultComp)) {
|
|
f = me.query('button')[defaultComp];
|
|
} else if (Ext.isString(defaultComp)) {
|
|
f = me.down('#' + defaultComp);
|
|
} else {
|
|
f = defaultComp;
|
|
}
|
|
}
|
|
return f || me.focusEl;
|
|
},
|
|
|
|
|
|
beforeShow: function() {
|
|
this.callParent();
|
|
|
|
if (this.expandOnShow) {
|
|
this.expand(false);
|
|
}
|
|
},
|
|
|
|
|
|
afterShow: function(animateTarget) {
|
|
var me = this,
|
|
animating = animateTarget || me.animateTarget;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (me.maximized) {
|
|
me.fitContainer();
|
|
}
|
|
|
|
me.syncMonitorWindowResize();
|
|
if (!animating) {
|
|
me.doConstrain();
|
|
}
|
|
|
|
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() {
|
|
if (this.maximized) {
|
|
this.fitContainer();
|
|
}
|
|
this.doConstrain();
|
|
},
|
|
|
|
|
|
minimize: function() {
|
|
this.fireEvent('minimize', this);
|
|
return this;
|
|
},
|
|
|
|
afterCollapse: function() {
|
|
var me = this;
|
|
|
|
if (me.maximizable) {
|
|
me.tools.maximize.hide();
|
|
me.tools.restore.hide();
|
|
}
|
|
if (me.resizer) {
|
|
me.resizer.disable();
|
|
}
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
afterExpand: function() {
|
|
var me = this;
|
|
|
|
if (me.maximized) {
|
|
me.tools.restore.show();
|
|
} else if (me.maximizable) {
|
|
me.tools.maximize.show();
|
|
}
|
|
if (me.resizer) {
|
|
me.resizer.enable();
|
|
}
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
maximize: function() {
|
|
var me = this;
|
|
|
|
if (!me.maximized) {
|
|
me.expand(false);
|
|
if (!me.hasSavedRestore) {
|
|
me.restoreSize = me.getSize();
|
|
me.restorePos = me.getPosition(true);
|
|
}
|
|
if (me.maximizable) {
|
|
me.tools.maximize.hide();
|
|
me.tools.restore.show();
|
|
}
|
|
me.maximized = true;
|
|
me.el.disableShadow();
|
|
|
|
if (me.dd) {
|
|
me.dd.disable();
|
|
}
|
|
if (me.collapseTool) {
|
|
me.collapseTool.hide();
|
|
}
|
|
me.el.addCls(Ext.baseCSSPrefix + 'window-maximized');
|
|
me.container.addCls(Ext.baseCSSPrefix + 'window-maximized-ct');
|
|
|
|
me.syncMonitorWindowResize();
|
|
me.setPosition(0, 0);
|
|
me.fitContainer();
|
|
me.fireEvent('maximize', me);
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
restore: function() {
|
|
var me = this,
|
|
tools = me.tools;
|
|
|
|
if (me.maximized) {
|
|
delete me.hasSavedRestore;
|
|
me.removeCls(Ext.baseCSSPrefix + 'window-maximized');
|
|
|
|
|
|
if (tools.restore) {
|
|
tools.restore.hide();
|
|
}
|
|
if (tools.maximize) {
|
|
tools.maximize.show();
|
|
}
|
|
if (me.collapseTool) {
|
|
me.collapseTool.show();
|
|
}
|
|
|
|
|
|
me.setPosition(me.restorePos);
|
|
me.setSize(me.restoreSize);
|
|
|
|
|
|
delete me.restorePos;
|
|
delete me.restoreSize;
|
|
|
|
me.maximized = false;
|
|
|
|
me.el.enableShadow(true);
|
|
|
|
|
|
if (me.dd) {
|
|
me.dd.enable();
|
|
}
|
|
|
|
me.container.removeCls(Ext.baseCSSPrefix + 'window-maximized-ct');
|
|
|
|
me.syncMonitorWindowResize();
|
|
me.doConstrain();
|
|
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);
|
|
me._monitoringResize = true;
|
|
}
|
|
} else if (currentlyMonitoring) {
|
|
|
|
Ext.EventManager.removeResizeListener(me.onWindowResize, me);
|
|
me._monitoringResize = false;
|
|
}
|
|
},
|
|
|
|
|
|
toggleMaximize: function() {
|
|
return this[this.maximized ? 'restore': 'maximize']();
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
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'],
|
|
requires: ['Ext.util.DelayedTask', 'Ext.XTemplate', 'Ext.layout.component.field.Field'],
|
|
|
|
|
|
fieldSubTpl: [
|
|
'<input id="{id}" type="{type}" ',
|
|
'<tpl if="name">name="{name}" </tpl>',
|
|
'<tpl if="size">size="{size}" </tpl>',
|
|
'<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
|
|
'class="{fieldCls} {typeCls}" autocomplete="off" />',
|
|
{
|
|
compiled: true,
|
|
disableFormats: true
|
|
}
|
|
],
|
|
|
|
|
|
|
|
|
|
inputType: 'text',
|
|
|
|
|
|
|
|
|
|
invalidText : 'The value in this field is invalid',
|
|
|
|
|
|
fieldCls : Ext.baseCSSPrefix + 'form-field',
|
|
|
|
|
|
|
|
|
|
focusCls : Ext.baseCSSPrefix + 'form-focus',
|
|
|
|
|
|
dirtyCls : Ext.baseCSSPrefix + 'form-dirty',
|
|
|
|
|
|
checkChangeEvents: Ext.isIE && (!document.documentMode || document.documentMode < 9) ?
|
|
['change', 'propertychange'] :
|
|
['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,
|
|
|
|
|
|
initComponent : function() {
|
|
var me = this;
|
|
|
|
me.callParent();
|
|
|
|
me.subTplData = me.subTplData || {};
|
|
|
|
me.addEvents(
|
|
|
|
'focus',
|
|
|
|
'blur',
|
|
|
|
'specialkey'
|
|
);
|
|
|
|
|
|
me.initLabelable();
|
|
me.initField();
|
|
|
|
|
|
if (!me.name) {
|
|
me.name = me.getInputId();
|
|
}
|
|
},
|
|
|
|
|
|
getInputId: function() {
|
|
return this.inputId || (this.inputId = Ext.id());
|
|
},
|
|
|
|
|
|
getSubTplData: function() {
|
|
var me = this,
|
|
type = me.inputType,
|
|
inputId = me.getInputId();
|
|
|
|
return Ext.applyIf(me.subTplData, {
|
|
id: inputId,
|
|
cmpId: me.id,
|
|
name: me.name || inputId,
|
|
type: type,
|
|
size: me.size || 20,
|
|
cls: me.cls,
|
|
fieldCls: me.fieldCls,
|
|
tabIdx: me.tabIndex,
|
|
typeCls: Ext.baseCSSPrefix + 'form-' + (type === 'password' ? 'text' : type)
|
|
});
|
|
},
|
|
|
|
afterRender: function() {
|
|
this.callParent();
|
|
|
|
if (this.inputEl) {
|
|
this.inputEl.selectable();
|
|
}
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
onRender : function() {
|
|
var me = this,
|
|
fieldStyle = me.fieldStyle;
|
|
|
|
me.onLabelableRender();
|
|
|
|
|
|
me.addChildEls({ name: 'inputEl', id: me.getInputId() });
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
me.setRawValue(me.rawValue);
|
|
|
|
if (me.readOnly) {
|
|
me.setReadOnly(true);
|
|
}
|
|
if (me.disabled) {
|
|
me.disable();
|
|
}
|
|
if (fieldStyle) {
|
|
me.setFieldStyle(fieldStyle);
|
|
}
|
|
|
|
me.renderActiveError();
|
|
},
|
|
|
|
initAria: function() {
|
|
var me = this;
|
|
me.callParent();
|
|
|
|
|
|
me.getActionEl().dom.setAttribute('aria-describedby', Ext.id(me.errorEl));
|
|
},
|
|
|
|
getFocusEl: function() {
|
|
return this.inputEl;
|
|
},
|
|
|
|
isFileUpload: function() {
|
|
return this.inputType === 'file';
|
|
},
|
|
|
|
extractFileInput: function() {
|
|
var me = this,
|
|
fileInput = me.isFileUpload() ? me.inputEl.dom : null,
|
|
clone;
|
|
if (fileInput) {
|
|
clone = fileInput.cloneNode(true);
|
|
fileInput.parentNode.replaceChild(clone, fileInput);
|
|
me.inputEl = Ext.get(clone);
|
|
}
|
|
return fileInput;
|
|
},
|
|
|
|
|
|
getSubmitData: function() {
|
|
var me = this,
|
|
data = null,
|
|
val;
|
|
if (!me.disabled && me.submitValue && !me.isFileUpload()) {
|
|
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(value, '');
|
|
me.rawValue = value;
|
|
|
|
|
|
if (me.inputEl) {
|
|
me.inputEl.dom.value = value;
|
|
}
|
|
return value;
|
|
},
|
|
|
|
|
|
valueToRaw: function(value) {
|
|
return '' + Ext.value(value, '');
|
|
},
|
|
|
|
|
|
rawToValue: function(rawValue) {
|
|
return rawValue;
|
|
},
|
|
|
|
|
|
processRawValue: function(value) {
|
|
return value;
|
|
},
|
|
|
|
|
|
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);
|
|
},
|
|
|
|
|
|
|
|
onDisable: function() {
|
|
var me = this,
|
|
inputEl = me.inputEl;
|
|
me.callParent();
|
|
if (inputEl) {
|
|
inputEl.dom.disabled = true;
|
|
}
|
|
},
|
|
|
|
|
|
onEnable: function() {
|
|
var me = this,
|
|
inputEl = me.inputEl;
|
|
me.callParent();
|
|
if (inputEl) {
|
|
inputEl.dom.disabled = false;
|
|
}
|
|
},
|
|
|
|
|
|
setReadOnly: function(readOnly) {
|
|
var me = this,
|
|
inputEl = me.inputEl;
|
|
if (inputEl) {
|
|
inputEl.dom.readOnly = readOnly;
|
|
inputEl.dom.setAttribute('aria-readonly', readOnly);
|
|
}
|
|
me[readOnly ? 'addCls' : 'removeCls'](me.readOnlyCls);
|
|
me.readOnly = readOnly;
|
|
},
|
|
|
|
|
|
fireKey: function(e){
|
|
if(e.isSpecialKey()){
|
|
this.fireEvent('specialkey', this, Ext.create('Ext.EventObjectImpl', e));
|
|
}
|
|
},
|
|
|
|
|
|
initEvents : function(){
|
|
var me = this,
|
|
inputEl = me.inputEl,
|
|
onChangeTask,
|
|
onChangeEvent;
|
|
if (inputEl) {
|
|
me.mon(inputEl, Ext.EventManager.getKeyEvent(), me.fireKey, me);
|
|
me.mon(inputEl, 'focus', me.onFocus, me);
|
|
|
|
|
|
|
|
me.mon(inputEl, 'blur', me.onBlur, me, me.inEditor ? {buffer:10} : null);
|
|
|
|
|
|
onChangeTask = Ext.create('Ext.util.DelayedTask', me.checkChange, me);
|
|
me.onChangeEvent = onChangeEvent = function() {
|
|
onChangeTask.delay(me.checkChangeBuffer);
|
|
};
|
|
Ext.each(me.checkChangeEvents, function(eventName) {
|
|
if (eventName === 'propertychange') {
|
|
me.usesPropertychange = true;
|
|
}
|
|
me.mon(inputEl, eventName, onChangeEvent);
|
|
}, me);
|
|
}
|
|
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);
|
|
}
|
|
},
|
|
|
|
|
|
preFocus: Ext.emptyFn,
|
|
|
|
|
|
onFocus: function() {
|
|
var me = this,
|
|
focusCls = me.focusCls,
|
|
inputEl = me.inputEl;
|
|
me.preFocus();
|
|
if (focusCls && inputEl) {
|
|
inputEl.addCls(focusCls);
|
|
}
|
|
if (!me.hasFocus) {
|
|
me.hasFocus = true;
|
|
me.componentLayout.onFocus();
|
|
me.fireEvent('focus', me);
|
|
}
|
|
},
|
|
|
|
|
|
beforeBlur : Ext.emptyFn,
|
|
|
|
|
|
onBlur : function(){
|
|
var me = this,
|
|
focusCls = me.focusCls,
|
|
inputEl = me.inputEl;
|
|
|
|
if (me.destroying) {
|
|
return;
|
|
}
|
|
|
|
me.beforeBlur();
|
|
if (focusCls && inputEl) {
|
|
inputEl.removeCls(focusCls);
|
|
}
|
|
if (me.validateOnBlur) {
|
|
me.validate();
|
|
}
|
|
me.hasFocus = false;
|
|
me.fireEvent('blur', me);
|
|
me.postBlur();
|
|
},
|
|
|
|
|
|
postBlur : Ext.emptyFn,
|
|
|
|
|
|
|
|
onDirtyChange: function(isDirty) {
|
|
this[isDirty ? 'addCls' : 'removeCls'](this.dirtyCls);
|
|
},
|
|
|
|
|
|
|
|
isValid : function() {
|
|
var me = this;
|
|
return me.disabled || me.validateValue(me.processRawValue(me.getRawValue()));
|
|
},
|
|
|
|
|
|
|
|
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();
|
|
me.setActiveErrors(Ext.Array.from(errors));
|
|
if (oldMsg !== me.getActiveError()) {
|
|
me.doComponentLayout();
|
|
}
|
|
},
|
|
|
|
|
|
clearInvalid : function() {
|
|
|
|
var me = this,
|
|
hadError = me.hasActiveError();
|
|
me.unsetActiveError();
|
|
if (hadError) {
|
|
me.doComponentLayout();
|
|
}
|
|
},
|
|
|
|
|
|
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.Text', {
|
|
extend:'Ext.form.field.Base',
|
|
alias: 'widget.textfield',
|
|
requires: ['Ext.form.field.VTypes', 'Ext.layout.component.field.Text'],
|
|
alternateClassName: ['Ext.form.TextField', 'Ext.form.Text'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
size: 20,
|
|
|
|
|
|
|
|
|
|
growMin : 30,
|
|
|
|
|
|
growMax : 800,
|
|
|
|
|
|
growAppend: 'W',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
allowBlank : 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',
|
|
|
|
ariaRole: 'textbox',
|
|
|
|
|
|
|
|
componentLayout: 'textfield',
|
|
|
|
initComponent : function(){
|
|
this.callParent();
|
|
this.addEvents(
|
|
|
|
'autosize',
|
|
|
|
|
|
'keydown',
|
|
|
|
'keyup',
|
|
|
|
'keypress'
|
|
);
|
|
},
|
|
|
|
|
|
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() {
|
|
this.callParent();
|
|
this.autoSize();
|
|
},
|
|
|
|
afterRender: function(){
|
|
var me = this;
|
|
if (me.enforceMaxLength) {
|
|
me.inputEl.dom.maxLength = me.maxLength;
|
|
}
|
|
me.applyEmptyText();
|
|
me.autoSize();
|
|
me.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);
|
|
}
|
|
|
|
|
|
|
|
if (isEmpty) {
|
|
me.inputEl.addCls(me.emptyCls);
|
|
}
|
|
|
|
me.autoSize();
|
|
}
|
|
},
|
|
|
|
|
|
preFocus : function(){
|
|
var me = this,
|
|
inputEl = me.inputEl,
|
|
emptyText = me.emptyText,
|
|
isEmpty;
|
|
|
|
if (emptyText && !Ext.supports.Placeholder && inputEl.dom.value === emptyText) {
|
|
me.setRawValue('');
|
|
isEmpty = true;
|
|
inputEl.removeCls(me.emptyCls);
|
|
} else if (Ext.supports.Placeholder) {
|
|
me.inputEl.removeCls(me.emptyCls);
|
|
}
|
|
if (me.selectOnFocus || isEmpty) {
|
|
inputEl.dom.select();
|
|
}
|
|
},
|
|
|
|
onFocus: function() {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
if (me.emptyText) {
|
|
me.autoSize();
|
|
}
|
|
},
|
|
|
|
|
|
postBlur : function(){
|
|
this.applyEmptyText();
|
|
},
|
|
|
|
|
|
filterKeys : function(e){
|
|
|
|
if (e.ctrlKey && !e.altKey) {
|
|
return;
|
|
}
|
|
var key = e.getKey(),
|
|
charCode = String.fromCharCode(e.getCharCode());
|
|
|
|
if(Ext.isGecko && (e.isNavKeyPress() || key === e.BACKSPACE || (key === e.DELETE && e.button === -1))){
|
|
return;
|
|
}
|
|
|
|
if(!Ext.isGecko && e.isSpecialKey() && !charCode){
|
|
return;
|
|
}
|
|
if(!this.maskRe.test(charCode)){
|
|
e.stopEvent();
|
|
}
|
|
},
|
|
|
|
|
|
getRawValue: function() {
|
|
var me = this,
|
|
v = me.callParent();
|
|
if (v === me.emptyText) {
|
|
v = '';
|
|
}
|
|
return v;
|
|
},
|
|
|
|
|
|
setValue: function(value) {
|
|
var me = this,
|
|
inputEl = me.inputEl;
|
|
|
|
if (inputEl && me.emptyText && !Ext.isEmpty(value)) {
|
|
inputEl.removeCls(me.emptyCls);
|
|
}
|
|
|
|
me.callParent(arguments);
|
|
|
|
me.applyEmptyText();
|
|
return me;
|
|
},
|
|
|
|
|
|
getErrors: function(value) {
|
|
var me = this,
|
|
errors = me.callParent(arguments),
|
|
validator = me.validator,
|
|
emptyText = me.emptyText,
|
|
allowBlank = me.allowBlank,
|
|
vtype = me.vtype,
|
|
vtypes = Ext.form.field.VTypes,
|
|
regex = me.regex,
|
|
format = Ext.String.format,
|
|
msg;
|
|
|
|
value = value || me.processRawValue(me.getRawValue());
|
|
|
|
if (Ext.isFunction(validator)) {
|
|
msg = validator.call(me, value);
|
|
if (msg !== true) {
|
|
errors.push(msg);
|
|
}
|
|
}
|
|
|
|
if (value.length < 1 || value === emptyText) {
|
|
if (!allowBlank) {
|
|
errors.push(me.blankText);
|
|
}
|
|
|
|
return errors;
|
|
}
|
|
|
|
if (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,
|
|
width;
|
|
if (me.grow && me.rendered) {
|
|
me.doComponentLayout();
|
|
width = me.inputEl.getWidth();
|
|
if (width !== me.lastInputWidth) {
|
|
me.fireEvent('autosize', width);
|
|
me.lastInputWidth = width;
|
|
}
|
|
}
|
|
},
|
|
|
|
initAria: function() {
|
|
this.callParent();
|
|
this.getActionEl().dom.setAttribute('aria-required', this.allowBlank === false);
|
|
},
|
|
|
|
|
|
getBodyNaturalWidth: function() {
|
|
return Math.round(this.size * 6.5) + 20;
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.field.TextArea', {
|
|
extend:'Ext.form.field.Text',
|
|
alias: ['widget.textareafield', 'widget.textarea'],
|
|
alternateClassName: 'Ext.form.TextArea',
|
|
requires: ['Ext.XTemplate', 'Ext.layout.component.field.TextArea'],
|
|
|
|
fieldSubTpl: [
|
|
'<textarea id="{id}" ',
|
|
'<tpl if="name">name="{name}" </tpl>',
|
|
'<tpl if="rows">rows="{rows}" </tpl>',
|
|
'<tpl if="cols">cols="{cols}" </tpl>',
|
|
'<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
|
|
'class="{fieldCls} {typeCls}" ',
|
|
'autocomplete="off">',
|
|
'</textarea>',
|
|
{
|
|
compiled: true,
|
|
disableFormats: true
|
|
}
|
|
],
|
|
|
|
|
|
growMin: 60,
|
|
|
|
|
|
growMax: 1000,
|
|
|
|
|
|
growAppend: '\n-',
|
|
|
|
|
|
cols: 20,
|
|
|
|
|
|
rows: 4,
|
|
|
|
|
|
enterIsSpecial: false,
|
|
|
|
|
|
preventScrollbars: false,
|
|
|
|
|
|
componentLayout: 'textareafield',
|
|
|
|
|
|
onRender: function(ct, position) {
|
|
var me = this;
|
|
Ext.applyIf(me.subTplData, {
|
|
cols: me.cols,
|
|
rows: me.rows
|
|
});
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
afterRender: function(){
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (me.grow) {
|
|
if (me.preventScrollbars) {
|
|
me.inputEl.setStyle('overflow', 'hidden');
|
|
}
|
|
me.inputEl.setHeight(me.growMin);
|
|
}
|
|
},
|
|
|
|
|
|
fireKey: function(e) {
|
|
if (e.isSpecialKey() && (this.enterIsSpecial || (e.getKey() !== e.ENTER || e.hasModifier()))) {
|
|
this.fireEvent('specialkey', this, e);
|
|
}
|
|
},
|
|
|
|
|
|
autoSize: function() {
|
|
var me = this,
|
|
height;
|
|
|
|
if (me.grow && me.rendered) {
|
|
me.doComponentLayout();
|
|
height = me.inputEl.getHeight();
|
|
if (height !== me.lastInputHeight) {
|
|
me.fireEvent('autosize', height);
|
|
me.lastInputHeight = height;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
initAria: function() {
|
|
this.callParent(arguments);
|
|
this.getActionEl().dom.setAttribute('aria-multiline', true);
|
|
},
|
|
|
|
|
|
getBodyNaturalWidth: function() {
|
|
return Math.round(this.cols * 6.5) + 20;
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.window.MessageBox', {
|
|
extend: 'Ext.window.Window',
|
|
|
|
requires: [
|
|
'Ext.toolbar.Toolbar',
|
|
'Ext.form.field.Text',
|
|
'Ext.form.field.TextArea',
|
|
'Ext.button.Button',
|
|
'Ext.layout.container.Anchor',
|
|
'Ext.layout.container.HBox',
|
|
'Ext.ProgressBar'
|
|
],
|
|
|
|
alias: 'widget.messagebox',
|
|
|
|
|
|
OK : 1,
|
|
|
|
YES : 2,
|
|
|
|
NO : 4,
|
|
|
|
CANCEL : 8,
|
|
|
|
OKCANCEL : 9,
|
|
|
|
YESNO : 6,
|
|
|
|
YESNOCANCEL : 14,
|
|
|
|
INFO : 'ext-mb-info',
|
|
|
|
WARNING : 'ext-mb-warning',
|
|
|
|
QUESTION : 'ext-mb-question',
|
|
|
|
ERROR : 'ext-mb-error',
|
|
|
|
|
|
hideMode: 'offsets',
|
|
closeAction: 'hide',
|
|
resizable: false,
|
|
title: ' ',
|
|
|
|
width: 600,
|
|
height: 500,
|
|
minWidth: 250,
|
|
maxWidth: 600,
|
|
minHeight: 110,
|
|
maxHeight: 500,
|
|
constrain: true,
|
|
|
|
cls: Ext.baseCSSPrefix + 'message-box',
|
|
|
|
layout: {
|
|
type: 'anchor'
|
|
},
|
|
|
|
|
|
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,
|
|
|
|
makeButton: function(btnIdx) {
|
|
var btnId = this.buttonIds[btnIdx];
|
|
return Ext.create('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();
|
|
}
|
|
|
|
|
|
btn.blur();
|
|
me.hide();
|
|
me.userCallback(btn.itemId, value, me.cfg);
|
|
},
|
|
|
|
hide: function() {
|
|
var me = this;
|
|
me.dd.endDrag();
|
|
me.progressBar.reset();
|
|
me.removeCls(me.cfg.cls);
|
|
me.callParent();
|
|
},
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
i, button;
|
|
|
|
me.title = ' ';
|
|
|
|
me.topContainer = Ext.create('Ext.container.Container', {
|
|
anchor: '100%',
|
|
style: {
|
|
padding: '10px',
|
|
overflow: 'hidden'
|
|
},
|
|
items: [
|
|
me.iconComponent = Ext.create('Ext.Component', {
|
|
cls: 'ext-mb-icon',
|
|
width: 50,
|
|
height: me.iconHeight,
|
|
style: {
|
|
'float': 'left'
|
|
}
|
|
}),
|
|
me.promptContainer = Ext.create('Ext.container.Container', {
|
|
layout: {
|
|
type: 'anchor'
|
|
},
|
|
items: [
|
|
me.msg = Ext.create('Ext.Component', {
|
|
autoEl: { tag: 'span' },
|
|
cls: 'ext-mb-text'
|
|
}),
|
|
me.textField = Ext.create('Ext.form.field.Text', {
|
|
anchor: '100%',
|
|
enableKeyEvents: true,
|
|
listeners: {
|
|
keydown: me.onPromptKey,
|
|
scope: me
|
|
}
|
|
}),
|
|
me.textArea = Ext.create('Ext.form.field.TextArea', {
|
|
anchor: '100%',
|
|
height: 75
|
|
})
|
|
]
|
|
})
|
|
]
|
|
});
|
|
me.progressBar = Ext.create('Ext.ProgressBar', {
|
|
anchor: '-10',
|
|
style: 'margin-left:10px'
|
|
});
|
|
|
|
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 = Ext.create('Ext.toolbar.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.callParent();
|
|
},
|
|
|
|
onPromptKey: function(textField, e) {
|
|
var me = this,
|
|
blur;
|
|
|
|
if (e.keyCode === Ext.EventObject.RETURN || e.keyCode === 10) {
|
|
if (me.msgButtons.ok.isVisible()) {
|
|
blur = true;
|
|
me.msgButtons.ok.handler.call(me, me.msgButtons.ok);
|
|
} else if (me.msgButtons.yes.isVisible()) {
|
|
me.msgButtons.yes.handler.call(me, me.msgButtons.yes);
|
|
blur = true;
|
|
}
|
|
|
|
if (blur) {
|
|
me.textField.blur();
|
|
}
|
|
}
|
|
},
|
|
|
|
reconfigure: function(cfg) {
|
|
var me = this,
|
|
buttons = cfg.buttons || 0,
|
|
hideToolbar = true,
|
|
initialWidth = me.maxWidth,
|
|
i;
|
|
|
|
cfg = cfg || {};
|
|
me.cfg = cfg;
|
|
if (cfg.width) {
|
|
initialWidth = cfg.width;
|
|
}
|
|
|
|
|
|
delete me.defaultFocus;
|
|
|
|
|
|
me.animateTarget = cfg.animateTarget || undefined;
|
|
|
|
|
|
me.modal = cfg.modal !== false;
|
|
|
|
|
|
if (cfg.title) {
|
|
me.setTitle(cfg.title||' ');
|
|
}
|
|
|
|
if (!me.rendered) {
|
|
me.width = initialWidth;
|
|
me.render(Ext.getBody());
|
|
} else {
|
|
me.setSize(initialWidth, me.maxHeight);
|
|
}
|
|
me.setPosition(-10000, -10000);
|
|
|
|
|
|
me.closable = cfg.closable && !cfg.wait;
|
|
me.header.child('[type=close]').setVisible(cfg.closable !== false);
|
|
|
|
|
|
if (!cfg.title && !me.closable) {
|
|
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);
|
|
|
|
|
|
if (cfg.msg) {
|
|
me.msg.update(cfg.msg);
|
|
me.msg.show();
|
|
} else {
|
|
me.msg.hide();
|
|
}
|
|
|
|
|
|
if (cfg.prompt || cfg.multiline) {
|
|
me.multiline = cfg.multiline;
|
|
if (cfg.multiline) {
|
|
me.textArea.setValue(cfg.value);
|
|
me.textArea.setHeight(cfg.defaultTextHeight || me.defaultTextHeight);
|
|
me.textArea.show();
|
|
me.textField.hide();
|
|
me.defaultFocus = me.textArea;
|
|
} else {
|
|
me.textField.setValue(cfg.value);
|
|
me.textArea.hide();
|
|
me.textField.show();
|
|
me.defaultFocus = me.textField;
|
|
}
|
|
} else {
|
|
me.textArea.hide();
|
|
me.textField.hide();
|
|
}
|
|
|
|
|
|
if (cfg.progress || cfg.wait) {
|
|
me.progressBar.show();
|
|
me.updateProgress(0, cfg.progressText);
|
|
if(cfg.wait === true){
|
|
me.progressBar.wait(cfg.waitConfig);
|
|
}
|
|
} else {
|
|
me.progressBar.hide();
|
|
}
|
|
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
if (buttons & Math.pow(2, i)) {
|
|
|
|
|
|
if (!me.defaultFocus) {
|
|
me.defaultFocus = me.msgButtons[i];
|
|
}
|
|
me.msgButtons[i].show();
|
|
hideToolbar = false;
|
|
} else {
|
|
me.msgButtons[i].hide();
|
|
}
|
|
}
|
|
|
|
|
|
if (hideToolbar) {
|
|
me.bottomTb.hide();
|
|
} else {
|
|
me.bottomTb.show();
|
|
}
|
|
},
|
|
|
|
|
|
show: function(cfg) {
|
|
var me = this;
|
|
|
|
me.reconfigure(cfg);
|
|
me.addCls(cfg.cls);
|
|
if (cfg.animateTarget) {
|
|
me.doAutoSize(true);
|
|
me.callParent();
|
|
} else {
|
|
me.callParent();
|
|
me.doAutoSize(true);
|
|
}
|
|
return me;
|
|
},
|
|
|
|
afterShow: function(){
|
|
if (this.animateTarget) {
|
|
this.center();
|
|
}
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
doAutoSize: function(center) {
|
|
var me = this,
|
|
icon = me.iconComponent,
|
|
iconHeight = me.iconHeight;
|
|
|
|
if (!Ext.isDefined(me.frameWidth)) {
|
|
me.frameWidth = me.el.getWidth() - me.body.getWidth();
|
|
}
|
|
|
|
|
|
icon.setHeight(iconHeight);
|
|
|
|
|
|
me.minWidth = me.cfg.minWidth || Ext.getClass(this).prototype.minWidth;
|
|
|
|
|
|
|
|
me.topContainer.doLayout();
|
|
if (Ext.isIE6 || Ext.isIEQuirks) {
|
|
|
|
|
|
|
|
me.textField.setCalculatedSize(9);
|
|
me.textArea.setCalculatedSize(9);
|
|
}
|
|
var width = me.cfg.width || me.msg.getWidth() + icon.getWidth() + 25,
|
|
height = (me.header.rendered ? me.header.getHeight() : 0) +
|
|
Math.max(me.promptContainer.getHeight(), icon.getHeight()) +
|
|
me.progressBar.getHeight() +
|
|
(me.bottomTb.rendered ? me.bottomTb.getHeight() : 0) + 20 ;
|
|
|
|
|
|
icon.setHeight(Math.max(iconHeight, me.msg.getHeight()));
|
|
me.setSize(width + me.frameWidth, height + me.frameWidth);
|
|
if (center) {
|
|
me.center();
|
|
}
|
|
return me;
|
|
},
|
|
|
|
updateText: function(text) {
|
|
this.msg.update(text);
|
|
return this.doAutoSize(true);
|
|
},
|
|
|
|
|
|
setIcon : function(icon) {
|
|
var me = this;
|
|
me.iconComponent.removeCls(me.iconCls);
|
|
if (icon) {
|
|
me.iconComponent.show();
|
|
me.iconComponent.addCls(Ext.baseCSSPrefix + 'dlg-icon');
|
|
me.iconComponent.addCls(me.iconCls = icon);
|
|
} else {
|
|
me.iconComponent.removeCls(Ext.baseCSSPrefix + 'dlg-icon');
|
|
me.iconComponent.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: 'ext-mb-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',
|
|
requires: ['Ext.util.MixedCollection', 'Ext.form.action.Load', 'Ext.form.action.Submit',
|
|
'Ext.window.MessageBox', 'Ext.data.Errors', 'Ext.util.DelayedTask'],
|
|
|
|
|
|
constructor: function(owner, config) {
|
|
var me = this,
|
|
onItemAddOrRemove = me.onItemAddOrRemove;
|
|
|
|
|
|
me.owner = owner;
|
|
|
|
|
|
me.mon(owner, {
|
|
add: onItemAddOrRemove,
|
|
remove: onItemAddOrRemove,
|
|
scope: me
|
|
});
|
|
|
|
Ext.apply(me, config);
|
|
|
|
|
|
if (Ext.isString(me.paramOrder)) {
|
|
me.paramOrder = me.paramOrder.split(/[\s,|]/);
|
|
}
|
|
|
|
me.checkValidityTask = Ext.create('Ext.util.DelayedTask', me.checkValidity, me);
|
|
|
|
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() {
|
|
this.clearListeners();
|
|
this.checkValidityTask.cancel();
|
|
},
|
|
|
|
|
|
onItemAddOrRemove: function(parent, child) {
|
|
var me = this,
|
|
isAdding = !!child.ownerCt,
|
|
isContainer = child.isContainer;
|
|
|
|
function handleField(field) {
|
|
|
|
me[isAdding ? 'mon' : 'mun'](field, {
|
|
validitychange: me.checkValidity,
|
|
dirtychange: me.checkDirty,
|
|
scope: me,
|
|
buffer: 100
|
|
});
|
|
|
|
delete me._fields;
|
|
}
|
|
|
|
if (child.isFormField) {
|
|
handleField(child);
|
|
} else if (isContainer) {
|
|
|
|
if (child.isDestroyed) {
|
|
|
|
|
|
delete me._fields;
|
|
} else {
|
|
Ext.Array.forEach(child.query('[isFormField]'), handleField);
|
|
}
|
|
}
|
|
|
|
|
|
delete this._boundItems;
|
|
|
|
|
|
|
|
if (me.initialized) {
|
|
me.checkValidityTask.delay(10);
|
|
}
|
|
},
|
|
|
|
|
|
getFields: function() {
|
|
var fields = this._fields;
|
|
if (!fields) {
|
|
fields = this._fields = Ext.create('Ext.util.MixedCollection');
|
|
fields.addAll(this.owner.query('[isFormField]'));
|
|
}
|
|
return fields;
|
|
},
|
|
|
|
|
|
getBoundItems: function() {
|
|
var boundItems = this._boundItems;
|
|
|
|
if (!boundItems || boundItems.getCount() === 0) {
|
|
boundItems = this._boundItems = Ext.create('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;
|
|
me.batchLayouts(function() {
|
|
invalid = me.getFields().filterBy(function(field) {
|
|
return !field.validate();
|
|
});
|
|
});
|
|
return invalid.length < 1;
|
|
},
|
|
|
|
|
|
checkValidity: function() {
|
|
var me = this,
|
|
valid = !me.hasInvalidField();
|
|
if (valid !== me.wasValid) {
|
|
me.onValidityChange(valid);
|
|
me.fireEvent('validitychange', me, valid);
|
|
me.wasValid = valid;
|
|
}
|
|
},
|
|
|
|
|
|
onValidityChange: function(valid) {
|
|
var boundItems = this.getBoundItems();
|
|
if (boundItems) {
|
|
boundItems.each(function(cmp) {
|
|
if (cmp.disabled === valid) {
|
|
cmp.setDisabled(!valid);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
isDirty: function() {
|
|
return !!this.getFields().findBy(function(f) {
|
|
return f.isDirty();
|
|
});
|
|
},
|
|
|
|
|
|
checkDirty: function() {
|
|
var 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) {
|
|
return this.doAction(this.standardSubmit ? 'standardsubmit' : this.api ? 'directsubmit' : 'submit', options);
|
|
},
|
|
|
|
|
|
load: function(options) {
|
|
return this.doAction(this.api ? 'directload' : 'load', options);
|
|
},
|
|
|
|
|
|
updateRecord: function(record) {
|
|
var fields = record.fields,
|
|
values = this.getFieldValues(),
|
|
name,
|
|
obj = {};
|
|
|
|
fields.each(function(f) {
|
|
name = f.name;
|
|
if (name in values) {
|
|
obj[name] = values[name];
|
|
}
|
|
});
|
|
|
|
record.beginEdit();
|
|
record.set(obj);
|
|
record.endEdit();
|
|
|
|
return this;
|
|
},
|
|
|
|
|
|
loadRecord: function(record) {
|
|
this._record = record;
|
|
return this.setValues(record.data);
|
|
},
|
|
|
|
|
|
getRecord: function() {
|
|
return this._record;
|
|
},
|
|
|
|
|
|
beforeAction: function(action) {
|
|
var waitMsg = action.waitMsg,
|
|
maskCls = Ext.baseCSSPrefix + 'mask-loading',
|
|
waitMsgTarget;
|
|
|
|
|
|
this.getFields().each(function(f) {
|
|
if (f.isFormField && f.syncValue) {
|
|
f.syncValue();
|
|
}
|
|
});
|
|
|
|
if (waitMsg) {
|
|
waitMsgTarget = this.waitMsgTarget;
|
|
if (waitMsgTarget === true) {
|
|
this.owner.el.mask(waitMsg, maskCls);
|
|
} else if (waitMsgTarget) {
|
|
waitMsgTarget = this.waitMsgTarget = Ext.get(waitMsgTarget);
|
|
waitMsgTarget.mask(waitMsg, maskCls);
|
|
} else {
|
|
Ext.MessageBox.wait(waitMsg, action.waitTitle || this.waitTitle);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
afterAction: function(action, success) {
|
|
if (action.waitMsg) {
|
|
var MessageBox = Ext.MessageBox,
|
|
waitMsgTarget = this.waitMsgTarget;
|
|
if (waitMsgTarget === true) {
|
|
this.owner.el.unmask();
|
|
} else if (waitMsgTarget) {
|
|
waitMsgTarget.unmask();
|
|
} else {
|
|
MessageBox.updateProgress(1);
|
|
MessageBox.hide();
|
|
}
|
|
}
|
|
if (success) {
|
|
if (action.reset) {
|
|
this.reset();
|
|
}
|
|
Ext.callback(action.success, action.scope || action, [this, action]);
|
|
this.fireEvent('actioncomplete', this, action);
|
|
} else {
|
|
Ext.callback(action.failure, action.scope || action, [this, action]);
|
|
this.fireEvent('actionfailed', this, action);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
findField: function(id) {
|
|
return this.getFields().findBy(function(f) {
|
|
return f.id === id || f.getName() === id;
|
|
});
|
|
},
|
|
|
|
|
|
|
|
markInvalid: function(errors) {
|
|
var me = this;
|
|
|
|
function mark(fieldId, msg) {
|
|
var field = me.findField(fieldId);
|
|
if (field) {
|
|
field.markInvalid(msg);
|
|
}
|
|
}
|
|
|
|
if (Ext.isArray(errors)) {
|
|
Ext.each(errors, function(err) {
|
|
mark(err.id, err.msg);
|
|
});
|
|
}
|
|
else if (errors instanceof Ext.data.Errors) {
|
|
errors.each(function(err) {
|
|
mark(err.field, err.message);
|
|
});
|
|
}
|
|
else {
|
|
Ext.iterate(errors, mark);
|
|
}
|
|
return this;
|
|
},
|
|
|
|
|
|
setValues: function(values) {
|
|
var me = this;
|
|
|
|
function setVal(fieldId, val) {
|
|
var field = me.findField(fieldId);
|
|
if (field) {
|
|
field.setValue(val);
|
|
if (me.trackResetOnLoad) {
|
|
field.resetOriginalValue();
|
|
}
|
|
}
|
|
}
|
|
|
|
if (Ext.isArray(values)) {
|
|
|
|
Ext.each(values, function(val) {
|
|
setVal(val.id, val.value);
|
|
});
|
|
} else {
|
|
|
|
Ext.iterate(values, setVal);
|
|
}
|
|
return this;
|
|
},
|
|
|
|
|
|
getValues: function(asString, dirtyOnly, includeEmptyText, useDataValues) {
|
|
var values = {};
|
|
|
|
this.getFields().each(function(field) {
|
|
if (!dirtyOnly || field.isDirty()) {
|
|
var data = field[useDataValues ? 'getModelData' : 'getSubmitData'](includeEmptyText);
|
|
if (Ext.isObject(data)) {
|
|
Ext.iterate(data, function(name, val) {
|
|
if (includeEmptyText && val === '') {
|
|
val = field.emptyText || '';
|
|
}
|
|
if (name in values) {
|
|
var bucket = values[name],
|
|
isArray = Ext.isArray;
|
|
if (!isArray(bucket)) {
|
|
bucket = values[name] = [bucket];
|
|
}
|
|
if (isArray(val)) {
|
|
values[name] = bucket.concat(val);
|
|
} else {
|
|
bucket.push(val);
|
|
}
|
|
} else {
|
|
values[name] = val;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
if (asString) {
|
|
values = Ext.Object.toQueryString(values);
|
|
}
|
|
return values;
|
|
},
|
|
|
|
|
|
getFieldValues: function(dirtyOnly) {
|
|
return this.getValues(false, dirtyOnly, false, true);
|
|
},
|
|
|
|
|
|
clearInvalid: function() {
|
|
var me = this;
|
|
me.batchLayouts(function() {
|
|
me.getFields().each(function(f) {
|
|
f.clearInvalid();
|
|
});
|
|
});
|
|
return me;
|
|
},
|
|
|
|
|
|
reset: function() {
|
|
var me = this;
|
|
me.batchLayouts(function() {
|
|
me.getFields().each(function(f) {
|
|
f.reset();
|
|
});
|
|
});
|
|
return me;
|
|
},
|
|
|
|
|
|
applyToFields: function(obj) {
|
|
this.getFields().each(function(f) {
|
|
Ext.apply(f, obj);
|
|
});
|
|
return this;
|
|
},
|
|
|
|
|
|
applyIfToFields: function(obj) {
|
|
this.getFields().each(function(f) {
|
|
Ext.applyIf(f, obj);
|
|
});
|
|
return this;
|
|
},
|
|
|
|
|
|
batchLayouts: function(fn) {
|
|
var me = this,
|
|
suspended = new Ext.util.HashMap();
|
|
|
|
|
|
me.getFields().each(function(field) {
|
|
var ownerCt = field.ownerCt;
|
|
if (!suspended.contains(ownerCt)) {
|
|
suspended.add(ownerCt);
|
|
ownerCt.oldSuspendLayout = ownerCt.suspendLayout;
|
|
ownerCt.suspendLayout = true;
|
|
}
|
|
});
|
|
|
|
|
|
fn();
|
|
|
|
|
|
suspended.each(function(id, ct) {
|
|
ct.suspendLayout = ct.oldSuspendLayout;
|
|
delete ct.oldSuspendLayout;
|
|
});
|
|
|
|
|
|
me.owner.doComponentLayout();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.FieldAncestor', {
|
|
|
|
|
|
|
|
|
|
|
|
initFieldAncestor: function() {
|
|
var me = this,
|
|
onSubtreeChange = me.onFieldAncestorSubtreeChange;
|
|
|
|
me.addEvents(
|
|
|
|
'fieldvaliditychange',
|
|
|
|
|
|
'fielderrorchange'
|
|
);
|
|
|
|
|
|
me.on('add', onSubtreeChange, me);
|
|
me.on('remove', onSubtreeChange, me);
|
|
|
|
me.initFieldDefaults();
|
|
},
|
|
|
|
|
|
initFieldDefaults: function() {
|
|
if (!this.fieldDefaults) {
|
|
this.fieldDefaults = {};
|
|
}
|
|
},
|
|
|
|
|
|
onFieldAncestorSubtreeChange: function(parent, child) {
|
|
var me = this,
|
|
isAdding = !!child.ownerCt;
|
|
|
|
function handleCmp(cmp) {
|
|
var isLabelable = cmp.isFieldLabelable,
|
|
isField = cmp.isFormField;
|
|
if (isLabelable || isField) {
|
|
if (isLabelable) {
|
|
me['onLabelable' + (isAdding ? 'Added' : 'Removed')](cmp);
|
|
}
|
|
if (isField) {
|
|
me['onField' + (isAdding ? 'Added' : 'Removed')](cmp);
|
|
}
|
|
}
|
|
else if (cmp.isContainer) {
|
|
Ext.Array.forEach(cmp.getRefItems(), handleCmp);
|
|
}
|
|
}
|
|
handleCmp(child);
|
|
},
|
|
|
|
|
|
onLabelableAdded: function(labelable) {
|
|
var me = this;
|
|
|
|
|
|
me.mon(labelable, 'errorchange', me.handleFieldErrorChange, me, {buffer: 10});
|
|
|
|
labelable.setFieldDefaults(me.fieldDefaults);
|
|
},
|
|
|
|
|
|
onFieldAdded: function(field) {
|
|
var me = this;
|
|
me.mon(field, 'validitychange', me.handleFieldValidityChange, me);
|
|
},
|
|
|
|
|
|
onLabelableRemoved: function(labelable) {
|
|
var me = this;
|
|
me.mun(labelable, 'errorchange', me.handleFieldErrorChange, me);
|
|
},
|
|
|
|
|
|
onFieldRemoved: function(field) {
|
|
var me = this;
|
|
me.mun(field, 'validitychange', me.handleFieldValidityChange, me);
|
|
},
|
|
|
|
|
|
handleFieldValidityChange: function(field, isValid) {
|
|
var me = this;
|
|
me.fireEvent('fieldvaliditychange', me, field, isValid);
|
|
me.onFieldValidityChange();
|
|
},
|
|
|
|
|
|
handleFieldErrorChange: function(labelable, activeError) {
|
|
var me = this;
|
|
me.fireEvent('fielderrorchange', me, labelable, activeError);
|
|
me.onFieldErrorChange();
|
|
},
|
|
|
|
|
|
onFieldValidityChange: Ext.emptyFn,
|
|
|
|
|
|
onFieldErrorChange: Ext.emptyFn
|
|
|
|
});
|
|
|
|
Ext.define('Ext.layout.container.CheckboxGroup', {
|
|
extend: 'Ext.layout.container.Container',
|
|
alias: ['layout.checkboxgroup'],
|
|
|
|
|
|
onLayout: function() {
|
|
var numCols = this.getColCount(),
|
|
shadowCt = this.getShadowCt(),
|
|
owner = this.owner,
|
|
items = owner.items,
|
|
shadowItems = shadowCt.items,
|
|
numItems = items.length,
|
|
colIndex = 0,
|
|
i, numRows;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
shadowItems.each(function(col) {
|
|
col.items.clear();
|
|
});
|
|
|
|
|
|
|
|
while (shadowItems.length > numCols) {
|
|
shadowCt.remove(shadowItems.last());
|
|
}
|
|
while (shadowItems.length < numCols) {
|
|
shadowCt.add({
|
|
xtype: 'container',
|
|
cls: owner.groupCls,
|
|
flex: 1
|
|
});
|
|
}
|
|
|
|
if (owner.vertical) {
|
|
numRows = Math.ceil(numItems / numCols);
|
|
for (i = 0; i < numItems; i++) {
|
|
if (i > 0 && i % numRows === 0) {
|
|
colIndex++;
|
|
}
|
|
shadowItems.getAt(colIndex).items.add(items.getAt(i));
|
|
}
|
|
} else {
|
|
for (i = 0; i < numItems; i++) {
|
|
colIndex = i % numCols;
|
|
shadowItems.getAt(colIndex).items.add(items.getAt(i));
|
|
}
|
|
}
|
|
|
|
if (!shadowCt.rendered) {
|
|
shadowCt.render(this.getRenderTarget());
|
|
} else {
|
|
|
|
|
|
shadowItems.each(function(col) {
|
|
var layout = col.getLayout();
|
|
layout.renderItems(layout.getLayoutItems(), layout.getRenderTarget());
|
|
});
|
|
}
|
|
|
|
shadowCt.doComponentLayout();
|
|
},
|
|
|
|
|
|
|
|
renderItems: Ext.emptyFn,
|
|
|
|
|
|
|
|
getShadowCt: function() {
|
|
var me = this,
|
|
shadowCt = me.shadowCt,
|
|
owner, items, item, columns, columnsIsArray, numCols, i;
|
|
|
|
if (!shadowCt) {
|
|
|
|
owner = me.owner;
|
|
columns = owner.columns;
|
|
columnsIsArray = Ext.isArray(columns);
|
|
numCols = me.getColCount();
|
|
items = [];
|
|
for(i = 0; i < numCols; i++) {
|
|
item = {
|
|
xtype: 'container',
|
|
cls: owner.groupCls
|
|
};
|
|
if (columnsIsArray) {
|
|
|
|
|
|
if (columns[i] < 1) {
|
|
item.flex = columns[i];
|
|
} else {
|
|
item.width = columns[i];
|
|
}
|
|
}
|
|
else {
|
|
|
|
item.flex = 1;
|
|
}
|
|
items.push(item);
|
|
}
|
|
|
|
|
|
shadowCt = me.shadowCt = Ext.createWidget('container', {
|
|
layout: 'hbox',
|
|
items: items,
|
|
ownerCt: owner
|
|
});
|
|
}
|
|
|
|
return shadowCt;
|
|
},
|
|
|
|
|
|
|
|
getColCount: function() {
|
|
var owner = this.owner,
|
|
colsCfg = owner.columns;
|
|
return Ext.isArray(colsCfg) ? colsCfg.length : (Ext.isNumber(colsCfg) ? colsCfg : owner.items.length);
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.FieldContainer', {
|
|
extend: 'Ext.container.Container',
|
|
mixins: {
|
|
labelable: 'Ext.form.Labelable',
|
|
fieldAncestor: 'Ext.form.FieldAncestor'
|
|
},
|
|
alias: 'widget.fieldcontainer',
|
|
|
|
componentLayout: 'field',
|
|
|
|
|
|
combineLabels: false,
|
|
|
|
|
|
labelConnector: ', ',
|
|
|
|
|
|
combineErrors: false,
|
|
|
|
maskOnDisable: false,
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
onSubCmpAddOrRemove = me.onSubCmpAddOrRemove;
|
|
|
|
|
|
me.initLabelable();
|
|
me.initFieldAncestor();
|
|
|
|
me.callParent();
|
|
},
|
|
|
|
|
|
onLabelableAdded: function(labelable) {
|
|
var me = this;
|
|
me.mixins.fieldAncestor.onLabelableAdded.call(this, labelable);
|
|
me.updateLabel();
|
|
},
|
|
|
|
|
|
onLabelableRemoved: function(labelable) {
|
|
var me = this;
|
|
me.mixins.fieldAncestor.onLabelableRemoved.call(this, labelable);
|
|
me.updateLabel();
|
|
},
|
|
|
|
onRender: function() {
|
|
var me = this;
|
|
|
|
me.onLabelableRender();
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
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());
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
updateLabel: function() {
|
|
var me = this,
|
|
label = me.labelEl;
|
|
if (label) {
|
|
label.update(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 forEach = Ext.Array.forEach,
|
|
errors = [];
|
|
forEach(invalidFields, function(field) {
|
|
forEach(field.getActiveErrors(), function(error) {
|
|
var label = field.getFieldLabel();
|
|
errors.push((label ? label + ': ' : '') + error);
|
|
});
|
|
});
|
|
return errors;
|
|
},
|
|
|
|
getTargetEl: function() {
|
|
return this.bodyEl || this.callParent();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.CheckboxGroup', {
|
|
extend:'Ext.form.FieldContainer',
|
|
mixins: {
|
|
field: 'Ext.form.field.Field'
|
|
},
|
|
alias: 'widget.checkboxgroup',
|
|
requires: ['Ext.layout.container.CheckboxGroup', 'Ext.form.field.Base'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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',
|
|
|
|
|
|
fieldBodyCls: Ext.baseCSSPrefix + 'form-checkboxgroup-body',
|
|
|
|
|
|
layout: 'checkboxgroup',
|
|
|
|
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);
|
|
}
|
|
},
|
|
|
|
|
|
onFieldAdded: function(field) {
|
|
var me = this;
|
|
if (field.isCheckbox) {
|
|
me.mon(field, 'change', me.checkChange, me);
|
|
}
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
onFieldRemoved: function(field) {
|
|
var me = this;
|
|
if (field.isCheckbox) {
|
|
me.mun(field, 'change', me.checkChange, me);
|
|
}
|
|
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() {
|
|
return this.query('[isCheckbox]');
|
|
},
|
|
|
|
|
|
eachBox: function(fn, scope) {
|
|
Ext.Array.forEach(this.getBoxes(), fn, scope || this);
|
|
},
|
|
|
|
|
|
getChecked: function() {
|
|
return Ext.Array.filter(this.getBoxes(), function(cb) {
|
|
return cb.getValue();
|
|
});
|
|
},
|
|
|
|
|
|
isDirty: function(){
|
|
return Ext.Array.some(this.getBoxes(), function(cb) {
|
|
return cb.isDirty();
|
|
});
|
|
},
|
|
|
|
|
|
setReadOnly: function(readOnly) {
|
|
this.eachBox(function(cb) {
|
|
cb.setReadOnly(readOnly);
|
|
});
|
|
this.readOnly = readOnly;
|
|
},
|
|
|
|
|
|
reset: function() {
|
|
var me = this,
|
|
hadError = me.hasActiveError(),
|
|
preventMark = me.preventMark;
|
|
me.preventMark = true;
|
|
me.batchChanges(function() {
|
|
me.eachBox(function(cb) {
|
|
cb.reset();
|
|
});
|
|
});
|
|
me.preventMark = preventMark;
|
|
me.unsetActiveError();
|
|
if (hadError) {
|
|
me.doComponentLayout();
|
|
}
|
|
},
|
|
|
|
|
|
resetOriginalValue: function() {
|
|
|
|
|
|
Ext.defer(function() {
|
|
this.callParent();
|
|
}, 1, this);
|
|
},
|
|
|
|
|
|
|
|
setValue: function(value) {
|
|
var me = this;
|
|
me.batchChanges(function() {
|
|
me.eachBox(function(cb) {
|
|
var name = cb.getName(),
|
|
cbValue = false;
|
|
if (value && name in value) {
|
|
if (Ext.isArray(value[name])) {
|
|
cbValue = Ext.Array.contains(value[name], cb.inputValue);
|
|
} else {
|
|
|
|
cbValue = value[name];
|
|
}
|
|
}
|
|
cb.setValue(cbValue);
|
|
});
|
|
});
|
|
return me;
|
|
},
|
|
|
|
|
|
|
|
getValue: function() {
|
|
var values = {};
|
|
this.eachBox(function(cb) {
|
|
var name = cb.getName(),
|
|
inputValue = cb.inputValue,
|
|
bucket;
|
|
if (cb.getValue()) {
|
|
if (name in values) {
|
|
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 = me.getErrors(),
|
|
isValid = Ext.isEmpty(errors),
|
|
wasValid = !me.hasActiveError();
|
|
|
|
if (isValid) {
|
|
me.unsetActiveError();
|
|
} else {
|
|
me.setActiveError(errors);
|
|
}
|
|
if (isValid !== wasValid) {
|
|
me.fireEvent('validitychange', me, isValid);
|
|
me.doComponentLayout();
|
|
}
|
|
|
|
return isValid;
|
|
}
|
|
|
|
}, function() {
|
|
|
|
this.borrow(Ext.form.field.Base, ['markInvalid', 'clearInvalid']);
|
|
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.form.CheckboxManager', {
|
|
extend: 'Ext.util.MixedCollection',
|
|
singleton: true,
|
|
|
|
getByName: function(name) {
|
|
return this.filterBy(function(item) {
|
|
return item.name == name;
|
|
});
|
|
},
|
|
|
|
getWithValue: function(name, value) {
|
|
return this.filterBy(function(item) {
|
|
return item.name == name && item.inputValue == value;
|
|
});
|
|
},
|
|
|
|
getChecked: function(name) {
|
|
return this.filterBy(function(item) {
|
|
return item.name == name && item.checked;
|
|
});
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.FieldSet', {
|
|
extend: 'Ext.container.Container',
|
|
alias: 'widget.fieldset',
|
|
uses: ['Ext.form.field.Checkbox', 'Ext.panel.Tool', 'Ext.layout.container.Anchor', 'Ext.layout.component.FieldSet'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
collapsed: false,
|
|
|
|
|
|
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'fieldset',
|
|
|
|
|
|
layout: 'anchor',
|
|
|
|
componentLayout: 'fieldset',
|
|
|
|
|
|
ariaRole: '',
|
|
|
|
renderTpl: ['<div id="{id}-body" class="{baseCls}-body"></div>'],
|
|
|
|
maskOnDisable: false,
|
|
|
|
getElConfig: function(){
|
|
return {tag: 'fieldset', id: this.id};
|
|
},
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
baseCls = me.baseCls;
|
|
|
|
me.callParent();
|
|
|
|
|
|
me.initLegend();
|
|
|
|
|
|
me.addChildEls('body');
|
|
|
|
if (me.collapsed) {
|
|
me.addCls(baseCls + '-collapsed');
|
|
me.collapse();
|
|
}
|
|
},
|
|
|
|
|
|
onRender: function(container, position) {
|
|
this.callParent(arguments);
|
|
|
|
this.initLegend();
|
|
},
|
|
|
|
|
|
initLegend: function() {
|
|
var me = this,
|
|
legendItems,
|
|
legend = me.legend;
|
|
|
|
|
|
if (!legend && (me.title || me.checkboxToggle || me.collapsible)) {
|
|
legendItems = [];
|
|
|
|
|
|
if (me.checkboxToggle) {
|
|
legendItems.push(me.createCheckboxCmp());
|
|
}
|
|
|
|
else if (me.collapsible) {
|
|
legendItems.push(me.createToggleCmp());
|
|
}
|
|
|
|
|
|
legendItems.push(me.createTitleCmp());
|
|
|
|
legend = me.legend = Ext.create('Ext.container.Container', {
|
|
baseCls: me.baseCls + '-header',
|
|
ariaRole: '',
|
|
ownerCt: this,
|
|
getElConfig: function(){
|
|
var result = {
|
|
tag: 'legend',
|
|
cls: this.baseCls
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
if (!Ext.isGecko3) {
|
|
result.children = [{
|
|
cls: Ext.baseCSSPrefix + 'clear'
|
|
}];
|
|
}
|
|
return result;
|
|
},
|
|
items: legendItems
|
|
});
|
|
}
|
|
|
|
|
|
if (legend && !legend.rendered && me.rendered) {
|
|
me.legend.render(me.el, me.body);
|
|
}
|
|
},
|
|
|
|
|
|
createTitleCmp: function() {
|
|
var me = this;
|
|
me.titleCmp = Ext.create('Ext.Component', {
|
|
html: me.title,
|
|
getElConfig: function() {
|
|
return {
|
|
tag: Ext.isGecko3 ? 'span' : 'div',
|
|
cls: me.titleCmp.cls,
|
|
id: me.titleCmp.id
|
|
};
|
|
},
|
|
cls: me.baseCls + '-header-text'
|
|
});
|
|
return me.titleCmp;
|
|
},
|
|
|
|
|
|
|
|
|
|
createCheckboxCmp: function() {
|
|
var me = this,
|
|
suffix = '-checkbox';
|
|
|
|
me.checkboxCmp = Ext.create('Ext.form.field.Checkbox', {
|
|
getElConfig: function() {
|
|
return {
|
|
tag: Ext.isGecko3 ? 'span' : 'div',
|
|
id: me.checkboxCmp.id,
|
|
cls: me.checkboxCmp.cls
|
|
};
|
|
},
|
|
name: me.checkboxName || me.id + suffix,
|
|
cls: me.baseCls + '-header' + suffix,
|
|
checked: !me.collapsed,
|
|
listeners: {
|
|
change: me.onCheckChange,
|
|
scope: me
|
|
}
|
|
});
|
|
return me.checkboxCmp;
|
|
},
|
|
|
|
|
|
|
|
|
|
createToggleCmp: function() {
|
|
var me = this;
|
|
me.toggleCmp = Ext.create('Ext.panel.Tool', {
|
|
getElConfig: function() {
|
|
return {
|
|
tag: Ext.isGecko3 ? 'span' : 'div',
|
|
id: me.toggleCmp.id,
|
|
cls: me.toggleCmp.cls
|
|
};
|
|
},
|
|
type: 'toggle',
|
|
handler: me.toggle,
|
|
scope: me
|
|
});
|
|
return me.toggleCmp;
|
|
},
|
|
|
|
|
|
setTitle: function(title) {
|
|
var me = this;
|
|
me.title = title;
|
|
me.initLegend();
|
|
me.titleCmp.update(title);
|
|
return me;
|
|
},
|
|
|
|
getTargetEl : function() {
|
|
return this.body || this.frameBody || this.el;
|
|
},
|
|
|
|
getContentTarget: function() {
|
|
return this.body;
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
expand : function(){
|
|
return this.setExpanded(true);
|
|
},
|
|
|
|
|
|
collapse : function() {
|
|
return this.setExpanded(false);
|
|
},
|
|
|
|
|
|
setExpanded: function(expanded) {
|
|
var me = this,
|
|
checkboxCmp = me.checkboxCmp;
|
|
|
|
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) {
|
|
|
|
me.getComponentLayout().childrenChanged = true;
|
|
}
|
|
me.doComponentLayout();
|
|
return me;
|
|
},
|
|
|
|
|
|
toggle: function() {
|
|
this.setExpanded(!!this.collapsed);
|
|
},
|
|
|
|
|
|
onCheckChange: function(cmp, checked) {
|
|
this.setExpanded(checked);
|
|
},
|
|
|
|
beforeDestroy : function() {
|
|
var legend = this.legend;
|
|
if (legend) {
|
|
legend.destroy();
|
|
}
|
|
this.callParent();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.Label', {
|
|
extend:'Ext.Component',
|
|
alias: 'widget.label',
|
|
requires: ['Ext.util.Format'],
|
|
|
|
|
|
|
|
|
|
|
|
maskOnDisable: false,
|
|
getElConfig: function(){
|
|
var me = this;
|
|
return {
|
|
tag: 'label',
|
|
id: me.id,
|
|
htmlFor: me.forId || '',
|
|
html: me.text ? Ext.util.Format.htmlEncode(me.text) : (me.html || '')
|
|
};
|
|
},
|
|
|
|
|
|
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;
|
|
}
|
|
return this;
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.form.Panel', {
|
|
extend:'Ext.panel.Panel',
|
|
mixins: {
|
|
fieldAncestor: 'Ext.form.FieldAncestor'
|
|
},
|
|
alias: 'widget.form',
|
|
alternateClassName: ['Ext.FormPanel', 'Ext.form.FormPanel'],
|
|
requires: ['Ext.form.Basic', 'Ext.util.TaskRunner'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
layout: 'anchor',
|
|
|
|
ariaRole: 'form',
|
|
|
|
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() {
|
|
|
|
var me = this;
|
|
|
|
me.form = me.createForm();
|
|
me.callParent();
|
|
me.form.initialize();
|
|
},
|
|
|
|
|
|
createForm: function() {
|
|
return Ext.create('Ext.form.Basic', this, Ext.applyIf({listeners: {}}, this.initialConfig));
|
|
},
|
|
|
|
|
|
getForm: function() {
|
|
return this.form;
|
|
},
|
|
|
|
|
|
loadRecord: function(record) {
|
|
return this.getForm().loadRecord(record);
|
|
},
|
|
|
|
|
|
getRecord: function() {
|
|
return this.getForm().getRecord();
|
|
},
|
|
|
|
|
|
getValues: function() {
|
|
return this.getForm().getValues();
|
|
},
|
|
|
|
beforeDestroy: function() {
|
|
this.stopPolling();
|
|
this.form.destroy();
|
|
this.callParent();
|
|
},
|
|
|
|
|
|
load: function(options) {
|
|
this.form.load(options);
|
|
},
|
|
|
|
|
|
submit: function(options) {
|
|
this.form.submit(options);
|
|
},
|
|
|
|
|
|
disable: function(silent) {
|
|
this.callParent(arguments);
|
|
this.form.getFields().each(function(field) {
|
|
field.disable();
|
|
});
|
|
},
|
|
|
|
|
|
enable: function(silent) {
|
|
this.callParent(arguments);
|
|
this.form.getFields().each(function(field) {
|
|
field.enable();
|
|
});
|
|
},
|
|
|
|
|
|
startPolling: function(interval) {
|
|
this.stopPolling();
|
|
var task = Ext.create('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() {
|
|
this.form.getFields().each(function(field) {
|
|
field.checkChange();
|
|
});
|
|
}
|
|
});
|
|
|
|
|
|
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',
|
|
|
|
getBoxes: function() {
|
|
return this.query('[isRadio]');
|
|
},
|
|
|
|
|
|
setValue: function(value) {
|
|
var me = this;
|
|
if (Ext.isObject(value)) {
|
|
Ext.Object.each(value, function(name, cbValue) {
|
|
var radios = Ext.form.RadioManager.getWithValue(name, cbValue);
|
|
radios.each(function(cb) {
|
|
cb.setValue(true);
|
|
});
|
|
});
|
|
}
|
|
return me;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.RadioManager', {
|
|
extend: 'Ext.util.MixedCollection',
|
|
singleton: true,
|
|
|
|
getByName: function(name) {
|
|
return this.filterBy(function(item) {
|
|
return item.name == name;
|
|
});
|
|
},
|
|
|
|
getWithValue: function(name, value) {
|
|
return this.filterBy(function(item) {
|
|
return item.name == name && item.inputValue == value;
|
|
});
|
|
},
|
|
|
|
getChecked: function(name) {
|
|
return this.findBy(function(item) {
|
|
return item.name == name && item.checked;
|
|
});
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.action.DirectLoad', {
|
|
extend:'Ext.form.action.Load',
|
|
requires: ['Ext.direct.Manager'],
|
|
alternateClassName: 'Ext.form.Action.DirectLoad',
|
|
alias: 'formaction.directload',
|
|
|
|
type: 'directload',
|
|
|
|
run: function() {
|
|
this.form.api.load.apply(window, this.getArgs());
|
|
},
|
|
|
|
|
|
getArgs: function() {
|
|
var me = this,
|
|
args = [],
|
|
form = me.form,
|
|
paramOrder = form.paramOrder,
|
|
params = me.getParams(),
|
|
i, len;
|
|
|
|
|
|
if (paramOrder) {
|
|
for (i = 0, len = paramOrder.length; i < len; i++) {
|
|
args.push(params[paramOrder[i]]);
|
|
}
|
|
}
|
|
|
|
else if (form.paramsAsHash) {
|
|
args.push(params);
|
|
}
|
|
|
|
|
|
args.push(me.onSuccess, me);
|
|
|
|
return args;
|
|
},
|
|
|
|
|
|
|
|
|
|
processResponse: function(result) {
|
|
return (this.result = result);
|
|
},
|
|
|
|
onSuccess: function(result, trans) {
|
|
if (trans.type == Ext.direct.Manager.self.exceptions.SERVER) {
|
|
result = {};
|
|
}
|
|
this.callParent([result]);
|
|
}
|
|
});
|
|
|
|
|
|
|
|
|
|
Ext.define('Ext.form.action.DirectSubmit', {
|
|
extend:'Ext.form.action.Submit',
|
|
requires: ['Ext.direct.Manager'],
|
|
alternateClassName: 'Ext.form.Action.DirectSubmit',
|
|
alias: 'formaction.directsubmit',
|
|
|
|
type: 'directsubmit',
|
|
|
|
doSubmit: function() {
|
|
var me = this,
|
|
callback = Ext.Function.bind(me.onSuccess, me),
|
|
formEl = me.buildForm();
|
|
me.form.api.submit(formEl, callback, me);
|
|
Ext.removeNode(formEl);
|
|
},
|
|
|
|
|
|
|
|
|
|
processResponse: function(result) {
|
|
return (this.result = result);
|
|
},
|
|
|
|
onSuccess: function(response, trans) {
|
|
if (trans.type === Ext.direct.Manager.self.exceptions.SERVER) {
|
|
response = {};
|
|
}
|
|
this.callParent([response]);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.action.StandardSubmit', {
|
|
extend:'Ext.form.action.Submit',
|
|
alias: 'formaction.standardsubmit',
|
|
|
|
|
|
|
|
|
|
doSubmit: function() {
|
|
var form = this.buildForm();
|
|
form.submit();
|
|
Ext.removeNode(form);
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.field.Checkbox', {
|
|
extend: 'Ext.form.field.Base',
|
|
alias: ['widget.checkboxfield', 'widget.checkbox'],
|
|
alternateClassName: 'Ext.form.Checkbox',
|
|
requires: ['Ext.XTemplate', 'Ext.form.CheckboxManager'],
|
|
|
|
|
|
fieldSubTpl: [
|
|
'<tpl if="boxLabel && boxLabelAlign == \'before\'">',
|
|
'<label id="{cmpId}-boxLabelEl" class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
|
|
'</tpl>',
|
|
|
|
|
|
|
|
'<input type="button" id="{id}" ',
|
|
'<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
|
|
'class="{fieldCls} {typeCls}" autocomplete="off" hidefocus="true" />',
|
|
'<tpl if="boxLabel && boxLabelAlign == \'after\'">',
|
|
'<label id="{cmpId}-boxLabelEl" class="{boxLabelCls} {boxLabelCls}-{boxLabelAlign}" for="{id}">{boxLabel}</label>',
|
|
'</tpl>',
|
|
{
|
|
disableFormats: true,
|
|
compiled: true
|
|
}
|
|
],
|
|
|
|
isCheckbox: true,
|
|
|
|
|
|
focusCls: Ext.baseCSSPrefix + 'form-cb-focus',
|
|
|
|
|
|
|
|
|
|
fieldBodyCls: Ext.baseCSSPrefix + 'form-cb-wrap',
|
|
|
|
|
|
checked: false,
|
|
|
|
|
|
checkedCls: Ext.baseCSSPrefix + 'form-cb-checked',
|
|
|
|
|
|
|
|
|
|
boxLabelCls: Ext.baseCSSPrefix + 'form-cb-label',
|
|
|
|
|
|
boxLabelAlign: 'after',
|
|
|
|
|
|
inputValue: 'on',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
checkChangeEvents: [],
|
|
inputType: 'checkbox',
|
|
ariaRole: 'checkbox',
|
|
|
|
|
|
onRe: /^on$/i,
|
|
|
|
initComponent: function(){
|
|
this.callParent(arguments);
|
|
this.getManager().add(this);
|
|
},
|
|
|
|
initValue: function() {
|
|
var me = this,
|
|
checked = !!me.checked;
|
|
|
|
|
|
me.originalValue = me.lastValue = checked;
|
|
|
|
|
|
me.setValue(checked);
|
|
},
|
|
|
|
|
|
onRender : function(ct, position) {
|
|
var me = this;
|
|
|
|
|
|
me.addChildEls('boxLabelEl');
|
|
|
|
Ext.applyIf(me.subTplData, {
|
|
boxLabel: me.boxLabel,
|
|
boxLabelCls: me.boxLabelCls,
|
|
boxLabelAlign: me.boxLabelAlign
|
|
});
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
initEvents: function() {
|
|
var me = this;
|
|
me.callParent();
|
|
me.mon(me.inputEl, 'click', me.onBoxClick, me);
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
setRawValue: function(value) {
|
|
var me = this,
|
|
inputEl = me.inputEl,
|
|
inputValue = me.inputValue,
|
|
checked = (value === true || value === 'true' || value === '1' || value === 1 ||
|
|
(((Ext.isString(value) || Ext.isNumber(value)) && inputValue) ? value == inputValue : me.onRe.test(value)));
|
|
|
|
if (inputEl) {
|
|
inputEl.dom.setAttribute('aria-checked', checked);
|
|
me[checked ? 'addCls' : 'removeCls'](me.checkedCls);
|
|
}
|
|
|
|
me.checked = me.rawValue = checked;
|
|
return checked;
|
|
},
|
|
|
|
|
|
setValue: function(checked) {
|
|
var me = this;
|
|
|
|
|
|
|
|
|
|
|
|
if (Ext.isArray(checked)) {
|
|
me.getManager().getByName(me.name).each(function(cb) {
|
|
cb.setValue(Ext.Array.contains(checked, cb.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);
|
|
},
|
|
|
|
|
|
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.readOnly = readOnly;
|
|
},
|
|
|
|
|
|
|
|
getBodyNaturalWidth: function() {
|
|
var me = this,
|
|
bodyEl = me.bodyEl,
|
|
ws = 'white-space',
|
|
width;
|
|
bodyEl.setStyle(ws, 'nowrap');
|
|
width = bodyEl.getWidth();
|
|
bodyEl.setStyle(ws, '');
|
|
return width;
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.layout.component.field.Trigger', {
|
|
|
|
|
|
|
|
alias: ['layout.triggerfield'],
|
|
|
|
extend: 'Ext.layout.component.field.Field',
|
|
|
|
|
|
|
|
type: 'triggerfield',
|
|
|
|
sizeBodyContents: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
inputEl = owner.inputEl,
|
|
triggerWrap = owner.triggerWrap,
|
|
triggerWidth = owner.getTriggerWidth();
|
|
|
|
|
|
|
|
if (owner.hideTrigger || owner.readOnly || triggerWidth > 0) {
|
|
|
|
|
|
me.setElementSize(inputEl, Ext.isNumber(width) ? width - triggerWidth : width);
|
|
|
|
|
|
triggerWrap.setWidth(triggerWidth);
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.view.View', {
|
|
extend: 'Ext.view.AbstractView',
|
|
alternateClassName: 'Ext.DataView',
|
|
alias: 'widget.dataview',
|
|
|
|
inheritableStatics: {
|
|
EventMap: {
|
|
mousedown: 'MouseDown',
|
|
mouseup: 'MouseUp',
|
|
click: 'Click',
|
|
dblclick: 'DblClick',
|
|
contextmenu: 'ContextMenu',
|
|
mouseover: 'MouseOver',
|
|
mouseout: 'MouseOut',
|
|
mouseenter: 'MouseEnter',
|
|
mouseleave: 'MouseLeave',
|
|
keydown: 'KeyDown',
|
|
focus: 'Focus'
|
|
}
|
|
},
|
|
|
|
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'
|
|
);
|
|
},
|
|
|
|
afterRender: function(){
|
|
var me = this,
|
|
listeners;
|
|
|
|
me.callParent();
|
|
|
|
listeners = {
|
|
scope: me,
|
|
|
|
freezeEvent: true,
|
|
click: me.handleEvent,
|
|
mousedown: me.handleEvent,
|
|
mouseup: me.handleEvent,
|
|
dblclick: me.handleEvent,
|
|
contextmenu: me.handleEvent,
|
|
mouseover: me.handleEvent,
|
|
mouseout: me.handleEvent,
|
|
keydown: me.handleEvent
|
|
};
|
|
|
|
me.mon(me.getTargetEl(), listeners);
|
|
|
|
if (me.store) {
|
|
me.bindStore(me.store, true);
|
|
}
|
|
},
|
|
|
|
handleEvent: function(e) {
|
|
if (this.processUIEvent(e) !== false) {
|
|
this.processSpecialEvent(e);
|
|
}
|
|
},
|
|
|
|
|
|
processItemEvent: Ext.emptyFn,
|
|
processContainerEvent: Ext.emptyFn,
|
|
processSpecialEvent: Ext.emptyFn,
|
|
|
|
|
|
stillOverItem: function (event, overItem) {
|
|
var nowOver;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (overItem && typeof(overItem.offsetParent) === "object") {
|
|
|
|
|
|
nowOver = (event.type == 'mouseout') ? event.getRelatedTarget() : event.getTarget();
|
|
return Ext.fly(overItem).contains(nowOver);
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
processUIEvent: function(e) {
|
|
var me = this,
|
|
item = e.getTarget(me.getItemSelector(), me.getTargetEl()),
|
|
map = this.statics().EventMap,
|
|
index, record,
|
|
type = e.type,
|
|
overItem = me.mouseOverItem,
|
|
newType;
|
|
|
|
if (!item) {
|
|
if (type == 'mouseover' && me.stillOverItem(e, overItem)) {
|
|
item = overItem;
|
|
}
|
|
|
|
|
|
if (type == 'keydown') {
|
|
record = me.getSelectionModel().getLastSelected();
|
|
if (record) {
|
|
item = me.getNode(record);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (item) {
|
|
index = me.indexOf(item);
|
|
if (!record) {
|
|
record = me.getRecord(item);
|
|
}
|
|
|
|
if (me.processItemEvent(record, item, index, e) === false) {
|
|
return false;
|
|
}
|
|
|
|
newType = me.isNewItemEvent(item, e);
|
|
if (newType === 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;
|
|
},
|
|
|
|
isNewItemEvent: function (item, e) {
|
|
var me = this,
|
|
overItem = me.mouseOverItem,
|
|
type = e.type;
|
|
|
|
switch (type) {
|
|
case 'mouseover':
|
|
if (item === overItem) {
|
|
return false;
|
|
}
|
|
me.mouseOverItem = item;
|
|
return 'mouseenter';
|
|
|
|
case 'mouseout':
|
|
|
|
if (me.stillOverItem(e, overItem)) {
|
|
return false;
|
|
}
|
|
me.mouseOverItem = null;
|
|
return 'mouseleave';
|
|
}
|
|
return type;
|
|
},
|
|
|
|
|
|
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,
|
|
|
|
|
|
highlightItem: function(item) {
|
|
var me = this;
|
|
me.clearHighlight();
|
|
me.highlightedItem = item;
|
|
Ext.fly(item).addCls(me.overItemCls);
|
|
},
|
|
|
|
|
|
clearHighlight: function() {
|
|
var me = this,
|
|
highlighted = me.highlightedItem;
|
|
|
|
if (highlighted) {
|
|
Ext.fly(highlighted).removeCls(me.overItemCls);
|
|
delete me.highlightedItem;
|
|
}
|
|
},
|
|
|
|
refresh: function() {
|
|
var me = this;
|
|
me.clearHighlight();
|
|
me.callParent(arguments);
|
|
if (!me.isFixedHeight()) {
|
|
me.doComponentLayout();
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.layout.component.BoundList', {
|
|
extend: 'Ext.layout.component.Component',
|
|
alias: 'layout.boundlist',
|
|
|
|
type: 'component',
|
|
|
|
beforeLayout: function() {
|
|
return this.callParent(arguments) || this.owner.refreshed > 0;
|
|
},
|
|
|
|
onLayout : function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
floating = owner.floating,
|
|
el = owner.el,
|
|
xy = el.getXY(),
|
|
isNumber = Ext.isNumber,
|
|
minWidth, maxWidth, minHeight, maxHeight,
|
|
naturalWidth, naturalHeight, constrainedWidth, constrainedHeight, undef;
|
|
|
|
if (floating) {
|
|
|
|
el.setXY([-9999,-9999]);
|
|
}
|
|
|
|
|
|
me.setTargetSize(width, height);
|
|
|
|
|
|
if (!isNumber(width)) {
|
|
minWidth = owner.minWidth;
|
|
maxWidth = owner.maxWidth;
|
|
if (isNumber(minWidth) || isNumber(maxWidth)) {
|
|
naturalWidth = el.getWidth();
|
|
if (naturalWidth < minWidth) {
|
|
constrainedWidth = minWidth;
|
|
}
|
|
else if (naturalWidth > maxWidth) {
|
|
constrainedWidth = maxWidth;
|
|
}
|
|
if (constrainedWidth) {
|
|
me.setTargetSize(constrainedWidth);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!isNumber(height)) {
|
|
minHeight = owner.minHeight;
|
|
maxHeight = owner.maxHeight;
|
|
if (isNumber(minHeight) || isNumber(maxHeight)) {
|
|
naturalHeight = el.getHeight();
|
|
if (naturalHeight < minHeight) {
|
|
constrainedHeight = minHeight;
|
|
}
|
|
else if (naturalHeight > maxHeight) {
|
|
constrainedHeight = maxHeight;
|
|
}
|
|
if (constrainedHeight) {
|
|
me.setTargetSize(undef, constrainedHeight);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (floating) {
|
|
|
|
el.setXY(xy);
|
|
}
|
|
},
|
|
|
|
afterLayout: function() {
|
|
var me = this,
|
|
toolbar = me.owner.pagingToolbar;
|
|
me.callParent();
|
|
if (toolbar) {
|
|
toolbar.doComponentLayout();
|
|
}
|
|
},
|
|
|
|
setTargetSize : function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
listHeight = null,
|
|
toolbar;
|
|
|
|
|
|
if (Ext.isNumber(height)) {
|
|
listHeight = height - owner.el.getFrameWidth('tb');
|
|
toolbar = owner.pagingToolbar;
|
|
if (toolbar) {
|
|
listHeight -= toolbar.getHeight();
|
|
}
|
|
}
|
|
me.setElementSize(owner.listEl, null, listHeight);
|
|
|
|
me.callParent(arguments);
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.toolbar.TextItem', {
|
|
extend: 'Ext.toolbar.Item',
|
|
requires: ['Ext.XTemplate'],
|
|
alias: 'widget.tbtext',
|
|
alternateClassName: 'Ext.Toolbar.TextItem',
|
|
|
|
|
|
text: '',
|
|
|
|
renderTpl: '{text}',
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'toolbar-text',
|
|
|
|
onRender : function() {
|
|
Ext.apply(this.renderData, {
|
|
text: this.text
|
|
});
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
setText : function(t) {
|
|
if (this.rendered) {
|
|
this.el.update(t);
|
|
this.ownerCt.doLayout();
|
|
} else {
|
|
this.text = t;
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.form.field.Trigger', {
|
|
extend:'Ext.form.field.Text',
|
|
alias: ['widget.triggerfield', 'widget.trigger'],
|
|
requires: ['Ext.DomHelper', 'Ext.util.ClickRepeater', 'Ext.layout.component.field.Trigger'],
|
|
alternateClassName: ['Ext.form.TriggerField', 'Ext.form.TwinTriggerField', 'Ext.form.Trigger'],
|
|
|
|
|
|
fieldSubTpl: [
|
|
'<input id="{id}" type="{type}" ',
|
|
'<tpl if="name">name="{name}" </tpl>',
|
|
'<tpl if="size">size="{size}" </tpl>',
|
|
'<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
|
|
'class="{fieldCls} {typeCls}" autocomplete="off" />',
|
|
'<div id="{cmpId}-triggerWrap" class="{triggerWrapCls}" role="presentation">',
|
|
'{triggerEl}',
|
|
'<div class="{clearCls}" role="presentation"></div>',
|
|
'</div>',
|
|
{
|
|
compiled: true,
|
|
disableFormats: true
|
|
}
|
|
],
|
|
|
|
|
|
|
|
|
|
triggerBaseCls: Ext.baseCSSPrefix + 'form-trigger',
|
|
|
|
|
|
triggerWrapCls: Ext.baseCSSPrefix + 'form-trigger-wrap',
|
|
|
|
|
|
hideTrigger: false,
|
|
|
|
|
|
editable: true,
|
|
|
|
|
|
readOnly: false,
|
|
|
|
|
|
|
|
|
|
repeatTriggerClick: false,
|
|
|
|
|
|
|
|
autoSize: Ext.emptyFn,
|
|
|
|
monitorTab: true,
|
|
|
|
mimicing: false,
|
|
|
|
triggerIndexRe: /trigger-index-(\d+)/,
|
|
|
|
componentLayout: 'triggerfield',
|
|
|
|
initComponent: function() {
|
|
this.wrapFocusCls = this.triggerWrapCls + '-focus';
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
onRender: function(ct, position) {
|
|
var me = this,
|
|
triggerCls,
|
|
triggerBaseCls = me.triggerBaseCls,
|
|
triggerWrapCls = me.triggerWrapCls,
|
|
triggerConfigs = [],
|
|
i;
|
|
|
|
|
|
|
|
|
|
|
|
if (!me.trigger1Cls) {
|
|
me.trigger1Cls = me.triggerCls;
|
|
}
|
|
|
|
|
|
for (i = 0; (triggerCls = me['trigger' + (i + 1) + 'Cls']) || i < 1; i++) {
|
|
triggerConfigs.push({
|
|
cls: [Ext.baseCSSPrefix + 'trigger-index-' + i, triggerBaseCls, triggerCls].join(' '),
|
|
role: 'button'
|
|
});
|
|
}
|
|
triggerConfigs[i - 1].cls += ' ' + triggerBaseCls + '-last';
|
|
|
|
|
|
me.addChildEls('triggerWrap');
|
|
|
|
Ext.applyIf(me.subTplData, {
|
|
triggerWrapCls: triggerWrapCls,
|
|
triggerEl: Ext.DomHelper.markup(triggerConfigs),
|
|
clearCls: me.clearCls
|
|
});
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
me.triggerEl = Ext.select('.' + triggerBaseCls, true, me.triggerWrap.dom);
|
|
|
|
me.doc = Ext.getDoc();
|
|
me.initTrigger();
|
|
},
|
|
|
|
onEnable: function() {
|
|
this.callParent();
|
|
this.triggerWrap.unmask();
|
|
},
|
|
|
|
onDisable: function() {
|
|
this.callParent();
|
|
this.triggerWrap.mask();
|
|
},
|
|
|
|
afterRender: function() {
|
|
this.callParent();
|
|
this.updateEditState();
|
|
this.triggerEl.unselectable();
|
|
},
|
|
|
|
updateEditState: function() {
|
|
var me = this,
|
|
inputEl = me.inputEl,
|
|
triggerWrap = me.triggerWrap,
|
|
noeditCls = Ext.baseCSSPrefix + 'trigger-noedit',
|
|
displayed,
|
|
readOnly;
|
|
|
|
if (me.rendered) {
|
|
if (me.readOnly) {
|
|
inputEl.addCls(noeditCls);
|
|
readOnly = true;
|
|
displayed = false;
|
|
} else {
|
|
if (me.editable) {
|
|
inputEl.removeCls(noeditCls);
|
|
readOnly = false;
|
|
} else {
|
|
inputEl.addCls(noeditCls);
|
|
readOnly = true;
|
|
}
|
|
displayed = !me.hideTrigger;
|
|
}
|
|
|
|
triggerWrap.setDisplayed(displayed);
|
|
inputEl.dom.readOnly = readOnly;
|
|
me.doComponentLayout();
|
|
}
|
|
},
|
|
|
|
|
|
getTriggerWidth: function() {
|
|
var me = this,
|
|
triggerWrap = me.triggerWrap,
|
|
totalTriggerWidth = 0;
|
|
if (triggerWrap && !me.hideTrigger && !me.readOnly) {
|
|
me.triggerEl.each(function(trigger) {
|
|
totalTriggerWidth += trigger.getWidth();
|
|
});
|
|
totalTriggerWidth += me.triggerWrap.getFrameWidth('lr');
|
|
}
|
|
return totalTriggerWidth;
|
|
},
|
|
|
|
setHideTrigger: function(hideTrigger) {
|
|
if (hideTrigger != this.hideTrigger) {
|
|
this.hideTrigger = hideTrigger;
|
|
this.updateEditState();
|
|
}
|
|
},
|
|
|
|
|
|
setEditable: function(editable) {
|
|
if (editable != this.editable) {
|
|
this.editable = editable;
|
|
this.updateEditState();
|
|
}
|
|
},
|
|
|
|
|
|
setReadOnly: function(readOnly) {
|
|
if (readOnly != this.readOnly) {
|
|
this.readOnly = readOnly;
|
|
this.updateEditState();
|
|
}
|
|
},
|
|
|
|
|
|
initTrigger: function() {
|
|
var me = this,
|
|
triggerWrap = me.triggerWrap,
|
|
triggerEl = me.triggerEl;
|
|
|
|
if (me.repeatTriggerClick) {
|
|
me.triggerRepeater = Ext.create('Ext.util.ClickRepeater', triggerWrap, {
|
|
preventDefault: true,
|
|
handler: function(cr, e) {
|
|
me.onTriggerWrapClick(e);
|
|
}
|
|
});
|
|
} else {
|
|
me.mon(me.triggerWrap, 'click', me.onTriggerWrapClick, me);
|
|
}
|
|
|
|
triggerEl.addClsOnOver(me.triggerBaseCls + '-over');
|
|
triggerEl.each(function(el, c, i) {
|
|
el.addClsOnOver(me['trigger' + (i + 1) + 'Cls'] + '-over');
|
|
});
|
|
triggerEl.addClsOnClick(me.triggerBaseCls + '-click');
|
|
triggerEl.each(function(el, c, i) {
|
|
el.addClsOnClick(me['trigger' + (i + 1) + 'Cls'] + '-click');
|
|
});
|
|
},
|
|
|
|
|
|
onDestroy: function() {
|
|
var me = this;
|
|
Ext.destroyMembers(me, 'triggerRepeater', 'triggerWrap', 'triggerEl');
|
|
delete me.doc;
|
|
me.callParent();
|
|
},
|
|
|
|
|
|
onFocus: function() {
|
|
var me = this;
|
|
me.callParent();
|
|
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();
|
|
}
|
|
},
|
|
|
|
|
|
onBlur: Ext.emptyFn,
|
|
|
|
|
|
mimicBlur: function(e) {
|
|
if (!this.isDestroyed && !this.bodyEl.contains(e.target) && this.validateBlur(e)) {
|
|
this.triggerBlur();
|
|
}
|
|
},
|
|
|
|
|
|
triggerBlur: function() {
|
|
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);
|
|
if (me.bodyEl) {
|
|
me.bodyEl.removeCls(me.wrapFocusCls);
|
|
}
|
|
},
|
|
|
|
beforeBlur: Ext.emptyFn,
|
|
|
|
|
|
|
|
validateBlur: function(e) {
|
|
return true;
|
|
},
|
|
|
|
|
|
|
|
|
|
onTriggerWrapClick: function(e) {
|
|
var me = this,
|
|
t = e && e.getTarget('.' + Ext.baseCSSPrefix + 'form-trigger', null),
|
|
match = t && t.className.match(me.triggerIndexRe),
|
|
idx,
|
|
triggerClickMethod;
|
|
|
|
if (match && !me.readOnly) {
|
|
idx = parseInt(match[1], 10);
|
|
triggerClickMethod = me['onTrigger' + (idx + 1) + 'Click'] || me.onTriggerClick;
|
|
if (triggerClickMethod) {
|
|
triggerClickMethod.call(me, e);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onTriggerClick: Ext.emptyFn
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.field.Picker', {
|
|
extend: 'Ext.form.field.Trigger',
|
|
alias: 'widget.pickerfield',
|
|
alternateClassName: 'Ext.form.Picker',
|
|
requires: ['Ext.util.KeyNav'],
|
|
|
|
|
|
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 = Ext.create('Ext.util.KeyNav', me.inputEl, {
|
|
down: function() {
|
|
if (!me.isExpanded) {
|
|
|
|
|
|
me.onTriggerClick();
|
|
}
|
|
},
|
|
esc: me.collapse,
|
|
scope: me,
|
|
forceKeyDown: true
|
|
});
|
|
|
|
|
|
if (!me.editable) {
|
|
me.mon(me.inputEl, 'click', me.onTriggerClick, me);
|
|
}
|
|
|
|
|
|
if (Ext.isGecko) {
|
|
me.inputEl.dom.setAttribute('autocomplete', 'off');
|
|
}
|
|
},
|
|
|
|
|
|
|
|
expand: function() {
|
|
var me = this,
|
|
bodyEl, picker, collapseIf;
|
|
|
|
if (me.rendered && !me.isExpanded && !me.isDestroyed) {
|
|
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();
|
|
}
|
|
},
|
|
|
|
onExpand: Ext.emptyFn,
|
|
|
|
|
|
alignPicker: function() {
|
|
var me = this,
|
|
picker;
|
|
|
|
if (me.isExpanded) {
|
|
picker = me.getPicker();
|
|
if (me.matchFieldWidth) {
|
|
|
|
picker.setSize(me.bodyEl.getWidth(), picker.store && picker.store.getCount() ? null : 0);
|
|
}
|
|
if (picker.isFloating()) {
|
|
me.doAlign();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
doAlign: function(){
|
|
var me = this,
|
|
picker = me.picker,
|
|
aboveSfx = '-above',
|
|
isAbove;
|
|
|
|
me.picker.alignTo(me.inputEl, 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.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();
|
|
}
|
|
},
|
|
|
|
mimicBlur: function(e) {
|
|
var me = this,
|
|
picker = me.picker;
|
|
|
|
if (!picker || !e.within(picker.el, false, true)) {
|
|
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();
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.form.field.Spinner', {
|
|
extend: 'Ext.form.field.Trigger',
|
|
alias: 'widget.spinnerfield',
|
|
alternateClassName: 'Ext.form.Spinner',
|
|
requires: ['Ext.util.KeyNav'],
|
|
|
|
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,
|
|
|
|
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.setSpinUpEnabled(me.spinUpEnabled);
|
|
me.setSpinDownEnabled(me.spinDownEnabled);
|
|
|
|
|
|
if (me.keyNavEnabled) {
|
|
me.spinnerKeyNav = Ext.create('Ext.util.KeyNav', me.inputEl, {
|
|
scope: me,
|
|
up: me.spinUp,
|
|
down: me.spinDown
|
|
});
|
|
}
|
|
|
|
|
|
if (me.mouseWheelEnabled) {
|
|
me.mon(me.bodyEl, 'mousewheel', me.onMouseWheel, me);
|
|
}
|
|
},
|
|
|
|
|
|
getTriggerWidth: function() {
|
|
return this.hideTrigger || this.readOnly ? 0 : this.spinUpEl.getWidth() + this.triggerWrap.getFrameWidth('lr');
|
|
},
|
|
|
|
|
|
onTrigger1Click: function() {
|
|
this.spinUp();
|
|
},
|
|
|
|
|
|
onTrigger2Click: function() {
|
|
this.spinDown();
|
|
},
|
|
|
|
|
|
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'],
|
|
|
|
|
|
|
|
|
|
|
|
allowDecimals : true,
|
|
|
|
|
|
decimalSeparator : '.',
|
|
|
|
|
|
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,
|
|
allowed;
|
|
|
|
me.callParent();
|
|
|
|
me.setMinValue(me.minValue);
|
|
me.setMaxValue(me.maxValue);
|
|
|
|
|
|
if (me.disableKeyFilter !== true) {
|
|
allowed = me.baseChars + '';
|
|
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');
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
onChange: function() {
|
|
var me = this,
|
|
value = me.getValue(),
|
|
valueIsNull = value === null;
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
me.setSpinUpEnabled(valueIsNull || value < me.maxValue);
|
|
me.setSpinDownEnabled(valueIsNull || value > me.minValue);
|
|
},
|
|
|
|
|
|
setMinValue : function(value) {
|
|
this.minValue = Ext.Number.from(value, Number.NEGATIVE_INFINITY);
|
|
},
|
|
|
|
|
|
setMaxValue: function(value) {
|
|
this.maxValue = Ext.Number.from(value, Number.MAX_VALUE);
|
|
},
|
|
|
|
|
|
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);
|
|
}
|
|
},
|
|
|
|
onSpinUp: function() {
|
|
var me = this;
|
|
if (!me.readOnly) {
|
|
me.setValue(Ext.Number.constrain(me.getValue() + me.step, me.minValue, me.maxValue));
|
|
}
|
|
},
|
|
|
|
onSpinDown: function() {
|
|
var me = this;
|
|
if (!me.readOnly) {
|
|
me.setValue(Ext.Number.constrain(me.getValue() - me.step, me.minValue, me.maxValue));
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.toolbar.Paging', {
|
|
extend: 'Ext.toolbar.Toolbar',
|
|
alias: 'widget.pagingtoolbar',
|
|
alternateClassName: 'Ext.PagingToolbar',
|
|
requires: ['Ext.toolbar.TextItem', 'Ext.form.field.Number'],
|
|
|
|
|
|
|
|
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,
|
|
selectOnFocus: true,
|
|
submitValue: 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',
|
|
handler: me.doRefresh,
|
|
scope: me
|
|
}];
|
|
},
|
|
|
|
initComponent : function(){
|
|
var me = this,
|
|
pagingItems = me.getPagingItems(),
|
|
userItems = me.items || me.buttons || [];
|
|
|
|
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'
|
|
);
|
|
me.on('afterlayout', me.onLoad, me, {single: true});
|
|
|
|
me.bindStore(me.store || 'ext-empty-store', true);
|
|
},
|
|
|
|
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);
|
|
me.doComponentLayout();
|
|
}
|
|
},
|
|
|
|
|
|
onLoad : function(){
|
|
var me = this,
|
|
pageData,
|
|
currPage,
|
|
pageCount,
|
|
afterText;
|
|
|
|
if (!me.rendered) {
|
|
return;
|
|
}
|
|
|
|
pageData = me.getPageData();
|
|
currPage = pageData.currentPage;
|
|
pageCount = pageData.pageCount;
|
|
afterText = Ext.String.format(me.afterPageText, isNaN(pageCount) ? 1 : pageCount);
|
|
|
|
me.child('#afterTextItem').setText(afterText);
|
|
me.child('#inputItem').setValue(currPage);
|
|
me.child('#first').setDisabled(currPage === 1);
|
|
me.child('#prev').setDisabled(currPage === 1);
|
|
me.child('#next').setDisabled(currPage === pageCount);
|
|
me.child('#last').setDisabled(currPage === pageCount);
|
|
me.child('#refresh').enable();
|
|
me.updateInfo();
|
|
me.fireEvent('change', me, pageData);
|
|
},
|
|
|
|
|
|
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(){
|
|
if (!this.rendered) {
|
|
return;
|
|
}
|
|
this.child('#refresh').enable();
|
|
},
|
|
|
|
|
|
readPageFromInput : function(pageData){
|
|
var v = this.child('#inputItem').getValue(),
|
|
pageNum = parseInt(v, 10);
|
|
|
|
if (!v || isNaN(pageNum)) {
|
|
this.child('#inputItem').setValue(pageData.currentPage);
|
|
return false;
|
|
}
|
|
return pageNum;
|
|
},
|
|
|
|
onPagingFocus : function(){
|
|
this.child('#inputItem').select();
|
|
},
|
|
|
|
|
|
onPagingBlur : function(e){
|
|
var curPage = this.getPageData().currentPage;
|
|
this.child('#inputItem').setValue(curPage);
|
|
},
|
|
|
|
|
|
onPagingKeyDown : 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(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.PAGEUP || k == e.DOWN || k == e.PAGEDOWN) {
|
|
e.stopEvent();
|
|
pageNum = me.readPageFromInput(pageData);
|
|
if (pageNum) {
|
|
if (k == e.DOWN || k == e.PAGEDOWN) {
|
|
increment *= -1;
|
|
}
|
|
pageNum += increment;
|
|
if (pageNum >= 1 && pageNum <= pageData.pages) {
|
|
field.setValue(pageNum);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
beforeLoad : function(){
|
|
if(this.rendered && this.refresh){
|
|
this.refresh.disable();
|
|
}
|
|
},
|
|
|
|
|
|
doLoad : function(start){
|
|
if(this.fireEvent('beforechange', this, o) !== false){
|
|
this.store.load();
|
|
}
|
|
},
|
|
|
|
|
|
moveFirst : function(){
|
|
if (this.fireEvent('beforechange', this, 1) !== false){
|
|
this.store.loadPage(1);
|
|
}
|
|
},
|
|
|
|
|
|
movePrevious : function(){
|
|
var me = this,
|
|
prev = me.store.currentPage - 1;
|
|
|
|
if (prev > 0) {
|
|
if (me.fireEvent('beforechange', me, prev) !== false) {
|
|
me.store.previousPage();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
moveNext : function(){
|
|
var me = this,
|
|
total = me.getPageData().pageCount,
|
|
next = me.store.currentPage + 1;
|
|
|
|
if (next <= total) {
|
|
if (me.fireEvent('beforechange', me, next) !== false) {
|
|
me.store.nextPage();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
moveLast : function(){
|
|
var me = this,
|
|
last = me.getPageData().pageCount;
|
|
|
|
if (me.fireEvent('beforechange', me, last) !== false) {
|
|
me.store.loadPage(last);
|
|
}
|
|
},
|
|
|
|
|
|
doRefresh : function(){
|
|
var me = this,
|
|
current = me.store.currentPage;
|
|
|
|
if (me.fireEvent('beforechange', me, current) !== false) {
|
|
me.store.loadPage(current);
|
|
}
|
|
},
|
|
|
|
|
|
bindStore : function(store, initial){
|
|
var me = this;
|
|
|
|
if (!initial && me.store) {
|
|
if(store !== me.store && me.store.autoDestroy){
|
|
me.store.destroyStore();
|
|
}else{
|
|
me.store.un('beforeload', me.beforeLoad, me);
|
|
me.store.un('load', me.onLoad, me);
|
|
me.store.un('exception', me.onLoadError, me);
|
|
}
|
|
if(!store){
|
|
me.store = null;
|
|
}
|
|
}
|
|
if (store) {
|
|
store = Ext.data.StoreManager.lookup(store);
|
|
store.on({
|
|
scope: me,
|
|
beforeload: me.beforeLoad,
|
|
load: me.onLoad,
|
|
exception: me.onLoadError
|
|
});
|
|
}
|
|
me.store = store;
|
|
},
|
|
|
|
|
|
unbind : function(store){
|
|
this.bindStore(null);
|
|
},
|
|
|
|
|
|
bind : function(store){
|
|
this.bindStore(store);
|
|
},
|
|
|
|
|
|
onDestroy : function(){
|
|
this.bindStore(null);
|
|
this.callParent();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.view.BoundList', {
|
|
extend: 'Ext.view.View',
|
|
alias: 'widget.boundlist',
|
|
alternateClassName: 'Ext.BoundList',
|
|
requires: ['Ext.layout.component.BoundList', 'Ext.toolbar.Paging'],
|
|
|
|
|
|
pageSize: 0,
|
|
|
|
|
|
|
|
|
|
autoScroll: true,
|
|
baseCls: Ext.baseCSSPrefix + 'boundlist',
|
|
itemCls: Ext.baseCSSPrefix + 'boundlist-item',
|
|
listItemCls: '',
|
|
shadow: false,
|
|
trackOver: true,
|
|
refreshed: 0,
|
|
|
|
ariaRole: 'listbox',
|
|
|
|
componentLayout: 'boundlist',
|
|
|
|
renderTpl: ['<div id="{id}-listEl" class="list-ct"></div>'],
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
baseCls = me.baseCls,
|
|
itemCls = me.itemCls;
|
|
|
|
me.selectedItemCls = baseCls + '-selected';
|
|
me.overItemCls = baseCls + '-item-over';
|
|
me.itemSelector = "." + itemCls;
|
|
|
|
if (me.floating) {
|
|
me.addCls(baseCls + '-floating');
|
|
}
|
|
|
|
if (!me.tpl) {
|
|
|
|
|
|
me.tpl = Ext.create('Ext.XTemplate',
|
|
'<ul><tpl for=".">',
|
|
'<li role="option" class="' + itemCls + '">' + me.getInnerTpl(me.displayField) + '</li>',
|
|
'</tpl></ul>'
|
|
);
|
|
} else if (Ext.isString(me.tpl)) {
|
|
me.tpl = Ext.create('Ext.XTemplate', me.tpl);
|
|
}
|
|
|
|
if (me.pageSize) {
|
|
me.pagingToolbar = me.createPagingToolbar();
|
|
}
|
|
|
|
me.callParent();
|
|
|
|
me.addChildEls('listEl');
|
|
},
|
|
|
|
createPagingToolbar: function() {
|
|
return Ext.widget('pagingtoolbar', {
|
|
pageSize: this.pageSize,
|
|
store: this.store,
|
|
border: false
|
|
});
|
|
},
|
|
|
|
onRender: function() {
|
|
var me = this,
|
|
toolbar = me.pagingToolbar;
|
|
me.callParent(arguments);
|
|
if (toolbar) {
|
|
toolbar.render(me.el);
|
|
}
|
|
},
|
|
|
|
bindStore : function(store, initial) {
|
|
var me = this,
|
|
toolbar = me.pagingToolbar;
|
|
me.callParent(arguments);
|
|
if (toolbar) {
|
|
toolbar.bindStore(store, initial);
|
|
}
|
|
},
|
|
|
|
getTargetEl: function() {
|
|
return this.listEl || this.el;
|
|
},
|
|
|
|
getInnerTpl: function(displayField) {
|
|
return '{' + displayField + '}';
|
|
},
|
|
|
|
refresh: function() {
|
|
var me = this;
|
|
me.callParent();
|
|
if (me.isVisible()) {
|
|
me.refreshed++;
|
|
me.doComponentLayout();
|
|
me.refreshed--;
|
|
}
|
|
},
|
|
|
|
initAria: function() {
|
|
this.callParent();
|
|
|
|
var selModel = this.getSelectionModel(),
|
|
mode = selModel.getSelectionMode(),
|
|
actionEl = this.getActionEl();
|
|
|
|
|
|
if (mode !== 'SINGLE') {
|
|
actionEl.dom.setAttribute('aria-multiselectable', true);
|
|
}
|
|
},
|
|
|
|
onDestroy: function() {
|
|
Ext.destroyMembers(this, 'pagingToolbar', 'listEl');
|
|
this.callParent();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.view.BoundListKeyNav', {
|
|
extend: 'Ext.util.KeyNav',
|
|
requires: 'Ext.view.BoundList',
|
|
|
|
|
|
|
|
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 me = this,
|
|
boundList = me.boundList,
|
|
highlighted = boundList.highlightedItem,
|
|
selModel = boundList.getSelectionModel();
|
|
if (highlighted) {
|
|
selModel.selectWithEvent(boundList.getRecord(highlighted), e);
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
Ext.define('Ext.form.field.ComboBox', {
|
|
extend:'Ext.form.field.Picker',
|
|
requires: ['Ext.util.DelayedTask', 'Ext.EventObject', 'Ext.view.BoundList', 'Ext.view.BoundListKeyNav', 'Ext.data.StoreManager'],
|
|
alternateClassName: 'Ext.form.ComboBox',
|
|
alias: ['widget.combobox', 'widget.combo'],
|
|
|
|
|
|
triggerCls: Ext.baseCSSPrefix + 'form-arrow-trigger',
|
|
|
|
|
|
hiddenDataCls: Ext.baseCSSPrefix + 'hide-display ' + Ext.baseCSSPrefix + 'form-data-hidden',
|
|
|
|
|
|
fieldSubTpl: [
|
|
'<div class="{hiddenDataCls}" role="presentation"></div>',
|
|
'<input id="{id}" type="{type}" ',
|
|
'<tpl if="size">size="{size}" </tpl>',
|
|
'<tpl if="tabIdx">tabIndex="{tabIdx}" </tpl>',
|
|
'class="{fieldCls} {typeCls}" autocomplete="off" />',
|
|
'<div id="{cmpId}-triggerWrap" class="{triggerWrapCls}" role="presentation">',
|
|
'{triggerEl}',
|
|
'<div class="{clearCls}" role="presentation"></div>',
|
|
'</div>',
|
|
{
|
|
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,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
autoSelect: true,
|
|
|
|
|
|
typeAhead: false,
|
|
|
|
|
|
typeAheadDelay: 250,
|
|
|
|
|
|
selectOnTab: true,
|
|
|
|
|
|
forceSelection: false,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defaultListConfig: {
|
|
emptyText: '',
|
|
loadingText: 'Loading...',
|
|
loadingHeight: 70,
|
|
minWidth: 70,
|
|
maxHeight: 300,
|
|
shadow: 'sides'
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ignoreSelection: 0,
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
isDefined = Ext.isDefined,
|
|
store = me.store,
|
|
transform = me.transform,
|
|
transformSelect, isLocalMode;
|
|
|
|
Ext.applyIf(me.renderSelectors, {
|
|
hiddenDataEl: '.' + me.hiddenDataCls.split(' ').join('.')
|
|
});
|
|
|
|
|
|
this.addEvents(
|
|
|
|
'beforequery',
|
|
|
|
|
|
'select',
|
|
|
|
|
|
'beforeselect',
|
|
|
|
|
|
'beforedeselect'
|
|
);
|
|
|
|
|
|
if (transform) {
|
|
transformSelect = Ext.getDom(transform);
|
|
if (transformSelect) {
|
|
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 (!me.displayTpl) {
|
|
me.displayTpl = Ext.create('Ext.XTemplate',
|
|
'<tpl for=".">' +
|
|
'{[typeof values === "string" ? values : values["' + me.displayField + '"]]}' +
|
|
'<tpl if="xindex < xcount">' + me.delimiter + '</tpl>' +
|
|
'</tpl>'
|
|
);
|
|
} else if (Ext.isString(me.displayTpl)) {
|
|
me.displayTpl = Ext.create('Ext.XTemplate', me.displayTpl);
|
|
}
|
|
|
|
me.callParent();
|
|
|
|
me.doQueryTask = Ext.create('Ext.util.DelayedTask', me.doRawQuery, me);
|
|
|
|
|
|
if (me.store.getCount() > 0) {
|
|
me.setValue(me.value);
|
|
}
|
|
|
|
|
|
if (transformSelect) {
|
|
me.render(transformSelect.parentNode, transformSelect);
|
|
Ext.removeNode(transformSelect);
|
|
delete me.renderTo;
|
|
}
|
|
},
|
|
|
|
|
|
getStore : function(){
|
|
return this.store;
|
|
},
|
|
|
|
beforeBlur: function() {
|
|
this.doQueryTask.cancel();
|
|
this.assertValue();
|
|
},
|
|
|
|
|
|
assertValue: function() {
|
|
var me = this,
|
|
value = me.getRawValue(),
|
|
rec;
|
|
|
|
if (me.forceSelection) {
|
|
if (me.multiSelect) {
|
|
|
|
|
|
if (value !== me.getDisplayValue()) {
|
|
me.setValue(me.lastSelection);
|
|
}
|
|
} else {
|
|
|
|
|
|
rec = me.findRecordByDisplay(value);
|
|
if (rec) {
|
|
me.select(rec);
|
|
} 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: function() {
|
|
|
|
},
|
|
|
|
bindStore: function(store, initial) {
|
|
var me = this,
|
|
oldStore = me.store;
|
|
|
|
|
|
|
|
if (oldStore && !initial) {
|
|
if (oldStore !== store && oldStore.autoDestroy) {
|
|
oldStore.destroyStore();
|
|
} else {
|
|
oldStore.un({
|
|
scope: me,
|
|
load: me.onLoad,
|
|
exception: me.collapse
|
|
});
|
|
}
|
|
if (!store) {
|
|
me.store = null;
|
|
if (me.picker) {
|
|
me.picker.bindStore(null);
|
|
}
|
|
}
|
|
}
|
|
if (store) {
|
|
if (!initial) {
|
|
me.resetToDefault();
|
|
}
|
|
|
|
me.store = Ext.data.StoreManager.lookup(store);
|
|
me.store.on({
|
|
scope: me,
|
|
load: me.onLoad,
|
|
exception: me.collapse
|
|
});
|
|
|
|
if (me.picker) {
|
|
me.picker.bindStore(store);
|
|
}
|
|
}
|
|
},
|
|
|
|
onLoad: function() {
|
|
var me = this,
|
|
value = me.value;
|
|
|
|
|
|
if (me.rawQuery) {
|
|
me.rawQuery = false;
|
|
me.syncSelection();
|
|
if (me.picker && !me.picker.getSelectionModel().hasSelection()) {
|
|
me.doAutoSelect();
|
|
}
|
|
}
|
|
|
|
else {
|
|
|
|
if (me.value) {
|
|
me.setValue(me.value);
|
|
} else {
|
|
|
|
|
|
if (me.store.getCount()) {
|
|
me.doAutoSelect();
|
|
} else {
|
|
me.setValue('');
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
doRawQuery: function() {
|
|
this.doQuery(this.getRawValue(), false, true);
|
|
},
|
|
|
|
|
|
doQuery: function(queryString, forceAll, rawQuery) {
|
|
queryString = queryString || '';
|
|
|
|
|
|
|
|
var me = this,
|
|
qe = {
|
|
query: queryString,
|
|
forceAll: forceAll,
|
|
combo: me,
|
|
cancel: false
|
|
},
|
|
store = me.store,
|
|
isLocalMode = me.queryMode === 'local';
|
|
|
|
if (me.fireEvent('beforequery', qe) === false || qe.cancel) {
|
|
return false;
|
|
}
|
|
|
|
|
|
queryString = qe.query;
|
|
forceAll = qe.forceAll;
|
|
|
|
|
|
if (forceAll || (queryString.length >= me.minChars)) {
|
|
|
|
me.expand();
|
|
|
|
|
|
if (!me.queryCaching || me.lastQuery !== queryString) {
|
|
me.lastQuery = queryString;
|
|
|
|
if (isLocalMode) {
|
|
|
|
if (forceAll) {
|
|
store.clearFilter();
|
|
} else {
|
|
|
|
store.clearFilter(true);
|
|
store.filter(me.displayField, queryString);
|
|
}
|
|
} else {
|
|
|
|
me.rawQuery = rawQuery;
|
|
|
|
|
|
|
|
if (me.pageSize) {
|
|
|
|
me.loadPage(1);
|
|
} else {
|
|
store.load({
|
|
params: me.getParams(queryString)
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (me.getRawValue() !== me.getDisplayValue()) {
|
|
me.ignoreSelection++;
|
|
me.picker.getSelectionModel().deselectAll();
|
|
me.ignoreSelection--;
|
|
}
|
|
|
|
if (isLocalMode) {
|
|
me.doAutoSelect();
|
|
}
|
|
if (me.typeAhead) {
|
|
me.doTypeAhead();
|
|
}
|
|
}
|
|
return true;
|
|
},
|
|
|
|
loadPage: function(pageNum){
|
|
this.store.loadPage(pageNum, {
|
|
params: this.getParams(this.lastQuery)
|
|
});
|
|
},
|
|
|
|
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() {
|
|
if (!this.typeAheadTask) {
|
|
this.typeAheadTask = Ext.create('Ext.util.DelayedTask', this.onTypeAhead, this);
|
|
}
|
|
if (this.lastKey != Ext.EventObject.BACKSPACE && this.lastKey != Ext.EventObject.DELETE) {
|
|
this.typeAheadTask.delay(this.typeAheadDelay);
|
|
}
|
|
},
|
|
|
|
onTriggerClick: function() {
|
|
var me = this;
|
|
if (!me.readOnly && !me.disabled) {
|
|
if (me.isExpanded) {
|
|
me.collapse();
|
|
} else {
|
|
me.onFocus({});
|
|
if (me.triggerAction === 'all') {
|
|
me.doQuery(me.allQuery, true);
|
|
} else {
|
|
me.doQuery(me.getRawValue(), false, true);
|
|
}
|
|
}
|
|
me.inputEl.focus();
|
|
}
|
|
},
|
|
|
|
|
|
|
|
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);
|
|
}
|
|
},
|
|
|
|
onDestroy: function(){
|
|
this.bindStore(null);
|
|
this.callParent();
|
|
},
|
|
|
|
createPicker: function() {
|
|
var me = this,
|
|
picker,
|
|
menuCls = Ext.baseCSSPrefix + 'menu',
|
|
opts = Ext.apply({
|
|
pickerField: me,
|
|
selModel: {
|
|
mode: me.multiSelect ? 'SIMPLE' : 'SINGLE'
|
|
},
|
|
floating: true,
|
|
hidden: true,
|
|
ownerCt: me.ownerCt,
|
|
cls: me.el.up('.' + menuCls) ? menuCls : '',
|
|
store: me.store,
|
|
displayField: me.displayField,
|
|
focusOnToFront: false,
|
|
pageSize: me.pageSize,
|
|
tpl: me.tpl
|
|
}, me.listConfig, me.defaultListConfig);
|
|
|
|
picker = me.picker = Ext.create('Ext.view.BoundList', opts);
|
|
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.picker,
|
|
heightAbove = me.getPosition()[1] - Ext.getBody().getScroll().top,
|
|
heightBelow = Ext.Element.getViewHeight() - heightAbove - me.getHeight(),
|
|
space = Math.max(heightAbove, heightBelow);
|
|
|
|
me.callParent();
|
|
if (picker.getHeight() > space) {
|
|
picker.setHeight(space - 5);
|
|
me.doAlign();
|
|
}
|
|
},
|
|
|
|
onListRefresh: function() {
|
|
this.alignPicker();
|
|
this.syncSelection();
|
|
},
|
|
|
|
onItemClick: function(picker, record){
|
|
|
|
var me = this,
|
|
lastSelection = me.lastSelection,
|
|
valueField = me.valueField,
|
|
selected;
|
|
|
|
if (!me.multiSelect && lastSelection) {
|
|
selected = lastSelection[0];
|
|
if (selected && (record.get(valueField) === selected.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 = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
|
|
boundList: picker,
|
|
forceKeyDown: true,
|
|
tab: function(e) {
|
|
if (selectOnTab) {
|
|
this.selectHighlighted(e);
|
|
me.triggerBlur();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
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) {
|
|
this.setValue(r, true);
|
|
},
|
|
|
|
|
|
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,
|
|
models = [],
|
|
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) {
|
|
models.push(record);
|
|
displayTplData.push(record.data);
|
|
processedValue.push(record.get(me.valueField));
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
if (!me.forceSelection) {
|
|
displayTplData.push(value[i]);
|
|
processedValue.push(value[i]);
|
|
}
|
|
|
|
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 = models;
|
|
|
|
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, i;
|
|
if (!me.hiddenDataEl) {
|
|
return;
|
|
}
|
|
values = Ext.Array.from(values);
|
|
var 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:me.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() {
|
|
return this.getValue();
|
|
},
|
|
|
|
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,
|
|
ExtArray = Ext.Array,
|
|
picker = me.picker,
|
|
selection, selModel;
|
|
if (picker) {
|
|
|
|
selection = [];
|
|
ExtArray.forEach(me.valueModels || [], function(value) {
|
|
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);
|
|
}
|
|
me.ignoreSelection--;
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.picker.Month', {
|
|
extend: 'Ext.Component',
|
|
requires: ['Ext.XTemplate', 'Ext.util.ClickRepeater', 'Ext.Date', 'Ext.button.Button'],
|
|
alias: 'widget.monthpicker',
|
|
alternateClassName: 'Ext.MonthPicker',
|
|
|
|
renderTpl: [
|
|
'<div id="{id}-bodyEl" class="{baseCls}-body">',
|
|
'<div class="{baseCls}-months">',
|
|
'<tpl for="months">',
|
|
'<div class="{parent.baseCls}-item {parent.baseCls}-month"><a href="#" hidefocus="on">{.}</a></div>',
|
|
'</tpl>',
|
|
'</div>',
|
|
'<div class="{baseCls}-years">',
|
|
'<div class="{baseCls}-yearnav">',
|
|
'<button id="{id}-prevEl" class="{baseCls}-yearnav-prev"></button>',
|
|
'<button id="{id}-nextEl" class="{baseCls}-yearnav-next"></button>',
|
|
'</div>',
|
|
'<tpl for="years">',
|
|
'<div class="{parent.baseCls}-item {parent.baseCls}-year"><a href="#" hidefocus="on">{.}</a></div>',
|
|
'</tpl>',
|
|
'</div>',
|
|
'<div class="' + Ext.baseCSSPrefix + 'clear"></div>',
|
|
'</div>',
|
|
'<tpl if="showButtons">',
|
|
'<div id="{id}-buttonsEl" class="{baseCls}-buttons"></div>',
|
|
'</tpl>'
|
|
],
|
|
|
|
|
|
okText: 'OK',
|
|
|
|
|
|
cancelText: 'Cancel',
|
|
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'monthpicker',
|
|
|
|
|
|
showButtons: true,
|
|
|
|
|
|
|
|
|
|
width: 178,
|
|
|
|
|
|
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);
|
|
this.callParent();
|
|
},
|
|
|
|
|
|
onRender: function(ct, position){
|
|
var me = this,
|
|
i = 0,
|
|
months = [],
|
|
shortName = Ext.Date.getShortMonthName,
|
|
monthLen = me.monthOffset;
|
|
|
|
for (; i < monthLen; ++i) {
|
|
months.push(shortName(i), shortName(i + monthLen));
|
|
}
|
|
|
|
Ext.apply(me.renderData, {
|
|
months: months,
|
|
years: me.getYears(),
|
|
showButtons: me.showButtons
|
|
});
|
|
|
|
me.addChildEls('bodyEl', 'prevEl', 'nextEl', 'buttonsEl');
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
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');
|
|
|
|
if (me.showButtons) {
|
|
me.okBtn = Ext.create('Ext.button.Button', {
|
|
text: me.okText,
|
|
renderTo: buttonsEl,
|
|
handler: me.onOkClick,
|
|
scope: me
|
|
});
|
|
me.cancelBtn = Ext.create('Ext.button.Button', {
|
|
text: me.cancelText,
|
|
renderTo: buttonsEl,
|
|
handler: me.onCancelClick,
|
|
scope: me
|
|
});
|
|
}
|
|
|
|
me.backRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
|
|
handler: Ext.Function.bind(me.adjustYear, me, [-me.totalYears])
|
|
});
|
|
|
|
me.prevEl.addClsOnOver(me.baseCls + '-yearnav-prev-over');
|
|
me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
|
|
handler: Ext.Function.bind(me.adjustYear, me, [me.totalYears])
|
|
});
|
|
me.nextEl.addClsOnOver(me.baseCls + '-yearnav-next-over');
|
|
me.updateBody();
|
|
},
|
|
|
|
|
|
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;
|
|
|
|
if (me.rendered) {
|
|
years.removeCls(cls);
|
|
months.removeCls(cls);
|
|
years.each(function(el, all, index){
|
|
year = yearNumbers[index];
|
|
el.dom.innerHTML = year;
|
|
if (year == value) {
|
|
el.dom.className = 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();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.picker.Date', {
|
|
extend: 'Ext.Component',
|
|
requires: [
|
|
'Ext.XTemplate',
|
|
'Ext.button.Button',
|
|
'Ext.button.Split',
|
|
'Ext.util.ClickRepeater',
|
|
'Ext.util.KeyNav',
|
|
'Ext.EventObject',
|
|
'Ext.fx.Manager',
|
|
'Ext.picker.Month'
|
|
],
|
|
alias: 'widget.datepicker',
|
|
alternateClassName: 'Ext.DatePicker',
|
|
|
|
renderTpl: [
|
|
'<div class="{cls}" id="{id}" role="grid" title="{ariaTitle} {value:this.longDay}">',
|
|
'<div role="presentation" class="{baseCls}-header">',
|
|
'<div class="{baseCls}-prev"><a id="{id}-prevEl" href="#" role="button" title="{prevText}"></a></div>',
|
|
'<div class="{baseCls}-month" id="{id}-middleBtnEl"></div>',
|
|
'<div class="{baseCls}-next"><a id="{id}-nextEl" href="#" role="button" title="{nextText}"></a></div>',
|
|
'</div>',
|
|
'<table id="{id}-eventEl" class="{baseCls}-inner" cellspacing="0" role="presentation">',
|
|
'<thead role="presentation"><tr role="presentation">',
|
|
'<tpl for="dayNames">',
|
|
'<th role="columnheader" title="{.}"><span>{.:this.firstInitial}</span></th>',
|
|
'</tpl>',
|
|
'</tr></thead>',
|
|
'<tbody role="presentation"><tr role="presentation">',
|
|
'<tpl for="days">',
|
|
'{#:this.isEndOfWeek}',
|
|
'<td role="gridcell" id="{[Ext.id()]}">',
|
|
'<a role="presentation" href="#" hidefocus="on" class="{parent.baseCls}-date" tabIndex="1">',
|
|
'<em role="presentation"><span role="presentation"></span></em>',
|
|
'</a>',
|
|
'</td>',
|
|
'</tpl>',
|
|
'</tr></tbody>',
|
|
'</table>',
|
|
'<tpl if="showToday">',
|
|
'<div id="{id}-footerEl" role="presentation" class="{baseCls}-footer"></div>',
|
|
'</tpl>',
|
|
'</div>',
|
|
{
|
|
firstInitial: function(value) {
|
|
return value.substr(0,1);
|
|
},
|
|
isEndOfWeek: function(value) {
|
|
|
|
|
|
value--;
|
|
var end = value % 7 === 0 && value !== 0;
|
|
return end ? '</tr><tr role="row">' : '';
|
|
},
|
|
longDay: function(value){
|
|
return Ext.Date.format(value, this.longDayFormat);
|
|
}
|
|
}
|
|
],
|
|
|
|
ariaTitle: 'Date Picker',
|
|
|
|
|
|
todayText : 'Today',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)',
|
|
|
|
|
|
startDay : 0,
|
|
|
|
|
|
showToday : true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
disableAnim: false,
|
|
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'datepicker',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
longDayFormat: 'F d, Y',
|
|
|
|
|
|
|
|
|
|
focusOnShow: false,
|
|
|
|
|
|
|
|
focusOnSelect: true,
|
|
|
|
width: 178,
|
|
|
|
|
|
|
|
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.nextCls = me.baseCls + '-prevday';
|
|
me.todayCls = me.baseCls + '-today';
|
|
me.dayNames = me.dayNames.slice(me.startDay).concat(me.dayNames.slice(0, me.startDay));
|
|
this.callParent();
|
|
|
|
me.value = me.value ?
|
|
clearTime(me.value, true) : clearTime(new Date());
|
|
|
|
me.addEvents(
|
|
|
|
'select'
|
|
);
|
|
|
|
me.initDisabledDays();
|
|
},
|
|
|
|
|
|
onRender : function(container, position){
|
|
|
|
|
|
var me = this,
|
|
days = new Array(me.numDays),
|
|
today = Ext.Date.format(new Date(), me.format);
|
|
|
|
Ext.applyIf(me, {
|
|
renderData: {}
|
|
});
|
|
|
|
Ext.apply(me.renderData, {
|
|
dayNames: me.dayNames,
|
|
ariaTitle: me.ariaTitle,
|
|
value: me.value,
|
|
showToday: me.showToday,
|
|
prevText: me.prevText,
|
|
nextText: me.nextText,
|
|
days: days
|
|
});
|
|
me.getTpl('renderTpl').longDayFormat = me.longDayFormat;
|
|
|
|
me.addChildEls('eventEl', 'prevEl', 'nextEl', 'middleBtnEl', 'footerEl');
|
|
|
|
this.callParent(arguments);
|
|
me.el.unselectable();
|
|
|
|
me.cells = me.eventEl.select('tbody td');
|
|
me.textNodes = me.eventEl.query('tbody td span');
|
|
|
|
me.monthBtn = Ext.create('Ext.button.Split', {
|
|
text: '',
|
|
tooltip: me.monthYearText,
|
|
renderTo: me.middleBtnEl
|
|
});
|
|
|
|
|
|
|
|
me.todayBtn = Ext.create('Ext.button.Button', {
|
|
renderTo: me.footerEl,
|
|
text: Ext.String.format(me.todayText, today),
|
|
tooltip: Ext.String.format(me.todayTip, today),
|
|
handler: me.selectToday,
|
|
scope: me
|
|
});
|
|
},
|
|
|
|
|
|
initEvents: function(){
|
|
var me = this,
|
|
eDate = Ext.Date,
|
|
day = eDate.DAY;
|
|
|
|
this.callParent();
|
|
|
|
me.prevRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
|
|
handler: me.showPrevMonth,
|
|
scope: me,
|
|
preventDefault: true,
|
|
stopDefault: true
|
|
});
|
|
|
|
me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
|
|
handler: me.showNextMonth,
|
|
scope: me,
|
|
preventDefault:true,
|
|
stopDefault:true
|
|
});
|
|
|
|
me.keyNav = Ext.create('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' : me.showNextMonth,
|
|
'pageDown' : me.showPrevMonth,
|
|
'enter' : function(e){
|
|
e.stopPropagation();
|
|
return true;
|
|
}
|
|
}, me.keyNavConfig));
|
|
|
|
if(me.showToday){
|
|
me.todayKeyListener = me.eventEl.addKeyListener(Ext.EventObject.SPACE, me.selectToday, me);
|
|
}
|
|
me.mon(me.eventEl, 'mousewheel', me.handleMouseWheel, me);
|
|
me.mon(me.eventEl, 'click', me.handleDateClick, me, {delegate: 'a.' + me.baseCls + '-date'});
|
|
me.mon(me.monthBtn, 'click', me.showMonthPicker, me);
|
|
me.mon(me.monthBtn, 'arrowclick', me.showMonthPicker, me);
|
|
me.update(me.value);
|
|
},
|
|
|
|
|
|
initDisabledDays : function(){
|
|
var me = this,
|
|
dd = me.disabledDates,
|
|
re = '(?:',
|
|
len;
|
|
|
|
if(!me.disabledDatesRE && dd){
|
|
len = dd.length - 1;
|
|
|
|
Ext.each(dd, function(d, i){
|
|
re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(Ext.Date.dateFormat(d, me.format)) + '$' : dd[i];
|
|
if(i != len){
|
|
re += '|';
|
|
}
|
|
}, me);
|
|
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;
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
showMonthPicker : function(animate){
|
|
var me = this,
|
|
picker;
|
|
|
|
if (me.rendered && !me.disabled) {
|
|
picker = me.createMonthPicker();
|
|
picker.setValue(me.getActive());
|
|
picker.setSize(me.getSize());
|
|
picker.setPosition(-1, -1);
|
|
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 = Ext.create('Ext.picker.Month', {
|
|
renderTo: me.el,
|
|
floating: true,
|
|
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 = new Date(year, month, 1).getLastDateOfMonth();
|
|
}
|
|
me.update(date);
|
|
me.hideMonthPicker();
|
|
},
|
|
|
|
|
|
onCancelClick: function(){
|
|
this.hideMonthPicker();
|
|
},
|
|
|
|
|
|
showPrevMonth : function(e){
|
|
return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, -1));
|
|
},
|
|
|
|
|
|
showNextMonth : function(e){
|
|
return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, 1));
|
|
},
|
|
|
|
|
|
showPrevYear : function(){
|
|
this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, -1));
|
|
},
|
|
|
|
|
|
showNextYear : function(){
|
|
this.update(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.cancelFocus = me.focusOnSelect === false;
|
|
me.setValue(new Date(t.dateValue));
|
|
delete me.cancelFocus;
|
|
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, active){
|
|
var me = this,
|
|
t = date.getTime(),
|
|
cells = me.cells,
|
|
cls = me.selectedCls;
|
|
|
|
cells.removeCls(cls);
|
|
cells.each(function(c){
|
|
if (c.dom.firstChild.dateValue == t) {
|
|
me.el.dom.setAttribute('aria-activedescendent', c.dom.id);
|
|
c.addCls(cls);
|
|
if(me.isVisible() && !me.cancelFocus){
|
|
Ext.fly(c.dom.firstChild).focus(50);
|
|
}
|
|
return false;
|
|
}
|
|
}, this);
|
|
},
|
|
|
|
|
|
fullUpdate: function(date, active){
|
|
var me = this,
|
|
cells = me.cells.elements,
|
|
textNodes = me.textNodes,
|
|
disabledCls = me.disabledCellCls,
|
|
eDate = Ext.Date,
|
|
i = 0,
|
|
extraDays = 0,
|
|
visible = me.isVisible(),
|
|
sel = +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){
|
|
value = +eDate.clearTime(current, true);
|
|
cell.title = eDate.format(current, longDayFormat);
|
|
|
|
cell.firstChild.dateValue = value;
|
|
if(value == today){
|
|
cell.className += ' ' + me.todayCls;
|
|
cell.title = me.todayText;
|
|
}
|
|
if(value == sel){
|
|
cell.className += ' ' + me.selectedCls;
|
|
me.el.dom.setAttribute('aria-activedescendant', cell.id);
|
|
if (visible && me.floating) {
|
|
Ext.fly(cell.firstChild).focus(50);
|
|
}
|
|
}
|
|
|
|
if(value < min) {
|
|
cell.className = disabledCls;
|
|
cell.title = me.minText;
|
|
return;
|
|
}
|
|
if(value > max) {
|
|
cell.className = disabledCls;
|
|
cell.title = me.maxText;
|
|
return;
|
|
}
|
|
if(ddays){
|
|
if(ddays.indexOf(current.getDay()) != -1){
|
|
cell.title = ddaysText;
|
|
cell.className = disabledCls;
|
|
}
|
|
}
|
|
if(ddMatch && format){
|
|
formatValue = eDate.dateFormat(current, format);
|
|
if(ddMatch.test(formatValue)){
|
|
cell.title = ddText.replace('%0', formatValue);
|
|
cell.className = disabledCls;
|
|
}
|
|
}
|
|
};
|
|
|
|
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;
|
|
cells[i].className = cls;
|
|
current.setDate(current.getDate() + 1);
|
|
setCellClass(cells[i]);
|
|
}
|
|
|
|
me.monthBtn.setText(me.monthNames[date.getMonth()] + ' ' + date.getFullYear());
|
|
},
|
|
|
|
|
|
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();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
function() {
|
|
var proto = this.prototype;
|
|
|
|
proto.monthNames = Ext.Date.monthNames;
|
|
|
|
proto.dayNames = Ext.Date.dayNames;
|
|
|
|
proto.format = Ext.Date.defaultFormat;
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.field.Date', {
|
|
extend:'Ext.form.field.Picker',
|
|
alias: 'widget.datefield',
|
|
requires: ['Ext.picker.Date'],
|
|
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,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 = "(?:";
|
|
|
|
Ext.each(dd, function(d, i){
|
|
re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(d.dateFormat(this.format)) + '$' : dd[i];
|
|
if (i !== len) {
|
|
re += '|';
|
|
}
|
|
}, this);
|
|
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, 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,
|
|
parsedDate,
|
|
result = null;
|
|
|
|
if (utilDate.formatContainsHourInfo(format)) {
|
|
|
|
result = utilDate.parse(value, format);
|
|
} else {
|
|
|
|
parsedDate = utilDate.parse(value + ' ' + me.initTime, format + ' ' + me.initTimeFormat);
|
|
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 Ext.create('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();
|
|
}
|
|
}
|
|
});
|
|
},
|
|
|
|
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.Display', {
|
|
extend:'Ext.form.field.Base',
|
|
alias: 'widget.displayfield',
|
|
requires: ['Ext.util.Format', 'Ext.XTemplate'],
|
|
alternateClassName: ['Ext.form.DisplayField', 'Ext.form.Display'],
|
|
fieldSubTpl: [
|
|
'<div id="{id}" class="{fieldCls}"></div>',
|
|
{
|
|
compiled: true,
|
|
disableFormats: true
|
|
}
|
|
],
|
|
|
|
|
|
fieldCls: Ext.baseCSSPrefix + 'form-display-field',
|
|
|
|
|
|
htmlEncode: false,
|
|
|
|
validateOnChange: false,
|
|
|
|
initEvents: Ext.emptyFn,
|
|
|
|
submitValue: 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.htmlEncode ? Ext.util.Format.htmlEncode(value) : value;
|
|
}
|
|
return value;
|
|
},
|
|
|
|
|
|
getContentTarget: function() {
|
|
return this.inputEl;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
Ext.define("Ext.form.field.File", {
|
|
extend: 'Ext.form.field.Text',
|
|
alias: ['widget.filefield', 'widget.fileuploadfield'],
|
|
alternateClassName: ['Ext.form.FileUploadField', 'Ext.ux.form.FileUploadField', 'Ext.form.File'],
|
|
uses: ['Ext.button.Button', 'Ext.layout.component.field.File'],
|
|
|
|
|
|
buttonText: 'Browse...',
|
|
|
|
|
|
buttonOnly: false,
|
|
|
|
|
|
buttonMargin: 3,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fieldBodyCls: Ext.baseCSSPrefix + 'form-file-wrap',
|
|
|
|
|
|
readOnly: true,
|
|
|
|
|
|
componentLayout: 'filefield',
|
|
|
|
|
|
onRender: function() {
|
|
var me = this,
|
|
inputEl;
|
|
|
|
me.callParent(arguments);
|
|
|
|
me.createButton();
|
|
me.createFileInput();
|
|
|
|
|
|
|
|
if (me.disabled) {
|
|
me.disableItems();
|
|
}
|
|
|
|
inputEl = me.inputEl;
|
|
inputEl.dom.removeAttribute('name');
|
|
if (me.buttonOnly) {
|
|
inputEl.setDisplayed(false);
|
|
}
|
|
},
|
|
|
|
|
|
createButton: function() {
|
|
var me = this;
|
|
me.button = Ext.widget('button', Ext.apply({
|
|
ui: me.ui,
|
|
renderTo: me.bodyEl,
|
|
text: me.buttonText,
|
|
cls: Ext.baseCSSPrefix + 'form-file-btn',
|
|
preventDefault: false,
|
|
style: me.buttonOnly ? '' : 'margin-left:' + me.buttonMargin + 'px'
|
|
}, me.buttonConfig));
|
|
},
|
|
|
|
|
|
createFileInput : function() {
|
|
var me = this;
|
|
me.fileInputEl = me.button.el.createChild({
|
|
name: me.getName(),
|
|
cls: Ext.baseCSSPrefix + 'form-file-input',
|
|
tag: 'input',
|
|
type: 'file',
|
|
size: 1
|
|
}).on('change', me.onFileChange, me);
|
|
},
|
|
|
|
|
|
onFileChange: function() {
|
|
this.lastValue = null;
|
|
Ext.form.field.File.superclass.setValue.call(this, this.fileInputEl.dom.value);
|
|
},
|
|
|
|
|
|
setValue: Ext.emptyFn,
|
|
|
|
reset : function(){
|
|
var me = this;
|
|
if (me.rendered) {
|
|
me.fileInputEl.remove();
|
|
me.createFileInput();
|
|
me.inputEl.dom.value = '';
|
|
}
|
|
me.callParent();
|
|
},
|
|
|
|
onDisable: function(){
|
|
this.callParent();
|
|
this.disableItems();
|
|
},
|
|
|
|
disableItems: function(){
|
|
var file = this.fileInputEl,
|
|
button = this.button;
|
|
|
|
if (file) {
|
|
file.dom.disabled = true;
|
|
}
|
|
if (button) {
|
|
button.disable();
|
|
}
|
|
},
|
|
|
|
onEnable: function(){
|
|
var me = this;
|
|
me.callParent();
|
|
me.fileInputEl.dom.disabled = false;
|
|
me.button.enable();
|
|
},
|
|
|
|
isFileUpload: function() {
|
|
return true;
|
|
},
|
|
|
|
extractFileInput: function() {
|
|
var fileInput = this.fileInputEl.dom;
|
|
this.reset();
|
|
return fileInput;
|
|
},
|
|
|
|
onDestroy: function(){
|
|
Ext.destroyMembers(this, 'fileInputEl', 'button');
|
|
this.callParent();
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.field.Hidden', {
|
|
extend:'Ext.form.field.Base',
|
|
alias: ['widget.hiddenfield', 'widget.hidden'],
|
|
alternateClassName: 'Ext.form.Hidden',
|
|
|
|
|
|
inputType : 'hidden',
|
|
hideLabel: true,
|
|
|
|
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',
|
|
requires: 'Ext.XTemplate',
|
|
alias: 'widget.colorpicker',
|
|
alternateClassName: 'Ext.ColorPalette',
|
|
|
|
|
|
componentCls : Ext.baseCSSPrefix + 'color-picker',
|
|
|
|
|
|
selectedCls: Ext.baseCSSPrefix + 'color-picker-selected',
|
|
|
|
|
|
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: [
|
|
'<tpl for="colors">',
|
|
'<a href="#" class="color-{.}" hidefocus="on">',
|
|
'<em><span style="background:#{.}" unselectable="on"> </span></em>',
|
|
'</a>',
|
|
'</tpl>'
|
|
],
|
|
|
|
|
|
initComponent : function(){
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
me.addEvents(
|
|
|
|
'select'
|
|
);
|
|
|
|
if (me.handler) {
|
|
me.on('select', me.handler, me.scope, true);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
onRender : function(container, position){
|
|
var me = this,
|
|
clickEvent = me.clickEvent;
|
|
|
|
Ext.apply(me.renderData, {
|
|
itemCls: me.itemCls,
|
|
colors: me.colors
|
|
});
|
|
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);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getValue: function(){
|
|
return this.value || null;
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.layout.component.field.HtmlEditor', {
|
|
extend: 'Ext.layout.component.field.Field',
|
|
alias: ['layout.htmleditor'],
|
|
|
|
type: 'htmleditor',
|
|
|
|
sizeBodyContents: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
bodyEl = owner.bodyEl,
|
|
toolbar = owner.getToolbar(),
|
|
textarea = owner.textareaEl,
|
|
iframe = owner.iframeEl,
|
|
editorHeight;
|
|
|
|
if (Ext.isNumber(width)) {
|
|
width -= bodyEl.getFrameWidth('lr');
|
|
}
|
|
toolbar.setWidth(width);
|
|
textarea.setWidth(width);
|
|
iframe.setWidth(width);
|
|
|
|
|
|
if (Ext.isNumber(height)) {
|
|
editorHeight = height - toolbar.getHeight() - bodyEl.getFrameWidth('tb');
|
|
textarea.setHeight(editorHeight);
|
|
iframe.setHeight(editorHeight);
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.form.field.HtmlEditor', {
|
|
extend:'Ext.Component',
|
|
mixins: {
|
|
labelable: 'Ext.form.Labelable',
|
|
field: 'Ext.form.field.Field'
|
|
},
|
|
alias: 'widget.htmleditor',
|
|
alternateClassName: 'Ext.form.HtmlEditor',
|
|
requires: [
|
|
'Ext.tip.QuickTipManager',
|
|
'Ext.picker.Color',
|
|
'Ext.toolbar.Item',
|
|
'Ext.toolbar.Toolbar',
|
|
'Ext.util.Format',
|
|
'Ext.layout.component.field.HtmlEditor'
|
|
],
|
|
|
|
fieldSubTpl: [
|
|
'<div id="{cmpId}-toolbarWrap" class="{toolbarWrapCls}"></div>',
|
|
'<textarea id="{cmpId}-textareaEl" name="{name}" tabIndex="-1" class="{textareaCls}" ',
|
|
'style="{size}" autocomplete="off"></textarea>',
|
|
'<iframe id="{cmpId}-iframeEl" name="{iframeName}" frameBorder="0" style="overflow:auto;{size}" src="{iframeSrc}"></iframe>',
|
|
{
|
|
compiled: true,
|
|
disableFormats: true
|
|
}
|
|
],
|
|
|
|
|
|
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'
|
|
],
|
|
defaultFont: 'tahoma',
|
|
|
|
defaultValue: (Ext.isOpera || Ext.isIE6) ? ' ' : '​',
|
|
|
|
fieldBodyCls: Ext.baseCSSPrefix + 'html-editor-wrap',
|
|
|
|
componentLayout: 'htmleditor',
|
|
|
|
|
|
initialized : false,
|
|
activated : false,
|
|
sourceEditMode : false,
|
|
iframePad:3,
|
|
hideMode:'offsets',
|
|
|
|
maskOnDisable: true,
|
|
|
|
|
|
initComponent : function(){
|
|
var me = this;
|
|
|
|
me.addEvents(
|
|
|
|
'initialize',
|
|
|
|
'activate',
|
|
|
|
'beforesync',
|
|
|
|
'beforepush',
|
|
|
|
'sync',
|
|
|
|
'push',
|
|
|
|
'editmodechange'
|
|
);
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
me.initLabelable();
|
|
me.initField();
|
|
},
|
|
|
|
|
|
createToolbar : function(editor){
|
|
var me = this,
|
|
items = [],
|
|
tipsEnabled = Ext.tip.QuickTipManager && Ext.tip.QuickTipManager.isEnabled(),
|
|
baseCSSPrefix = Ext.baseCSSPrefix,
|
|
fontSelectItem, toolbar, undef;
|
|
|
|
function btn(id, toggle, handler){
|
|
return {
|
|
itemId : id,
|
|
cls : baseCSSPrefix + 'btn-icon',
|
|
iconCls: baseCSSPrefix + 'edit-'+id,
|
|
enableToggle:toggle !== false,
|
|
scope: editor,
|
|
handler:handler||editor.relayBtnCmd,
|
|
clickEvent:'mousedown',
|
|
tooltip: tipsEnabled ? editor.buttonTips[id] || undef : undef,
|
|
overflowText: editor.buttonTips[id].title || undef,
|
|
tabIndex:-1
|
|
};
|
|
}
|
|
|
|
|
|
if (me.enableFont && !Ext.isSafari2) {
|
|
fontSelectItem = Ext.widget('component', {
|
|
renderTpl: [
|
|
'<select id="{id}-selectEl" class="{cls}">',
|
|
'<tpl for="fonts">',
|
|
'<option value="{[values.toLowerCase()]}" style="font-family:{.}"<tpl if="values.toLowerCase()==parent.defaultFont"> selected</tpl>>{.}</option>',
|
|
'</tpl>',
|
|
'</select>'
|
|
],
|
|
renderData: {
|
|
cls: baseCSSPrefix + 'font-select',
|
|
fonts: me.fontFamilies,
|
|
defaultFont: me.defaultFont
|
|
},
|
|
childEls: ['selectEl'],
|
|
onDisable: function() {
|
|
var selectEl = this.selectEl;
|
|
if (selectEl) {
|
|
selectEl.dom.disabled = true;
|
|
}
|
|
Ext.Component.superclass.onDisable.apply(this, arguments);
|
|
},
|
|
onEnable: function() {
|
|
var selectEl = this.selectEl;
|
|
if (selectEl) {
|
|
selectEl.dom.disabled = false;
|
|
}
|
|
Ext.Component.superclass.onEnable.apply(this, arguments);
|
|
}
|
|
});
|
|
|
|
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: editor.buttonTips.forecolor.title,
|
|
tooltip: tipsEnabled ? editor.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.execCmd('forecolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
|
|
me.deferFocus();
|
|
this.up('menu').hide();
|
|
}
|
|
}]
|
|
})
|
|
}, {
|
|
itemId: 'backcolor',
|
|
cls: baseCSSPrefix + 'btn-icon',
|
|
iconCls: baseCSSPrefix + 'edit-backcolor',
|
|
overflowText: editor.buttonTips.backcolor.title,
|
|
tooltip: tipsEnabled ? editor.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.execCmd(Ext.isOpera ? 'hilitecolor' : 'backcolor', Ext.isWebKit || Ext.isIE ? '#'+color : color);
|
|
me.deferFocus();
|
|
}
|
|
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);
|
|
})
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
toolbar = Ext.widget('toolbar', {
|
|
renderTo: me.toolbarWrap,
|
|
enableOverflow: true,
|
|
items: items
|
|
});
|
|
|
|
if (fontSelectItem) {
|
|
me.fontSelect = fontSelectItem.selectEl;
|
|
|
|
me.mon(me.fontSelect, 'change', function(){
|
|
me.relayCmd('fontname', me.fontSelect.dom.value);
|
|
me.deferFocus();
|
|
});
|
|
}
|
|
|
|
|
|
me.mon(toolbar.el, 'click', function(e){
|
|
e.preventDefault();
|
|
});
|
|
|
|
me.toolbar = toolbar;
|
|
},
|
|
|
|
onDisable: function() {
|
|
this.bodyEl.mask();
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
onEnable: function() {
|
|
this.bodyEl.unmask();
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
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) {
|
|
|
|
iframeEl.setDisplayed(false);
|
|
body.contentEditable = !readOnly;
|
|
iframeEl.setDisplayed(true);
|
|
} else {
|
|
me.setDesignMode(!readOnly);
|
|
}
|
|
if (body) {
|
|
body.style.cursor = readOnly ? 'default' : 'text';
|
|
}
|
|
me.disableItems(readOnly);
|
|
}
|
|
},
|
|
|
|
|
|
getDocMarkup: function() {
|
|
var me = this,
|
|
h = me.iframeEl.getHeight() - me.iframePad * 2;
|
|
return Ext.String.format('<html><head><style type="text/css">body{border:0;margin:0;padding:{0}px;height:{1}px;box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box;cursor:text}</style></head><body></body></html>', me.iframePad, h);
|
|
},
|
|
|
|
|
|
getEditorBody: function() {
|
|
var doc = this.getDoc();
|
|
return doc.body || doc.documentElement;
|
|
},
|
|
|
|
|
|
getDoc: function() {
|
|
return (!Ext.isIE && this.iframeEl.dom.contentDocument) || this.getWin().document;
|
|
},
|
|
|
|
|
|
getWin: function() {
|
|
return Ext.isIE ? this.iframeEl.dom.contentWindow : window.frames[this.iframeEl.dom.name];
|
|
},
|
|
|
|
|
|
onRender: function() {
|
|
var me = this;
|
|
|
|
me.onLabelableRender();
|
|
|
|
me.addChildEls('toolbarWrap', 'iframeEl', 'textareaEl');
|
|
|
|
me.callParent(arguments);
|
|
|
|
me.textareaEl.dom.value = me.value || '';
|
|
|
|
|
|
me.monitorTask = Ext.TaskManager.start({
|
|
run: me.checkDesignMode,
|
|
scope: me,
|
|
interval:100
|
|
});
|
|
|
|
me.createToolbar(me);
|
|
me.disableItems(true);
|
|
},
|
|
|
|
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());
|
|
},
|
|
|
|
getSubTplData: function() {
|
|
var cssPrefix = Ext.baseCSSPrefix;
|
|
return {
|
|
cmpId: this.id,
|
|
id: this.getInputId(),
|
|
toolbarWrapCls: cssPrefix + 'html-editor-tb',
|
|
textareaCls: cssPrefix + 'hidden',
|
|
iframeName: Ext.id(),
|
|
iframeSrc: Ext.SSL_SECURE_URL,
|
|
size: 'height:100px;'
|
|
};
|
|
},
|
|
|
|
getSubTplMarkup: function() {
|
|
var data = this.getSubTplData();
|
|
return this.getTpl('fieldSubTpl').apply(data);
|
|
},
|
|
|
|
getBodyNaturalWidth: function() {
|
|
return 565;
|
|
},
|
|
|
|
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 = {
|
|
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();
|
|
}
|
|
},
|
|
|
|
|
|
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';
|
|
}
|
|
},
|
|
|
|
|
|
getDesignMode: function() {
|
|
var doc = this.getDoc();
|
|
return !doc ? '' : String(doc.designMode).toLowerCase();
|
|
},
|
|
|
|
disableItems: function(disabled) {
|
|
this.getToolbar().items.each(function(item){
|
|
if(item.getItemId() !== 'sourceedit'){
|
|
item.setDisabled(disabled);
|
|
}
|
|
});
|
|
},
|
|
|
|
|
|
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();
|
|
}
|
|
else {
|
|
if (me.initialized) {
|
|
me.disableItems(me.readOnly);
|
|
}
|
|
me.pushValue();
|
|
iframe.removeCls(hiddenCls);
|
|
textarea.addCls(hiddenCls);
|
|
textarea.dom.setAttribute('tabIndex', -1);
|
|
me.deferFocus();
|
|
}
|
|
me.fireEvent('editmodechange', me, sourceEditMode);
|
|
me.doComponentLayout();
|
|
},
|
|
|
|
|
|
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;
|
|
me.mixins.field.setValue.call(me, value);
|
|
if (value === null || value === undefined) {
|
|
value = '';
|
|
}
|
|
if (textarea) {
|
|
textarea.dom.value = value;
|
|
}
|
|
me.pushValue();
|
|
return this;
|
|
},
|
|
|
|
|
|
cleanHtml: function(html) {
|
|
html = String(html);
|
|
if (Ext.isWebKit) {
|
|
html = html.replace(/\sclass="(?:Apple-style-span|khtml-block-placeholder)"/gi, '');
|
|
}
|
|
|
|
|
|
if (html.charCodeAt(0) === this.defaultValue.replace(/\D/g, '')) {
|
|
html = html.substring(1);
|
|
}
|
|
return html;
|
|
},
|
|
|
|
|
|
syncValue : function(){
|
|
var me = this,
|
|
body, html, bodyStyle, match;
|
|
if (me.initialized) {
|
|
body = me.getEditorBody();
|
|
html = body.innerHTML;
|
|
if (Ext.isWebKit) {
|
|
bodyStyle = body.getAttribute('style');
|
|
match = bodyStyle.match(/text-align:(.*?);/i);
|
|
if (match && match[1]) {
|
|
html = '<div style="' + match[0] + '">' + html + '</div>';
|
|
}
|
|
}
|
|
html = me.cleanHtml(html);
|
|
if (me.fireEvent('beforesync', me, html) !== false) {
|
|
me.textareaEl.dom.value = html;
|
|
me.fireEvent('sync', me, html);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
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) {
|
|
|
|
me.setDesignMode(false);
|
|
me.setDesignMode(true);
|
|
}
|
|
me.fireEvent('push', me, v);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
deferFocus : function(){
|
|
this.focus(false, true);
|
|
},
|
|
|
|
getFocusEl: function() {
|
|
var me = this,
|
|
win = me.win;
|
|
return win && !me.sourceEditMode ? win : me.textareaEl;
|
|
},
|
|
|
|
|
|
initEditor : function(){
|
|
|
|
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';
|
|
dbody.bgProperties = 'fixed';
|
|
|
|
Ext.DomHelper.applyStyles(dbody, ss);
|
|
|
|
doc = me.getDoc();
|
|
|
|
if (doc) {
|
|
try {
|
|
Ext.EventManager.removeAll(doc);
|
|
} catch(e) {}
|
|
}
|
|
|
|
|
|
fn = Ext.Function.bind(me.onEditorEvent, me);
|
|
Ext.EventManager.on(doc, {
|
|
mousedown: fn,
|
|
dblclick: fn,
|
|
click: fn,
|
|
keyup: fn,
|
|
buffer:100
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn = me.onRelayedEvent;
|
|
Ext.EventManager.on(doc, {
|
|
mousedown: fn,
|
|
mousemove: fn,
|
|
mouseup: fn,
|
|
click: fn,
|
|
dblclick: fn,
|
|
scope: me
|
|
});
|
|
|
|
if (Ext.isGecko) {
|
|
Ext.EventManager.on(doc, 'keypress', me.applyCommand, me);
|
|
}
|
|
if (me.fixKeys) {
|
|
Ext.EventManager.on(doc, 'keydown', me.fixKeys, me);
|
|
}
|
|
|
|
|
|
Ext.EventManager.on(window, 'unload', me.beforeDestroy, me);
|
|
doc.editorInitialized = true;
|
|
|
|
me.initialized = true;
|
|
me.pushValue();
|
|
me.setReadOnly(me.readOnly);
|
|
me.fireEvent('initialize', me);
|
|
} catch(ex) {
|
|
|
|
}
|
|
},
|
|
|
|
|
|
beforeDestroy : function(){
|
|
var me = this,
|
|
monitorTask = me.monitorTask,
|
|
doc, prop;
|
|
|
|
if (monitorTask) {
|
|
Ext.TaskManager.stop(monitorTask);
|
|
}
|
|
if (me.rendered) {
|
|
try {
|
|
doc = me.getDoc();
|
|
if (doc) {
|
|
Ext.EventManager.removeAll(doc);
|
|
for (prop in doc) {
|
|
if (doc.hasOwnProperty(prop)) {
|
|
delete doc[prop];
|
|
}
|
|
}
|
|
}
|
|
} catch(e) {
|
|
|
|
}
|
|
Ext.destroyMembers(me, 'tb', 'toolbarWrap', 'iframeEl', 'textareaEl');
|
|
}
|
|
me.callParent();
|
|
},
|
|
|
|
|
|
onRelayedEvent: function (event) {
|
|
|
|
|
|
var iframeEl = this.iframeEl,
|
|
iframeXY = iframeEl.getXY(),
|
|
eventXY = event.getXY();
|
|
|
|
|
|
|
|
event.xy = [iframeXY[0] + eventXY[0], iframeXY[1] + eventXY[1]];
|
|
|
|
event.injectEvent(iframeEl);
|
|
|
|
event.xy = eventXY;
|
|
},
|
|
|
|
|
|
onFirstFocus : function(){
|
|
var me = this,
|
|
selection, range;
|
|
me.activated = true;
|
|
me.disableItems(me.readOnly);
|
|
if (Ext.isGecko) {
|
|
me.win.focus();
|
|
selection = me.win.getSelection();
|
|
if (!selection.focusNode || selection.focusNode.nodeType !== 3) {
|
|
range = selection.getRangeAt(0);
|
|
range.selectNodeContents(me.getEditorBody());
|
|
range.collapse(true);
|
|
me.deferFocus();
|
|
}
|
|
try {
|
|
me.execCmd('useCSS', true);
|
|
me.execCmd('styleWithCSS', false);
|
|
} catch(e) {
|
|
|
|
}
|
|
}
|
|
me.fireEvent('activate', me);
|
|
},
|
|
|
|
|
|
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) {
|
|
|
|
|
|
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) {
|
|
adjust *= 2;
|
|
}
|
|
size = Math.max(1, size + adjust) + (isSafari ? 'px' : 0);
|
|
}
|
|
this.execCmd('FontSize', size);
|
|
},
|
|
|
|
|
|
onEditorEvent: function(e) {
|
|
this.updateToolbar();
|
|
},
|
|
|
|
|
|
updateToolbar: function() {
|
|
var me = this,
|
|
btns, doc, name, fontSelect;
|
|
|
|
if (me.readOnly) {
|
|
return;
|
|
}
|
|
|
|
if (!me.activated) {
|
|
me.onFirstFocus();
|
|
return;
|
|
}
|
|
|
|
btns = me.getToolbar().items.map;
|
|
doc = me.getDoc();
|
|
|
|
if (me.enableFont && !Ext.isSafari2) {
|
|
name = (doc.queryCommandValue('FontName') || me.defaultFont).toLowerCase();
|
|
fontSelect = me.fontSelect.dom;
|
|
if (name !== fontSelect.value) {
|
|
fontSelect.value = name;
|
|
}
|
|
}
|
|
|
|
function updateButtons() {
|
|
Ext.Array.forEach(Ext.Array.toArray(arguments), function(name) {
|
|
btns[name].toggle(doc.queryCommandState(name));
|
|
});
|
|
}
|
|
if(me.enableFormat){
|
|
updateButtons('bold', 'italic', 'underline');
|
|
}
|
|
if(me.enableAlignments){
|
|
updateButtons('justifyleft', 'justifycenter', 'justifyright');
|
|
}
|
|
if(!Ext.isSafari2 && me.enableLists){
|
|
updateButtons('insertorderedlist', 'insertunorderedlist');
|
|
}
|
|
|
|
Ext.menu.Manager.hideAll();
|
|
|
|
me.syncValue();
|
|
},
|
|
|
|
|
|
relayBtnCmd: function(btn) {
|
|
this.relayCmd(btn.getItemId());
|
|
},
|
|
|
|
|
|
relayCmd: function(cmd, value) {
|
|
Ext.defer(function() {
|
|
var me = this;
|
|
me.focus();
|
|
me.execCmd(cmd, value);
|
|
me.updateToolbar();
|
|
}, 10, this);
|
|
},
|
|
|
|
|
|
execCmd : function(cmd, value){
|
|
var me = this,
|
|
doc = me.getDoc(),
|
|
undef;
|
|
doc.execCommand(cmd, false, value === undef ? null : value);
|
|
me.syncValue();
|
|
},
|
|
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
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();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
fixKeys: function() {
|
|
if (Ext.isIE) {
|
|
return function(e){
|
|
var me = this,
|
|
k = e.getKey(),
|
|
doc = me.getDoc(),
|
|
range, target;
|
|
if (k === e.TAB) {
|
|
e.stopEvent();
|
|
range = doc.selection.createRange();
|
|
if(range){
|
|
range.collapse(true);
|
|
range.pasteHTML(' ');
|
|
me.deferFocus();
|
|
}
|
|
}
|
|
else if (k === e.ENTER) {
|
|
range = doc.selection.createRange();
|
|
if (range) {
|
|
target = range.parentElement();
|
|
if(!target || target.tagName.toLowerCase() !== 'li'){
|
|
e.stopEvent();
|
|
range.pasteHTML('<br />');
|
|
range.collapse(false);
|
|
range.select();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
if (Ext.isOpera) {
|
|
return function(e){
|
|
var me = this;
|
|
if (e.getKey() === e.TAB) {
|
|
e.stopEvent();
|
|
me.win.focus();
|
|
me.execCmd('InsertHTML',' ');
|
|
me.deferFocus();
|
|
}
|
|
};
|
|
}
|
|
|
|
if (Ext.isWebKit) {
|
|
return function(e){
|
|
var me = this,
|
|
k = e.getKey();
|
|
if (k === e.TAB) {
|
|
e.stopEvent();
|
|
me.execCmd('InsertText','\t');
|
|
me.deferFocus();
|
|
}
|
|
else if (k === e.ENTER) {
|
|
e.stopEvent();
|
|
me.execCmd('InsertHtml','<br /><br />');
|
|
me.deferFocus();
|
|
}
|
|
};
|
|
}
|
|
|
|
return null;
|
|
}(),
|
|
|
|
|
|
getToolbar : function(){
|
|
return this.toolbar;
|
|
},
|
|
|
|
|
|
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'
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.field.Radio', {
|
|
extend:'Ext.form.field.Checkbox',
|
|
alias: ['widget.radiofield', 'widget.radio'],
|
|
alternateClassName: 'Ext.form.Radio',
|
|
requires: ['Ext.form.RadioManager'],
|
|
|
|
isRadio: true,
|
|
|
|
|
|
|
|
|
|
inputType: 'radio',
|
|
ariaRole: 'radio',
|
|
|
|
|
|
getGroupValue: function() {
|
|
var selected = this.getManager().getChecked(this.name);
|
|
return selected ? selected.inputValue : null;
|
|
},
|
|
|
|
|
|
onBoxClick: function(e) {
|
|
var me = this;
|
|
if (!me.disabled && !me.readOnly) {
|
|
this.setValue(true);
|
|
}
|
|
},
|
|
|
|
|
|
setValue: function(v) {
|
|
var me = this,
|
|
active;
|
|
|
|
if (Ext.isBoolean(v)) {
|
|
me.callParent(arguments);
|
|
} else {
|
|
active = me.getManager().getWithValue(me.name, v).getAt(0);
|
|
if (active) {
|
|
active.setValue(true);
|
|
}
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
getSubmitValue: function() {
|
|
return this.checked ? this.inputValue : null;
|
|
},
|
|
|
|
getModelData: function() {
|
|
return this.getSubmitData();
|
|
},
|
|
|
|
|
|
onChange: function(newVal, oldVal) {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
|
|
if (newVal) {
|
|
this.getManager().getByName(me.name).each(function(item){
|
|
if (item !== me) {
|
|
item.setValue(false);
|
|
}
|
|
}, me);
|
|
}
|
|
},
|
|
|
|
|
|
getManager: function() {
|
|
return Ext.form.RadioManager;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.picker.Time', {
|
|
extend: 'Ext.view.BoundList',
|
|
alias: 'widget.timepicker',
|
|
requires: ['Ext.data.Store', 'Ext.Date'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
increment: 15,
|
|
|
|
|
|
format : "g:i A",
|
|
|
|
|
|
displayField: 'disp',
|
|
|
|
|
|
initDate: [2008,0,1],
|
|
|
|
componentCls: Ext.baseCSSPrefix + 'timepicker',
|
|
|
|
|
|
loadMask: false,
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
dateUtil = Ext.Date,
|
|
clearTime = dateUtil.clearTime,
|
|
initDate = me.initDate;
|
|
|
|
|
|
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();
|
|
me.updateList();
|
|
|
|
me.callParent();
|
|
},
|
|
|
|
|
|
setMinValue: function(value) {
|
|
this.minValue = value;
|
|
this.updateList();
|
|
},
|
|
|
|
|
|
setMaxValue: function(value) {
|
|
this.maxValue = value;
|
|
this.updateList();
|
|
},
|
|
|
|
|
|
normalizeDate: function(date) {
|
|
var initDate = this.initDate;
|
|
date.setFullYear(initDate[0], initDate[1], initDate[2]);
|
|
return date;
|
|
},
|
|
|
|
|
|
updateList: function() {
|
|
var me = this,
|
|
min = me.normalizeDate(me.minValue || me.absMin),
|
|
max = me.normalizeDate(me.maxValue || me.absMax);
|
|
|
|
me.store.filterBy(function(record) {
|
|
var date = record.get('date');
|
|
return date >= min && date <= max;
|
|
});
|
|
},
|
|
|
|
|
|
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 Ext.create('Ext.data.Store', {
|
|
fields: ['disp', 'date'],
|
|
data: times
|
|
});
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.form.field.Time', {
|
|
extend:'Ext.form.field.Picker',
|
|
alias: 'widget.timefield',
|
|
requires: ['Ext.form.field.Date', 'Ext.picker.Time', 'Ext.view.BoundListKeyNav', 'Ext.Date'],
|
|
alternateClassName: ['Ext.form.TimeField', 'Ext.form.Time'],
|
|
|
|
|
|
triggerCls: Ext.baseCSSPrefix + 'form-time-trigger',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
minText : "The time in this field must be equal to or after {0}",
|
|
|
|
|
|
maxText : "The time in this field must be equal to or before {0}",
|
|
|
|
|
|
invalidText : "{0} is not a valid time",
|
|
|
|
|
|
format : "g:i A",
|
|
|
|
|
|
|
|
|
|
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",
|
|
|
|
|
|
increment: 15,
|
|
|
|
|
|
pickerMaxHeight: 300,
|
|
|
|
|
|
selectOnTab: true,
|
|
|
|
|
|
initDate: '1/1/2008',
|
|
initDateFormat: 'j/n/Y',
|
|
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
min = me.minValue,
|
|
max = me.maxValue;
|
|
if (min) {
|
|
me.setMinValue(min);
|
|
}
|
|
if (max) {
|
|
me.setMaxValue(max);
|
|
}
|
|
this.callParent();
|
|
},
|
|
|
|
initValue: function() {
|
|
var me = this,
|
|
value = me.value;
|
|
|
|
|
|
if (Ext.isString(value)) {
|
|
me.value = me.rawToValue(value);
|
|
}
|
|
|
|
me.callParent();
|
|
},
|
|
|
|
|
|
setMinValue: function(value) {
|
|
var me = this,
|
|
picker = me.picker;
|
|
me.setLimit(value, true);
|
|
if (picker) {
|
|
picker.setMinValue(me.minValue);
|
|
}
|
|
},
|
|
|
|
|
|
setMaxValue: function(value) {
|
|
var me = this,
|
|
picker = me.picker;
|
|
me.setLimit(value, false);
|
|
if (picker) {
|
|
picker.setMaxValue(me.maxValue);
|
|
}
|
|
},
|
|
|
|
|
|
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 = Ext.Date.clearTime(new Date(me.initDate));
|
|
val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
|
|
me[isMin ? 'minValue' : 'maxValue'] = val;
|
|
}
|
|
},
|
|
|
|
rawToValue: function(rawValue) {
|
|
return this.parseDate(rawValue) || rawValue || null;
|
|
},
|
|
|
|
valueToRaw: function(value) {
|
|
return this.formatDate(this.parseDate(value));
|
|
},
|
|
|
|
|
|
getErrors: function(value) {
|
|
var me = this,
|
|
format = Ext.String.format,
|
|
errors = me.callParent(arguments),
|
|
minValue = me.minValue,
|
|
maxValue = me.maxValue,
|
|
date;
|
|
|
|
value = me.formatDate(value || me.processRawValue(me.getRawValue()));
|
|
|
|
if (value === null || value.length < 1) {
|
|
return errors;
|
|
}
|
|
|
|
date = me.parseDate(value);
|
|
if (!date) {
|
|
errors.push(format(me.invalidText, value, me.format));
|
|
return errors;
|
|
}
|
|
|
|
if (minValue && date < minValue) {
|
|
errors.push(format(me.minText, me.formatDate(minValue)));
|
|
}
|
|
|
|
if (maxValue && date > maxValue) {
|
|
errors.push(format(me.maxText, me.formatDate(maxValue)));
|
|
}
|
|
|
|
return errors;
|
|
},
|
|
|
|
formatDate: function() {
|
|
return Ext.form.field.Date.prototype.formatDate.apply(this, arguments);
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
safeParse: function(value, format){
|
|
var me = this,
|
|
utilDate = Ext.Date,
|
|
parsedDate,
|
|
result = null;
|
|
|
|
if (utilDate.formatContainsDateInfo(format)) {
|
|
|
|
result = utilDate.parse(value, format);
|
|
} else {
|
|
|
|
parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
|
|
if (parsedDate) {
|
|
result = parsedDate;
|
|
}
|
|
}
|
|
return result;
|
|
},
|
|
|
|
|
|
getSubmitValue: function() {
|
|
var me = this,
|
|
format = me.submitFormat || me.format,
|
|
value = me.getValue();
|
|
|
|
return value ? Ext.Date.format(value, format) : null;
|
|
},
|
|
|
|
|
|
createPicker: function() {
|
|
var me = this,
|
|
picker = Ext.create('Ext.picker.Time', {
|
|
pickerField: me,
|
|
selModel: {
|
|
mode: 'SINGLE'
|
|
},
|
|
floating: true,
|
|
hidden: true,
|
|
minValue: me.minValue,
|
|
maxValue: me.maxValue,
|
|
increment: me.increment,
|
|
format: me.format,
|
|
ownerCt: this.ownerCt,
|
|
renderTo: document.body,
|
|
maxHeight: me.pickerMaxHeight,
|
|
focusOnToFront: false
|
|
});
|
|
|
|
me.mon(picker.getSelectionModel(), {
|
|
selectionchange: me.onListSelect,
|
|
scope: me
|
|
});
|
|
|
|
return picker;
|
|
},
|
|
|
|
|
|
onExpand: function() {
|
|
var me = this,
|
|
keyNav = me.pickerKeyNav,
|
|
selectOnTab = me.selectOnTab,
|
|
picker = me.getPicker(),
|
|
lastSelected = picker.getSelectionModel().lastSelected,
|
|
itemNode;
|
|
|
|
if (!keyNav) {
|
|
keyNav = me.pickerKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
|
|
boundList: picker,
|
|
forceKeyDown: true,
|
|
tab: function(e) {
|
|
if (selectOnTab) {
|
|
if(me.picker.highlightedItem) {
|
|
this.selectHighlighted(e);
|
|
} else {
|
|
me.collapse();
|
|
}
|
|
me.triggerBlur();
|
|
}
|
|
|
|
return true;
|
|
}
|
|
});
|
|
|
|
if (selectOnTab) {
|
|
me.ignoreMonitorTab = true;
|
|
}
|
|
}
|
|
Ext.defer(keyNav.enable, 1, keyNav);
|
|
|
|
|
|
if (lastSelected) {
|
|
itemNode = picker.getNode(lastSelected);
|
|
if (itemNode) {
|
|
picker.highlightItem(itemNode);
|
|
picker.el.scrollChildIntoView(itemNode, false);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onCollapse: function() {
|
|
var me = this,
|
|
keyNav = me.pickerKeyNav;
|
|
if (keyNav) {
|
|
keyNav.disable();
|
|
me.ignoreMonitorTab = false;
|
|
}
|
|
},
|
|
|
|
|
|
onChange: function() {
|
|
var me = this,
|
|
picker = me.picker;
|
|
|
|
me.callParent(arguments);
|
|
if(picker) {
|
|
picker.clearHighlight();
|
|
}
|
|
},
|
|
|
|
|
|
onListSelect: function(list, recordArray) {
|
|
var me = this,
|
|
record = recordArray[0],
|
|
val = record ? record.get('date') : null;
|
|
me.setValue(val);
|
|
me.fireEvent('select', me, val);
|
|
me.picker.clearHighlight();
|
|
me.collapse();
|
|
me.inputEl.focus();
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.grid.CellEditor', {
|
|
extend: 'Ext.Editor',
|
|
constructor: function(config) {
|
|
config = Ext.apply({}, config);
|
|
|
|
if (config.field) {
|
|
config.field.monitorTab = false;
|
|
}
|
|
if (!Ext.isDefined(config.autoSize)) {
|
|
config.autoSize = {
|
|
width: 'boundEl'
|
|
};
|
|
}
|
|
this.callParent([config]);
|
|
},
|
|
|
|
|
|
onShow: function() {
|
|
var first = this.boundEl.first();
|
|
if (first) {
|
|
first.hide();
|
|
}
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
onHide: function() {
|
|
var first = this.boundEl.first();
|
|
if (first) {
|
|
first.show();
|
|
}
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
afterRender: function() {
|
|
this.callParent(arguments);
|
|
var field = this.field;
|
|
if (field.isXType('checkboxfield')) {
|
|
field.mon(field.inputEl, 'mousedown', this.onCheckBoxMouseDown, this);
|
|
field.mon(field.inputEl, 'click', this.onCheckBoxClick, this);
|
|
}
|
|
},
|
|
|
|
|
|
onCheckBoxMouseDown: function() {
|
|
this.completeEdit = Ext.emptyFn;
|
|
},
|
|
|
|
|
|
onCheckBoxClick: function() {
|
|
delete this.completeEdit;
|
|
this.field.focus(false, 10);
|
|
},
|
|
|
|
alignment: "tl-tl",
|
|
hideEl : false,
|
|
cls: Ext.baseCSSPrefix + "small-editor " + Ext.baseCSSPrefix + "grid-editor",
|
|
shim: false,
|
|
shadow: false
|
|
});
|
|
|
|
Ext.define('Ext.grid.ColumnLayout', {
|
|
extend: 'Ext.layout.container.HBox',
|
|
alias: 'layout.gridcolumn',
|
|
type : 'column',
|
|
|
|
reserveOffset: false,
|
|
|
|
shrinkToFit: false,
|
|
|
|
|
|
clearInnerCtOnLayout: true,
|
|
|
|
beforeLayout: function() {
|
|
var me = this,
|
|
i = 0,
|
|
items = me.getLayoutItems(),
|
|
len = items.length,
|
|
item, returnValue,
|
|
s;
|
|
|
|
|
|
if (!Ext.isDefined(me.availableSpaceOffset)) {
|
|
s = me.owner.up('tablepanel').verticalScroller;
|
|
me.availableSpaceOffset = s ? s.width-1 : 0;
|
|
}
|
|
|
|
returnValue = me.callParent(arguments);
|
|
|
|
|
|
me.innerCt.setHeight(23);
|
|
|
|
|
|
for (; i < len; i++) {
|
|
item = items[i];
|
|
item.el.setStyle({
|
|
height: 'auto'
|
|
});
|
|
item.titleContainer.setStyle({
|
|
height: 'auto',
|
|
paddingTop: '0'
|
|
});
|
|
if (item.componentLayout && item.componentLayout.lastComponentSize) {
|
|
item.componentLayout.lastComponentSize.height = item.el.dom.offsetHeight;
|
|
}
|
|
}
|
|
return returnValue;
|
|
},
|
|
|
|
|
|
calculateChildBoxes: function(visibleItems, targetSize) {
|
|
var me = this,
|
|
calculations = me.callParent(arguments),
|
|
boxes = calculations.boxes,
|
|
metaData = calculations.meta,
|
|
len = boxes.length, i = 0, box, item;
|
|
|
|
if (targetSize.width && !me.isHeader) {
|
|
|
|
if (me.owner.forceFit) {
|
|
|
|
for (; i < len; i++) {
|
|
box = boxes[i];
|
|
item = box.component;
|
|
|
|
|
|
item.minWidth = Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
|
|
|
|
|
|
|
|
item.flex = box.width;
|
|
}
|
|
|
|
|
|
calculations = me.callParent(arguments);
|
|
}
|
|
else if (metaData.tooNarrow) {
|
|
targetSize.width = metaData.desiredSize;
|
|
}
|
|
}
|
|
|
|
return calculations;
|
|
},
|
|
|
|
afterLayout: function() {
|
|
var me = this,
|
|
owner = me.owner,
|
|
topGrid,
|
|
bothHeaderCts,
|
|
otherHeaderCt,
|
|
thisHeight,
|
|
otherHeight,
|
|
modifiedGrid,
|
|
i = 0,
|
|
items,
|
|
len,
|
|
headerHeight;
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
if (!me.owner.hideHeaders) {
|
|
|
|
|
|
|
|
if (owner.lockableInjected) {
|
|
topGrid = owner.up('tablepanel').up('tablepanel');
|
|
bothHeaderCts = topGrid.query('headercontainer:not([isHeader])');
|
|
otherHeaderCt = (bothHeaderCts[0] === owner) ? bothHeaderCts[1] : bothHeaderCts[0];
|
|
|
|
|
|
if (!otherHeaderCt.rendered) {
|
|
return;
|
|
}
|
|
|
|
|
|
otherHeight = otherHeaderCt.layout.getRenderTarget().getViewSize().height;
|
|
if (!otherHeight) {
|
|
return;
|
|
}
|
|
thisHeight = this.getRenderTarget().getViewSize().height;
|
|
if (!thisHeight) {
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
topGrid.componentLayout.layoutBusy = true;
|
|
|
|
|
|
headerHeight = thisHeight;
|
|
|
|
|
|
if (thisHeight > otherHeight) {
|
|
otherHeaderCt.layout.align = 'stretch';
|
|
otherHeaderCt.setCalculatedSize(otherHeaderCt.getWidth(), owner.getHeight(), otherHeaderCt.ownerCt);
|
|
delete otherHeaderCt.layout.align;
|
|
modifiedGrid = otherHeaderCt.up('tablepanel');
|
|
} else if (otherHeight > thisHeight) {
|
|
headerHeight = otherHeight;
|
|
this.align = 'stretch';
|
|
owner.setCalculatedSize(owner.getWidth(), otherHeaderCt.getHeight(), owner.ownerCt);
|
|
delete this.align;
|
|
modifiedGrid = owner.up('tablepanel');
|
|
}
|
|
topGrid.componentLayout.layoutBusy = false;
|
|
|
|
|
|
items = bothHeaderCts[0].layout.getLayoutItems().concat(bothHeaderCts[1].layout.getLayoutItems());
|
|
} else {
|
|
headerHeight = this.getRenderTarget().getViewSize().height;
|
|
items = me.getLayoutItems();
|
|
}
|
|
|
|
len = items.length;
|
|
for (; i < len; i++) {
|
|
items[i].setPadding(headerHeight);
|
|
}
|
|
|
|
|
|
if (modifiedGrid) {
|
|
setTimeout(function() {
|
|
modifiedGrid.doLayout();
|
|
}, 1);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
|
|
updateInnerCtSize: function(tSize, calcs) {
|
|
var me = this,
|
|
extra;
|
|
|
|
|
|
if (!me.isHeader) {
|
|
me.tooNarrow = calcs.meta.tooNarrow;
|
|
extra = (me.reserveOffset ? me.availableSpaceOffset : 0);
|
|
|
|
if (calcs.meta.tooNarrow) {
|
|
tSize.width = calcs.meta.desiredSize + extra;
|
|
} else {
|
|
tSize.width += extra;
|
|
}
|
|
}
|
|
|
|
return me.callParent(arguments);
|
|
},
|
|
|
|
doOwnerCtLayouts: function() {
|
|
var ownerCt = this.owner.ownerCt;
|
|
if (!ownerCt.componentLayout.layoutBusy) {
|
|
ownerCt.doComponentLayout();
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.LockingView', {
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
eventRelayRe: /^(beforeitem|beforecontainer|item|container|cell)/,
|
|
|
|
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
|
|
});
|
|
},
|
|
|
|
getGridColumns: function() {
|
|
var cols = this.lockedGrid.headerCt.getGridColumns();
|
|
return cols.concat(this.normalGrid.headerCt.getGridColumns());
|
|
},
|
|
|
|
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);
|
|
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){
|
|
|
|
return this.normalView.getNode(nodeInfo);
|
|
},
|
|
|
|
getCell: function(record, column){
|
|
var view = this.getViewForColumn(column),
|
|
row;
|
|
|
|
row = view.getNode(record);
|
|
return Ext.fly(row).down(column.getCellSelector());
|
|
},
|
|
|
|
getRecord: function(node){
|
|
var result = this.lockedView.getRecord(node);
|
|
if (!node) {
|
|
result = this.normalView.getRecord(node);
|
|
}
|
|
return result;
|
|
},
|
|
|
|
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);
|
|
}
|
|
|
|
});
|
|
|
|
Ext.define('Ext.grid.Lockable', {
|
|
|
|
requires: ['Ext.grid.LockingView'],
|
|
|
|
|
|
syncRowHeight: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
spacerHidden: true,
|
|
|
|
headerCounter: 0,
|
|
|
|
|
|
unlockText: 'Unlock',
|
|
lockText: 'Lock',
|
|
|
|
determineXTypeToCreate: function() {
|
|
var me = this,
|
|
typeToCreate;
|
|
|
|
if (me.subGridXType) {
|
|
typeToCreate = me.subGridXType;
|
|
} else {
|
|
var 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,
|
|
|
|
|
|
|
|
xtype = me.determineXTypeToCreate(),
|
|
|
|
selModel = me.getSelectionModel(),
|
|
lockedGrid = {
|
|
xtype: xtype,
|
|
|
|
enableAnimations: false,
|
|
scroll: false,
|
|
scrollerOwner: false,
|
|
selModel: selModel,
|
|
border: false,
|
|
cls: Ext.baseCSSPrefix + 'grid-inner-locked'
|
|
},
|
|
normalGrid = {
|
|
xtype: xtype,
|
|
enableAnimations: false,
|
|
scrollerOwner: false,
|
|
selModel: selModel,
|
|
border: false
|
|
},
|
|
i = 0,
|
|
columns,
|
|
lockedHeaderCt,
|
|
normalHeaderCt;
|
|
|
|
me.addCls(Ext.baseCSSPrefix + 'grid-locked');
|
|
|
|
|
|
|
|
|
|
Ext.copyTo(normalGrid, me, me.normalCfgCopy);
|
|
Ext.copyTo(lockedGrid, me, me.lockedCfgCopy);
|
|
for (; 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(
|
|
|
|
'lockcolumn',
|
|
|
|
|
|
'unlockcolumn'
|
|
);
|
|
|
|
me.addStateEvents(['lockcolumn', 'unlockcolumn']);
|
|
|
|
me.lockedHeights = [];
|
|
me.normalHeights = [];
|
|
|
|
columns = me.processColumns(me.columns);
|
|
|
|
lockedGrid.width = columns.lockedWidth + Ext.num(selModel.headerWidth, 0);
|
|
lockedGrid.columns = columns.locked;
|
|
normalGrid.columns = columns.normal;
|
|
|
|
me.store = Ext.StoreManager.lookup(me.store);
|
|
lockedGrid.store = me.store;
|
|
normalGrid.store = me.store;
|
|
|
|
|
|
normalGrid.flex = 1;
|
|
lockedGrid.viewConfig = me.lockedViewConfig || {};
|
|
lockedGrid.viewConfig.loadingUseMsg = false;
|
|
normalGrid.viewConfig = me.normalViewConfig || {};
|
|
|
|
Ext.applyIf(lockedGrid.viewConfig, me.viewConfig);
|
|
Ext.applyIf(normalGrid.viewConfig, me.viewConfig);
|
|
|
|
me.normalGrid = Ext.ComponentManager.create(normalGrid);
|
|
me.lockedGrid = Ext.ComponentManager.create(lockedGrid);
|
|
|
|
me.view = Ext.create('Ext.grid.LockingView', {
|
|
locked: me.lockedGrid,
|
|
normal: me.normalGrid,
|
|
panel: me
|
|
});
|
|
|
|
if (me.syncRowHeight) {
|
|
me.lockedGrid.getView().on({
|
|
refresh: me.onLockedGridAfterRefresh,
|
|
itemupdate: me.onLockedGridAfterUpdate,
|
|
scope: me
|
|
});
|
|
|
|
me.normalGrid.getView().on({
|
|
refresh: me.onNormalGridAfterRefresh,
|
|
itemupdate: me.onNormalGridAfterUpdate,
|
|
scope: me
|
|
});
|
|
}
|
|
|
|
lockedHeaderCt = me.lockedGrid.headerCt;
|
|
normalHeaderCt = me.normalGrid.headerCt;
|
|
|
|
lockedHeaderCt.lockedCt = true;
|
|
lockedHeaderCt.lockableInjected = true;
|
|
normalHeaderCt.lockableInjected = true;
|
|
|
|
lockedHeaderCt.on({
|
|
columnshow: me.onLockedHeaderShow,
|
|
columnhide: me.onLockedHeaderHide,
|
|
columnmove: me.onLockedHeaderMove,
|
|
sortchange: me.onLockedHeaderSortChange,
|
|
columnresize: me.onLockedHeaderResize,
|
|
scope: me
|
|
});
|
|
|
|
normalHeaderCt.on({
|
|
columnmove: me.onNormalHeaderMove,
|
|
sortchange: me.onNormalHeaderSortChange,
|
|
scope: me
|
|
});
|
|
|
|
me.normalGrid.on({
|
|
scrollershow: me.onScrollerShow,
|
|
scrollerhide: me.onScrollerHide,
|
|
scope: me
|
|
});
|
|
|
|
me.lockedGrid.on('afterlayout', me.onLockedGridAfterLayout, me, {single: true});
|
|
|
|
me.modifyHeaderCt();
|
|
me.items = [me.lockedGrid, me.normalGrid];
|
|
|
|
me.relayHeaderCtEvents(lockedHeaderCt);
|
|
me.relayHeaderCtEvents(normalHeaderCt);
|
|
|
|
me.layout = {
|
|
type: 'hbox',
|
|
align: 'stretch'
|
|
};
|
|
},
|
|
|
|
processColumns: function(columns){
|
|
|
|
var i = 0,
|
|
len = columns.length,
|
|
lockedWidth = 1,
|
|
lockedHeaders = [],
|
|
normalHeaders = [],
|
|
column;
|
|
|
|
for (; i < len; ++i) {
|
|
column = columns[i];
|
|
|
|
|
|
column.processed = true;
|
|
if (column.locked) {
|
|
if (!column.hidden) {
|
|
lockedWidth += column.width || Ext.grid.header.Container.prototype.defaultWidth;
|
|
}
|
|
lockedHeaders.push(column);
|
|
} else {
|
|
normalHeaders.push(column);
|
|
}
|
|
if (!column.headerId) {
|
|
column.headerId = (column.initialConfig || column).id || ('L' + (++this.headerCounter));
|
|
}
|
|
}
|
|
return {
|
|
lockedWidth: lockedWidth,
|
|
locked: lockedHeaders,
|
|
normal: normalHeaders
|
|
};
|
|
},
|
|
|
|
|
|
onLockedGridAfterLayout: function() {
|
|
var me = this,
|
|
lockedView = me.lockedGrid.getView();
|
|
lockedView.on({
|
|
beforerefresh: me.destroySpacer,
|
|
scope: me
|
|
});
|
|
},
|
|
|
|
|
|
onLockedHeaderMove: function() {
|
|
if (this.syncRowHeight) {
|
|
this.onNormalGridAfterRefresh();
|
|
}
|
|
},
|
|
|
|
|
|
onNormalHeaderMove: function() {
|
|
if (this.syncRowHeight) {
|
|
this.onLockedGridAfterRefresh();
|
|
}
|
|
},
|
|
|
|
|
|
|
|
getSpacerEl: function() {
|
|
var me = this,
|
|
w,
|
|
view,
|
|
el;
|
|
|
|
if (!me.spacerEl) {
|
|
|
|
|
|
w = Ext.getScrollBarWidth() + (Ext.isIE ? 2 : 0);
|
|
view = me.lockedGrid.getView();
|
|
el = view.el;
|
|
|
|
me.spacerEl = Ext.DomHelper.append(el, {
|
|
cls: me.spacerHidden ? (Ext.baseCSSPrefix + 'hidden') : '',
|
|
style: 'height: ' + w + 'px;'
|
|
}, true);
|
|
}
|
|
return me.spacerEl;
|
|
},
|
|
|
|
destroySpacer: function() {
|
|
var me = this;
|
|
if (me.spacerEl) {
|
|
me.spacerEl.destroy();
|
|
delete me.spacerEl;
|
|
}
|
|
},
|
|
|
|
|
|
onLockedGridAfterRefresh: function() {
|
|
var me = this,
|
|
view = me.lockedGrid.getView(),
|
|
el = view.el,
|
|
rowEls = el.query(view.getItemSelector()),
|
|
ln = rowEls.length,
|
|
i = 0;
|
|
|
|
|
|
me.lockedHeights = [];
|
|
|
|
for (; i < ln; i++) {
|
|
me.lockedHeights[i] = rowEls[i].clientHeight;
|
|
}
|
|
me.syncRowHeights();
|
|
},
|
|
|
|
|
|
onNormalGridAfterRefresh: function() {
|
|
var me = this,
|
|
view = me.normalGrid.getView(),
|
|
el = view.el,
|
|
rowEls = el.query(view.getItemSelector()),
|
|
ln = rowEls.length,
|
|
i = 0;
|
|
|
|
|
|
me.normalHeights = [];
|
|
|
|
for (; i < ln; i++) {
|
|
me.normalHeights[i] = rowEls[i].clientHeight;
|
|
}
|
|
me.syncRowHeights();
|
|
},
|
|
|
|
|
|
onLockedGridAfterUpdate: function(record, index, node) {
|
|
this.lockedHeights[index] = node.clientHeight;
|
|
this.syncRowHeights();
|
|
},
|
|
|
|
|
|
onNormalGridAfterUpdate: function(record, index, node) {
|
|
this.normalHeights[index] = node.clientHeight;
|
|
this.syncRowHeights();
|
|
},
|
|
|
|
|
|
|
|
syncRowHeights: function() {
|
|
var me = this,
|
|
lockedHeights = me.lockedHeights,
|
|
normalHeights = me.normalHeights,
|
|
calcHeights = [],
|
|
ln = lockedHeights.length,
|
|
i = 0,
|
|
lockedView, normalView,
|
|
lockedRowEls, normalRowEls,
|
|
vertScroller = me.getVerticalScroller(),
|
|
scrollTop;
|
|
|
|
|
|
|
|
if (lockedHeights.length && normalHeights.length) {
|
|
lockedView = me.lockedGrid.getView();
|
|
normalView = me.normalGrid.getView();
|
|
lockedRowEls = lockedView.el.query(lockedView.getItemSelector());
|
|
normalRowEls = normalView.el.query(normalView.getItemSelector());
|
|
|
|
|
|
for (; i < ln; i++) {
|
|
|
|
if (!isNaN(lockedHeights[i]) && !isNaN(normalHeights[i])) {
|
|
if (lockedHeights[i] > normalHeights[i]) {
|
|
Ext.fly(normalRowEls[i]).setHeight(lockedHeights[i]);
|
|
} else if (lockedHeights[i] < normalHeights[i]) {
|
|
Ext.fly(lockedRowEls[i]).setHeight(normalHeights[i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
me.normalGrid.invalidateScroller();
|
|
|
|
|
|
|
|
if (vertScroller && vertScroller.setViewScrollTop) {
|
|
vertScroller.setViewScrollTop(me.virtualScrollTop);
|
|
} else {
|
|
|
|
|
|
|
|
scrollTop = normalView.el.dom.scrollTop;
|
|
normalView.el.dom.scrollTop = scrollTop;
|
|
lockedView.el.dom.scrollTop = scrollTop;
|
|
}
|
|
|
|
|
|
me.lockedHeights = [];
|
|
me.normalHeights = [];
|
|
}
|
|
},
|
|
|
|
|
|
onScrollerShow: function(scroller, direction) {
|
|
if (direction === 'horizontal') {
|
|
this.spacerHidden = false;
|
|
this.getSpacerEl().removeCls(Ext.baseCSSPrefix + 'hidden');
|
|
}
|
|
},
|
|
|
|
|
|
onScrollerHide: function(scroller, direction) {
|
|
if (direction === 'horizontal') {
|
|
this.spacerHidden = true;
|
|
if (this.spacerEl) {
|
|
this.spacerEl.addCls(Ext.baseCSSPrefix + 'hidden');
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
|
|
modifyHeaderCt: function() {
|
|
var me = this;
|
|
me.lockedGrid.headerCt.getMenuItems = me.getMenuItems(true);
|
|
me.normalGrid.headerCt.getMenuItems = me.getMenuItems(false);
|
|
},
|
|
|
|
onUnlockMenuClick: function() {
|
|
this.unlock();
|
|
},
|
|
|
|
onLockMenuClick: function() {
|
|
this.lock();
|
|
},
|
|
|
|
getMenuItems: function(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 = Ext.grid.header.Container.prototype.getMenuItems.call(this);
|
|
o.push('-',{
|
|
cls: unlockCls,
|
|
text: unlockText,
|
|
handler: unlockHandler,
|
|
disabled: !locked
|
|
});
|
|
o.push({
|
|
cls: lockCls,
|
|
text: lockText,
|
|
handler: lockHandler,
|
|
disabled: locked
|
|
});
|
|
return o;
|
|
};
|
|
},
|
|
|
|
|
|
|
|
lock: function(activeHd, toIdx) {
|
|
var me = this,
|
|
normalGrid = me.normalGrid,
|
|
lockedGrid = me.lockedGrid,
|
|
normalHCt = normalGrid.headerCt,
|
|
lockedHCt = lockedGrid.headerCt;
|
|
|
|
activeHd = activeHd || normalHCt.getMenu().activeHeader;
|
|
|
|
|
|
|
|
if (activeHd.flex) {
|
|
activeHd.width = activeHd.getWidth();
|
|
delete activeHd.flex;
|
|
}
|
|
|
|
normalHCt.remove(activeHd, false);
|
|
lockedHCt.suspendLayout = true;
|
|
activeHd.locked = true;
|
|
if (Ext.isDefined(toIdx)) {
|
|
lockedHCt.insert(toIdx, activeHd);
|
|
} else {
|
|
lockedHCt.add(activeHd);
|
|
}
|
|
lockedHCt.suspendLayout = false;
|
|
me.syncLockedSection();
|
|
|
|
me.fireEvent('lockcolumn', me, activeHd);
|
|
},
|
|
|
|
syncLockedSection: function() {
|
|
var me = this;
|
|
me.syncLockedWidth();
|
|
me.lockedGrid.getView().refresh();
|
|
me.normalGrid.getView().refresh();
|
|
},
|
|
|
|
|
|
|
|
syncLockedWidth: function() {
|
|
var me = this,
|
|
width = me.lockedGrid.headerCt.getFullWidth(true);
|
|
me.lockedGrid.setWidth(width+1);
|
|
me.doComponentLayout();
|
|
},
|
|
|
|
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);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
unlock: function(activeHd, toIdx) {
|
|
var me = this,
|
|
normalGrid = me.normalGrid,
|
|
lockedGrid = me.lockedGrid,
|
|
normalHCt = normalGrid.headerCt,
|
|
lockedHCt = lockedGrid.headerCt;
|
|
|
|
if (!Ext.isDefined(toIdx)) {
|
|
toIdx = 0;
|
|
}
|
|
activeHd = activeHd || lockedHCt.getMenu().activeHeader;
|
|
|
|
lockedHCt.remove(activeHd, false);
|
|
me.syncLockedWidth();
|
|
me.lockedGrid.getView().refresh();
|
|
activeHd.locked = false;
|
|
normalHCt.insert(toIdx, activeHd);
|
|
me.normalGrid.getView().refresh();
|
|
|
|
me.fireEvent('unlockcolumn', me, activeHd);
|
|
},
|
|
|
|
applyColumnsState: function (columns) {
|
|
var me = this,
|
|
lockedGrid = me.lockedGrid,
|
|
lockedHeaderCt = lockedGrid.headerCt,
|
|
normalHeaderCt = me.normalGrid.headerCt,
|
|
lockedCols = lockedHeaderCt.items,
|
|
normalCols = normalHeaderCt.items,
|
|
existing,
|
|
locked = [],
|
|
normal = [],
|
|
lockedDefault,
|
|
lockedWidth = 1;
|
|
|
|
Ext.each(columns, function (col) {
|
|
function matches (item) {
|
|
return item.headerId == col.id;
|
|
}
|
|
|
|
lockedDefault = true;
|
|
if (!(existing = lockedCols.findBy(matches))) {
|
|
existing = normalCols.findBy(matches);
|
|
lockedDefault = false;
|
|
}
|
|
|
|
if (existing) {
|
|
if (existing.applyColumnState) {
|
|
existing.applyColumnState(col);
|
|
}
|
|
if (!Ext.isDefined(existing.locked)) {
|
|
existing.locked = lockedDefault;
|
|
}
|
|
if (existing.locked) {
|
|
locked.push(existing);
|
|
if (!existing.hidden && Ext.isNumber(existing.width)) {
|
|
lockedWidth += existing.width;
|
|
}
|
|
} else {
|
|
normal.push(existing);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
if (locked.length + normal.length == lockedCols.getCount() + normalCols.getCount()) {
|
|
lockedHeaderCt.removeAll(false);
|
|
normalHeaderCt.removeAll(false);
|
|
|
|
lockedHeaderCt.add(locked);
|
|
normalHeaderCt.add(normal);
|
|
|
|
lockedGrid.setWidth(lockedWidth);
|
|
}
|
|
},
|
|
|
|
getColumnsState: function () {
|
|
var me = this,
|
|
locked = me.lockedGrid.headerCt.getColumnsState(),
|
|
normal = me.normalGrid.headerCt.getColumnsState();
|
|
|
|
return locked.concat(normal);
|
|
},
|
|
|
|
|
|
reconfigureLockable: function(store, columns) {
|
|
var me = this,
|
|
lockedGrid = me.lockedGrid,
|
|
normalGrid = me.normalGrid;
|
|
|
|
if (columns) {
|
|
lockedGrid.headerCt.suspendLayout = true;
|
|
normalGrid.headerCt.suspendLayout = true;
|
|
lockedGrid.headerCt.removeAll();
|
|
normalGrid.headerCt.removeAll();
|
|
|
|
columns = me.processColumns(columns);
|
|
lockedGrid.setWidth(columns.lockedWidth);
|
|
lockedGrid.headerCt.add(columns.locked);
|
|
normalGrid.headerCt.add(columns.normal);
|
|
}
|
|
|
|
if (store) {
|
|
store = Ext.data.StoreManager.lookup(store);
|
|
me.store = store;
|
|
lockedGrid.bindStore(store);
|
|
normalGrid.bindStore(store);
|
|
} else {
|
|
lockedGrid.getView().refresh();
|
|
normalGrid.getView().refresh();
|
|
}
|
|
|
|
if (columns) {
|
|
lockedGrid.headerCt.suspendLayout = false;
|
|
normalGrid.headerCt.suspendLayout = false;
|
|
lockedGrid.headerCt.forceComponentLayout();
|
|
normalGrid.headerCt.forceComponentLayout();
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.Scroller', {
|
|
extend: 'Ext.Component',
|
|
alias: 'widget.gridscroller',
|
|
weight: 110,
|
|
baseCls: Ext.baseCSSPrefix + 'scroller',
|
|
focusable: false,
|
|
reservedSpace: 0,
|
|
|
|
renderTpl: [
|
|
'<div class="' + Ext.baseCSSPrefix + 'scroller-ct" id="{baseId}_ct">',
|
|
'<div class="' + Ext.baseCSSPrefix + 'stretcher" id="{baseId}_stretch"></div>',
|
|
'</div>'
|
|
],
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
dock = me.dock,
|
|
cls = Ext.baseCSSPrefix + 'scroller-vertical';
|
|
|
|
me.offsets = {bottom: 0};
|
|
me.scrollProp = 'scrollTop';
|
|
me.vertical = true;
|
|
me.sizeProp = 'width';
|
|
|
|
if (dock === 'top' || dock === 'bottom') {
|
|
cls = Ext.baseCSSPrefix + 'scroller-horizontal';
|
|
me.sizeProp = 'height';
|
|
me.scrollProp = 'scrollLeft';
|
|
me.vertical = false;
|
|
me.weight += 5;
|
|
}
|
|
|
|
me.cls += (' ' + cls);
|
|
|
|
Ext.applyIf(me.renderSelectors, {
|
|
stretchEl: '.' + Ext.baseCSSPrefix + 'stretcher',
|
|
scrollEl: '.' + Ext.baseCSSPrefix + 'scroller-ct'
|
|
});
|
|
me.callParent();
|
|
},
|
|
|
|
ensureDimension: function(){
|
|
var me = this,
|
|
sizeProp = me.sizeProp;
|
|
|
|
me[sizeProp] = me.scrollerSize = Ext.getScrollbarSize()[sizeProp];
|
|
},
|
|
|
|
initRenderData: function () {
|
|
var me = this,
|
|
ret = me.callParent(arguments) || {};
|
|
|
|
ret.baseId = me.id;
|
|
|
|
return ret;
|
|
},
|
|
|
|
afterRender: function() {
|
|
var me = this;
|
|
me.callParent();
|
|
|
|
me.mon(me.scrollEl, 'scroll', me.onElScroll, me);
|
|
Ext.cache[me.el.id].skipGarbageCollection = true;
|
|
},
|
|
|
|
onAdded: function(container) {
|
|
|
|
this.ownerGrid = container;
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
getSizeCalculation: function() {
|
|
var me = this,
|
|
owner = me.getPanel(),
|
|
width = 1,
|
|
height = 1,
|
|
view, tbl;
|
|
|
|
if (!me.vertical) {
|
|
|
|
|
|
var items = owner.query('tableview'),
|
|
center = items[1] || items[0];
|
|
|
|
if (!center) {
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
width = center.headerCt.getFullWidth();
|
|
|
|
if (Ext.isIEQuirks) {
|
|
width--;
|
|
}
|
|
} else {
|
|
view = owner.down('tableview:not([lockableInjected])');
|
|
if (!view || !view.el) {
|
|
return false;
|
|
}
|
|
tbl = view.el.child('table', true);
|
|
if (!tbl) {
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
height = tbl.offsetHeight;
|
|
}
|
|
if (isNaN(width)) {
|
|
width = 1;
|
|
}
|
|
if (isNaN(height)) {
|
|
height = 1;
|
|
}
|
|
return {
|
|
width: width,
|
|
height: height
|
|
};
|
|
},
|
|
|
|
invalidate: function(firstPass) {
|
|
var me = this,
|
|
stretchEl = me.stretchEl;
|
|
|
|
if (!stretchEl || !me.ownerCt) {
|
|
return;
|
|
}
|
|
|
|
var size = me.getSizeCalculation(),
|
|
scrollEl = me.scrollEl,
|
|
elDom = scrollEl.dom,
|
|
reservedSpace = me.reservedSpace,
|
|
pos,
|
|
extra = 5;
|
|
|
|
if (size) {
|
|
stretchEl.setSize(size);
|
|
|
|
size = me.el.getSize(true);
|
|
|
|
if (me.vertical) {
|
|
size.width += extra;
|
|
size.height -= reservedSpace;
|
|
pos = 'left';
|
|
} else {
|
|
size.width -= reservedSpace;
|
|
size.height += extra;
|
|
pos = 'top';
|
|
}
|
|
|
|
scrollEl.setSize(size);
|
|
elDom.style[pos] = (-extra) + 'px';
|
|
|
|
|
|
|
|
elDom.scrollTop = elDom.scrollTop;
|
|
}
|
|
},
|
|
|
|
afterComponentLayout: function() {
|
|
this.callParent(arguments);
|
|
this.invalidate();
|
|
},
|
|
|
|
restoreScrollPos: function () {
|
|
var me = this,
|
|
el = this.scrollEl,
|
|
elDom = el && el.dom;
|
|
|
|
if (me._scrollPos !== null && elDom) {
|
|
elDom[me.scrollProp] = me._scrollPos;
|
|
me._scrollPos = null;
|
|
}
|
|
},
|
|
|
|
setReservedSpace: function (reservedSpace) {
|
|
var me = this;
|
|
if (me.reservedSpace !== reservedSpace) {
|
|
me.reservedSpace = reservedSpace;
|
|
me.invalidate();
|
|
}
|
|
},
|
|
|
|
saveScrollPos: function () {
|
|
var me = this,
|
|
el = this.scrollEl,
|
|
elDom = el && el.dom;
|
|
|
|
me._scrollPos = elDom ? elDom[me.scrollProp] : null;
|
|
},
|
|
|
|
|
|
setScrollTop: function(scrollTop) {
|
|
var el = this.scrollEl,
|
|
elDom = el && el.dom;
|
|
|
|
if (elDom) {
|
|
return elDom.scrollTop = Ext.Number.constrain(scrollTop, 0, elDom.scrollHeight - elDom.clientHeight);
|
|
}
|
|
},
|
|
|
|
|
|
setScrollLeft: function(scrollLeft) {
|
|
var el = this.scrollEl,
|
|
elDom = el && el.dom;
|
|
|
|
if (elDom) {
|
|
return elDom.scrollLeft = Ext.Number.constrain(scrollLeft, 0, elDom.scrollWidth - elDom.clientWidth);
|
|
}
|
|
},
|
|
|
|
|
|
scrollByDeltaY: function(delta) {
|
|
var el = this.scrollEl,
|
|
elDom = el && el.dom;
|
|
|
|
if (elDom) {
|
|
return this.setScrollTop(elDom.scrollTop + delta);
|
|
}
|
|
},
|
|
|
|
|
|
scrollByDeltaX: function(delta) {
|
|
var el = this.scrollEl,
|
|
elDom = el && el.dom;
|
|
|
|
if (elDom) {
|
|
return this.setScrollLeft(elDom.scrollLeft + delta);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
scrollToTop : function(){
|
|
this.setScrollTop(0);
|
|
},
|
|
|
|
|
|
onElScroll: function(event, target) {
|
|
this.fireEvent('bodyscroll', event, target);
|
|
},
|
|
|
|
getPanel: function() {
|
|
var me = this;
|
|
if (!me.panel) {
|
|
me.panel = this.up('[scrollerOwner]');
|
|
}
|
|
return me.panel;
|
|
}
|
|
});
|
|
|
|
|
|
|
|
Ext.define('Ext.grid.PagingScroller', {
|
|
extend: 'Ext.grid.Scroller',
|
|
alias: 'widget.paginggridscroller',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
percentageFromEdge: 0.35,
|
|
|
|
|
|
scrollToLoadBuffer: 200,
|
|
|
|
activePrefetch: true,
|
|
|
|
chunkSize: 50,
|
|
snapIncrement: 25,
|
|
|
|
syncScroll: true,
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
ds = me.store;
|
|
|
|
ds.on('guaranteedrange', me.onGuaranteedRange, me);
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
onGuaranteedRange: function(range, start, end) {
|
|
var me = this,
|
|
ds = me.store,
|
|
rs;
|
|
|
|
if (range.length && me.visibleStart < range[0].index) {
|
|
return;
|
|
}
|
|
|
|
ds.loadRecords(range);
|
|
|
|
if (!me.firstLoad) {
|
|
if (me.rendered) {
|
|
me.invalidate();
|
|
} else {
|
|
me.on('afterrender', me.invalidate, me, {single: true});
|
|
}
|
|
me.firstLoad = true;
|
|
} else {
|
|
|
|
|
|
if (me.scrollEl && me.scrollEl.dom && me.scrollEl.dom.scrollHeight) {
|
|
me.syncTo();
|
|
}
|
|
}
|
|
},
|
|
|
|
syncTo: function() {
|
|
var me = this,
|
|
pnl = me.getPanel(),
|
|
store = pnl.store,
|
|
scrollerElDom = this.scrollEl.dom,
|
|
rowOffset = me.visibleStart - store.guaranteedStart,
|
|
scrollBy = rowOffset * me.rowHeight,
|
|
scrollHeight = scrollerElDom.scrollHeight,
|
|
clientHeight = scrollerElDom.clientHeight,
|
|
scrollTop = scrollerElDom.scrollTop,
|
|
useMaximum;
|
|
|
|
|
|
|
|
|
|
if (Ext.isIE9 && Ext.isStrict) {
|
|
clientHeight = scrollerElDom.offsetHeight + 2;
|
|
}
|
|
|
|
|
|
|
|
useMaximum = (scrollHeight - clientHeight - scrollTop <= 0);
|
|
this.setViewScrollTop(scrollBy, useMaximum);
|
|
},
|
|
|
|
getPageData : function(){
|
|
var panel = this.getPanel(),
|
|
store = panel.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)
|
|
};
|
|
},
|
|
|
|
onElScroll: function(e, t) {
|
|
var me = this,
|
|
panel = me.getPanel(),
|
|
store = panel.store,
|
|
pageSize = store.pageSize,
|
|
guaranteedStart = store.guaranteedStart,
|
|
guaranteedEnd = store.guaranteedEnd,
|
|
totalCount = store.getTotalCount(),
|
|
numFromEdge = Math.ceil(me.percentageFromEdge * pageSize),
|
|
position = t.scrollTop,
|
|
visibleStart = Math.floor(position / me.rowHeight),
|
|
view = panel.down('tableview'),
|
|
viewEl = view.el,
|
|
visibleHeight = viewEl.getHeight(),
|
|
visibleAhead = Math.ceil(visibleHeight / me.rowHeight),
|
|
visibleEnd = visibleStart + visibleAhead,
|
|
prevPage = Math.floor(visibleStart / pageSize),
|
|
nextPage = Math.floor(visibleEnd / pageSize) + 2,
|
|
lastPage = Math.ceil(totalCount / pageSize),
|
|
snap = me.snapIncrement,
|
|
requestStart = Math.floor(visibleStart / snap) * snap,
|
|
requestEnd = requestStart + pageSize - 1,
|
|
activePrefetch = me.activePrefetch;
|
|
|
|
me.visibleStart = visibleStart;
|
|
me.visibleEnd = visibleEnd;
|
|
|
|
|
|
me.syncScroll = true;
|
|
if (totalCount >= pageSize) {
|
|
|
|
if (requestEnd > totalCount - 1) {
|
|
me.cancelLoad();
|
|
if (store.rangeSatisfied(totalCount - pageSize, totalCount - 1)) {
|
|
me.syncScroll = true;
|
|
}
|
|
store.guaranteeRange(totalCount - pageSize, totalCount - 1);
|
|
|
|
} else if (visibleStart <= guaranteedStart || visibleEnd > guaranteedEnd) {
|
|
if (visibleStart <= guaranteedStart) {
|
|
|
|
requestStart -= snap;
|
|
requestEnd -= snap;
|
|
|
|
if (requestStart < 0) {
|
|
requestStart = 0;
|
|
requestEnd = pageSize;
|
|
}
|
|
}
|
|
if (store.rangeSatisfied(requestStart, requestEnd)) {
|
|
me.cancelLoad();
|
|
store.guaranteeRange(requestStart, requestEnd);
|
|
} else {
|
|
store.mask();
|
|
me.attemptLoad(requestStart, requestEnd);
|
|
}
|
|
|
|
me.syncScroll = false;
|
|
} else if (activePrefetch && visibleStart < (guaranteedStart + numFromEdge) && prevPage > 0) {
|
|
me.syncScroll = true;
|
|
store.prefetchPage(prevPage);
|
|
} else if (activePrefetch && visibleEnd > (guaranteedEnd - numFromEdge) && nextPage < lastPage) {
|
|
me.syncScroll = true;
|
|
store.prefetchPage(nextPage);
|
|
}
|
|
}
|
|
|
|
if (me.syncScroll) {
|
|
me.syncTo();
|
|
}
|
|
},
|
|
|
|
getSizeCalculation: function() {
|
|
|
|
|
|
var me = this,
|
|
owner = me.ownerGrid,
|
|
view = owner.getView(),
|
|
store = me.store,
|
|
dock = me.dock,
|
|
elDom = me.el.dom,
|
|
width = 1,
|
|
height = 1;
|
|
|
|
if (!me.rowHeight) {
|
|
me.rowHeight = view.el.down(view.getItemSelector()).getHeight(false, true);
|
|
}
|
|
|
|
|
|
height = store[(!store.remoteFilter && store.isFiltered()) ? 'getCount' : 'getTotalCount']() * me.rowHeight;
|
|
|
|
if (isNaN(width)) {
|
|
width = 1;
|
|
}
|
|
if (isNaN(height)) {
|
|
height = 1;
|
|
}
|
|
return {
|
|
width: width,
|
|
height: height
|
|
};
|
|
},
|
|
|
|
attemptLoad: function(start, end) {
|
|
var me = this;
|
|
if (!me.loadTask) {
|
|
me.loadTask = Ext.create('Ext.util.DelayedTask', me.doAttemptLoad, me, []);
|
|
}
|
|
me.loadTask.delay(me.scrollToLoadBuffer, me.doAttemptLoad, me, [start, end]);
|
|
},
|
|
|
|
cancelLoad: function() {
|
|
if (this.loadTask) {
|
|
this.loadTask.cancel();
|
|
}
|
|
},
|
|
|
|
doAttemptLoad: function(start, end) {
|
|
var store = this.getPanel().store;
|
|
store.guaranteeRange(start, end);
|
|
},
|
|
|
|
setViewScrollTop: function(scrollTop, useMax) {
|
|
var me = this,
|
|
owner = me.getPanel(),
|
|
items = owner.query('tableview'),
|
|
i = 0,
|
|
len = items.length,
|
|
center,
|
|
centerEl,
|
|
calcScrollTop,
|
|
maxScrollTop,
|
|
scrollerElDom = me.el.dom;
|
|
|
|
owner.virtualScrollTop = scrollTop;
|
|
|
|
center = items[1] || items[0];
|
|
centerEl = center.el.dom;
|
|
|
|
maxScrollTop = ((owner.store.pageSize * me.rowHeight) - centerEl.clientHeight);
|
|
calcScrollTop = (scrollTop % ((owner.store.pageSize * me.rowHeight) + 1));
|
|
if (useMax) {
|
|
calcScrollTop = maxScrollTop;
|
|
}
|
|
if (calcScrollTop > maxScrollTop) {
|
|
|
|
return;
|
|
|
|
}
|
|
for (; i < len; i++) {
|
|
items[i].el.dom.scrollTop = calcScrollTop;
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.panel.Table', {
|
|
extend: 'Ext.panel.Panel',
|
|
|
|
alias: 'widget.tablepanel',
|
|
|
|
uses: [
|
|
'Ext.selection.RowModel',
|
|
'Ext.grid.Scroller',
|
|
'Ext.grid.header.Container',
|
|
'Ext.grid.Lockable'
|
|
],
|
|
|
|
extraBaseCls: Ext.baseCSSPrefix + 'grid',
|
|
extraBodyCls: Ext.baseCSSPrefix + 'grid-body',
|
|
|
|
layout: 'fit',
|
|
|
|
hasView: false,
|
|
|
|
|
|
|
|
viewType: null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
selType: 'rowmodel',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
scrollDelta: 40,
|
|
|
|
|
|
scroll: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
deferRowRender: true,
|
|
|
|
|
|
sortableColumns: true,
|
|
|
|
|
|
enableLocking: false,
|
|
|
|
verticalScrollDock: 'right',
|
|
verticalScrollerType: 'gridscroller',
|
|
|
|
horizontalScrollerPresentCls: Ext.baseCSSPrefix + 'horizontal-scroller-present',
|
|
verticalScrollerPresentCls: Ext.baseCSSPrefix + 'vertical-scroller-present',
|
|
|
|
|
|
|
|
scrollerOwner: true,
|
|
|
|
invalidateScrollerOnRefresh: true,
|
|
|
|
|
|
enableColumnMove: true,
|
|
|
|
|
|
enableColumnResize: true,
|
|
|
|
|
|
enableColumnHide: true,
|
|
|
|
initComponent: function() {
|
|
|
|
var me = this,
|
|
scroll = me.scroll,
|
|
vertical = false,
|
|
horizontal = false,
|
|
headerCtCfg = me.columns || me.colModel,
|
|
i = 0,
|
|
view,
|
|
border = me.border;
|
|
|
|
if (me.hideHeaders) {
|
|
border = false;
|
|
}
|
|
|
|
|
|
me.store = Ext.data.StoreManager.lookup(me.store || 'ext-empty-store');
|
|
|
|
|
|
|
|
if (headerCtCfg instanceof Ext.grid.header.Container) {
|
|
me.headerCt = headerCtCfg;
|
|
me.headerCt.border = border;
|
|
me.columns = me.headerCt.items.items;
|
|
} else {
|
|
if (Ext.isArray(headerCtCfg)) {
|
|
headerCtCfg = {
|
|
items: headerCtCfg,
|
|
border: border
|
|
};
|
|
}
|
|
Ext.apply(headerCtCfg, {
|
|
forceFit: me.forceFit,
|
|
sortable: me.sortableColumns,
|
|
enableColumnMove: me.enableColumnMove,
|
|
enableColumnResize: me.enableColumnResize,
|
|
enableColumnHide: me.enableColumnHide,
|
|
border: border
|
|
});
|
|
me.columns = headerCtCfg.items;
|
|
|
|
|
|
|
|
if (me.enableLocking || Ext.ComponentQuery.query('{locked !== undefined}{processed != true}', me.columns).length) {
|
|
me.self.mixin('lockable', Ext.grid.Lockable);
|
|
me.injectLockable();
|
|
}
|
|
}
|
|
|
|
me.addEvents(
|
|
|
|
'reconfigure',
|
|
|
|
'viewready',
|
|
|
|
'scrollerhide',
|
|
|
|
'scrollershow'
|
|
);
|
|
|
|
me.bodyCls = me.bodyCls || '';
|
|
me.bodyCls += (' ' + me.extraBodyCls);
|
|
|
|
me.cls = me.cls || '';
|
|
me.cls += (' ' + me.extraBaseCls);
|
|
|
|
|
|
delete me.autoScroll;
|
|
|
|
|
|
|
|
if (!me.hasView) {
|
|
|
|
|
|
|
|
if (!me.headerCt) {
|
|
me.headerCt = Ext.create('Ext.grid.header.Container', headerCtCfg);
|
|
}
|
|
|
|
|
|
me.columns = me.headerCt.items.items;
|
|
|
|
if (me.hideHeaders) {
|
|
me.headerCt.height = 0;
|
|
me.headerCt.border = false;
|
|
me.headerCt.addCls(Ext.baseCSSPrefix + 'grid-header-ct-hidden');
|
|
me.addCls(Ext.baseCSSPrefix + 'grid-header-hidden');
|
|
|
|
|
|
if (Ext.isIEQuirks) {
|
|
me.headerCt.style = {
|
|
display: 'none'
|
|
};
|
|
}
|
|
}
|
|
|
|
|
|
if (scroll === true || scroll === 'both') {
|
|
vertical = horizontal = true;
|
|
} else if (scroll === 'horizontal') {
|
|
horizontal = true;
|
|
} else if (scroll === 'vertical') {
|
|
vertical = true;
|
|
|
|
} else {
|
|
me.headerCt.availableSpaceOffset = 0;
|
|
}
|
|
|
|
if (vertical) {
|
|
me.verticalScroller = Ext.ComponentManager.create(me.initVerticalScroller());
|
|
me.mon(me.verticalScroller, {
|
|
bodyscroll: me.onVerticalScroll,
|
|
scope: me
|
|
});
|
|
}
|
|
|
|
if (horizontal) {
|
|
me.horizontalScroller = Ext.ComponentManager.create(me.initHorizontalScroller());
|
|
me.mon(me.horizontalScroller, {
|
|
bodyscroll: me.onHorizontalScroll,
|
|
scope: me
|
|
});
|
|
}
|
|
|
|
me.headerCt.on('resize', me.onHeaderResize, me);
|
|
me.relayHeaderCtEvents(me.headerCt);
|
|
me.features = me.features || [];
|
|
if (!Ext.isArray(me.features)) {
|
|
me.features = [me.features];
|
|
}
|
|
me.dockedItems = me.dockedItems || [];
|
|
me.dockedItems.unshift(me.headerCt);
|
|
me.viewConfig = me.viewConfig || {};
|
|
me.viewConfig.invalidateScrollerOnRefresh = me.invalidateScrollerOnRefresh;
|
|
|
|
|
|
|
|
view = me.getView();
|
|
|
|
view.on({
|
|
afterrender: function () {
|
|
|
|
view.el.scroll = Ext.Function.bind(me.elScroll, me);
|
|
|
|
|
|
me.mon(view.el, {
|
|
mousewheel: me.onMouseWheel,
|
|
scope: me
|
|
});
|
|
},
|
|
single: true
|
|
});
|
|
me.items = [view];
|
|
me.hasView = true;
|
|
|
|
me.mon(view.store, {
|
|
load: me.onStoreLoad,
|
|
scope: me
|
|
});
|
|
me.mon(view, {
|
|
viewReady: me.onViewReady,
|
|
resize: me.onViewResize,
|
|
refresh: {
|
|
fn: me.onViewRefresh,
|
|
scope: me,
|
|
buffer: 50
|
|
},
|
|
scope: me
|
|
});
|
|
this.relayEvents(view, [
|
|
|
|
'beforeitemmousedown',
|
|
|
|
'beforeitemmouseup',
|
|
|
|
'beforeitemmouseenter',
|
|
|
|
'beforeitemmouseleave',
|
|
|
|
'beforeitemclick',
|
|
|
|
'beforeitemdblclick',
|
|
|
|
'beforeitemcontextmenu',
|
|
|
|
'itemmousedown',
|
|
|
|
'itemmouseup',
|
|
|
|
'itemmouseenter',
|
|
|
|
'itemmouseleave',
|
|
|
|
'itemclick',
|
|
|
|
'itemdblclick',
|
|
|
|
'itemcontextmenu',
|
|
|
|
'beforecontainermousedown',
|
|
|
|
'beforecontainermouseup',
|
|
|
|
'beforecontainermouseover',
|
|
|
|
'beforecontainermouseout',
|
|
|
|
'beforecontainerclick',
|
|
|
|
'beforecontainerdblclick',
|
|
|
|
'beforecontainercontextmenu',
|
|
|
|
'containermouseup',
|
|
|
|
'containermouseover',
|
|
|
|
'containermouseout',
|
|
|
|
'containerclick',
|
|
|
|
'containerdblclick',
|
|
|
|
'containercontextmenu',
|
|
|
|
'selectionchange',
|
|
|
|
'beforeselect',
|
|
|
|
'select',
|
|
|
|
'beforedeselect',
|
|
|
|
'deselect'
|
|
]);
|
|
}
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
onRender: function(){
|
|
var vScroll = this.verticalScroller,
|
|
hScroll = this.horizontalScroller;
|
|
|
|
if (vScroll) {
|
|
vScroll.ensureDimension();
|
|
}
|
|
if (hScroll) {
|
|
hScroll.ensureDimension();
|
|
}
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
initStateEvents: function(){
|
|
var events = this.stateEvents;
|
|
|
|
Ext.each(['columnresize', 'columnmove', 'columnhide', 'columnshow', 'sortchange'], function(event){
|
|
if (Ext.Array.indexOf(events, event)) {
|
|
events.push(event);
|
|
}
|
|
});
|
|
this.callParent();
|
|
},
|
|
|
|
|
|
initHorizontalScroller: function () {
|
|
var me = this,
|
|
ret = {
|
|
xtype: 'gridscroller',
|
|
dock: 'bottom',
|
|
section: me,
|
|
store: me.store
|
|
};
|
|
|
|
return ret;
|
|
},
|
|
|
|
|
|
initVerticalScroller: function () {
|
|
var me = this,
|
|
ret = me.verticalScroller || {};
|
|
|
|
Ext.applyIf(ret, {
|
|
xtype: me.verticalScrollerType,
|
|
dock: me.verticalScrollDock,
|
|
store: me.store
|
|
});
|
|
|
|
return ret;
|
|
},
|
|
|
|
relayHeaderCtEvents: function (headerCt) {
|
|
this.relayEvents(headerCt, [
|
|
|
|
'columnresize',
|
|
|
|
'columnmove',
|
|
|
|
'columnhide',
|
|
|
|
'columnshow',
|
|
|
|
'sortchange'
|
|
]);
|
|
},
|
|
|
|
getState: function(){
|
|
var me = this,
|
|
state = me.callParent(),
|
|
sorter = me.store.sorters.first();
|
|
|
|
state.columns = (me.headerCt || me).getColumnsState();
|
|
|
|
if (sorter) {
|
|
state.sort = {
|
|
property: sorter.property,
|
|
direction: sorter.direction
|
|
};
|
|
}
|
|
|
|
return state;
|
|
},
|
|
|
|
applyState: function(state) {
|
|
var me = this,
|
|
sorter = state.sort,
|
|
store = me.store,
|
|
columns = state.columns;
|
|
|
|
delete state.columns;
|
|
|
|
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (columns) {
|
|
(me.headerCt || me).applyColumnsState(columns);
|
|
}
|
|
|
|
if (sorter) {
|
|
if (store.remoteSort) {
|
|
store.sorters.add(Ext.create('Ext.util.Sorter', {
|
|
property: sorter.property,
|
|
direction: sorter.direction
|
|
}));
|
|
}
|
|
else {
|
|
store.sort(sorter.property, sorter.direction);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getStore: function(){
|
|
return this.store;
|
|
},
|
|
|
|
|
|
getView: function() {
|
|
var me = this,
|
|
sm;
|
|
|
|
if (!me.view) {
|
|
sm = me.getSelectionModel();
|
|
me.view = me.createComponent(Ext.apply({}, me.viewConfig, {
|
|
deferInitialRefresh: me.deferRowRender,
|
|
xtype: me.viewType,
|
|
store: me.store,
|
|
headerCt: me.headerCt,
|
|
selModel: sm,
|
|
features: me.features,
|
|
panel: me
|
|
}));
|
|
me.mon(me.view, {
|
|
uievent: me.processEvent,
|
|
scope: me
|
|
});
|
|
sm.view = me.view;
|
|
me.headerCt.view = me.view;
|
|
me.relayEvents(me.view, ['cellclick', 'celldblclick']);
|
|
}
|
|
return me.view;
|
|
},
|
|
|
|
|
|
setAutoScroll: Ext.emptyFn,
|
|
|
|
|
|
|
|
|
|
elScroll: function(direction, distance, animate) {
|
|
var me = this,
|
|
scroller;
|
|
|
|
if (direction === "up" || direction === "left") {
|
|
distance = -distance;
|
|
}
|
|
|
|
if (direction === "down" || direction === "up") {
|
|
scroller = me.getVerticalScroller();
|
|
|
|
|
|
if (scroller) {
|
|
scroller.scrollByDeltaY(distance);
|
|
}
|
|
} else {
|
|
scroller = me.getHorizontalScroller();
|
|
|
|
|
|
if (scroller) {
|
|
scroller.scrollByDeltaX(distance);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
processEvent: function(type, view, cell, recordIndex, cellIndex, e) {
|
|
var me = this,
|
|
header;
|
|
|
|
if (cellIndex !== -1) {
|
|
header = me.headerCt.getGridColumns()[cellIndex];
|
|
return header.processEvent.apply(header, arguments);
|
|
}
|
|
},
|
|
|
|
|
|
determineScrollbars: function() {
|
|
|
|
if (this.determineScrollbarsRunning) {
|
|
return;
|
|
}
|
|
this.determineScrollbarsRunning = true;
|
|
var me = this,
|
|
view = me.view,
|
|
box,
|
|
tableEl,
|
|
scrollWidth,
|
|
clientWidth,
|
|
scrollHeight,
|
|
clientHeight,
|
|
verticalScroller = me.verticalScroller,
|
|
horizontalScroller = me.horizontalScroller,
|
|
curScrollbars = (verticalScroller && verticalScroller.ownerCt === me ? 1 : 0) |
|
|
(horizontalScroller && horizontalScroller.ownerCt === me ? 2 : 0),
|
|
reqScrollbars = 0;
|
|
|
|
|
|
if (!me.collapsed && view && view.viewReady) {
|
|
|
|
|
|
|
|
box = view.el.getSize();
|
|
|
|
clientWidth = box.width + ((curScrollbars & 1) ? verticalScroller.width : 0);
|
|
clientHeight = box.height + ((curScrollbars & 2) ? horizontalScroller.height : 0);
|
|
|
|
|
|
|
|
|
|
scrollWidth = (me.headerCt.query('[flex]').length && !me.headerCt.layout.tooNarrow) ? 0 : me.headerCt.getFullWidth();
|
|
|
|
|
|
if (verticalScroller && verticalScroller.el) {
|
|
scrollHeight = verticalScroller.getSizeCalculation().height;
|
|
} else {
|
|
tableEl = view.el.child('table', true);
|
|
scrollHeight = tableEl ? tableEl.offsetHeight : 0;
|
|
}
|
|
|
|
|
|
|
|
if (scrollHeight > clientHeight) {
|
|
reqScrollbars = 1;
|
|
|
|
|
|
if (horizontalScroller && ((clientWidth - scrollWidth) < verticalScroller.width)) {
|
|
reqScrollbars = 3;
|
|
}
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
|
|
if (scrollWidth > clientWidth) {
|
|
reqScrollbars = 2;
|
|
|
|
|
|
if (verticalScroller && ((clientHeight - scrollHeight) < horizontalScroller.height)) {
|
|
reqScrollbars = 3;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (reqScrollbars !== curScrollbars) {
|
|
|
|
|
|
me.suspendLayout = true;
|
|
if (reqScrollbars & 1) {
|
|
me.showVerticalScroller();
|
|
} else {
|
|
me.hideVerticalScroller();
|
|
}
|
|
if (reqScrollbars & 2) {
|
|
me.showHorizontalScroller();
|
|
} else {
|
|
me.hideHorizontalScroller();
|
|
}
|
|
me.suspendLayout = false;
|
|
|
|
|
|
me.doComponentLayout();
|
|
|
|
me.getLayout().layout();
|
|
}
|
|
}
|
|
delete me.determineScrollbarsRunning;
|
|
},
|
|
|
|
onViewResize: function() {
|
|
this.determineScrollbars();
|
|
},
|
|
|
|
afterComponentLayout: function() {
|
|
this.callParent(arguments);
|
|
this.determineScrollbars();
|
|
this.invalidateScroller();
|
|
},
|
|
|
|
onHeaderResize: function() {
|
|
if (!this.componentLayout.layoutBusy && this.view && this.view.rendered) {
|
|
this.determineScrollbars();
|
|
this.invalidateScroller();
|
|
}
|
|
},
|
|
|
|
afterCollapse: function() {
|
|
var me = this;
|
|
if (me.verticalScroller) {
|
|
me.verticalScroller.saveScrollPos();
|
|
}
|
|
if (me.horizontalScroller) {
|
|
me.horizontalScroller.saveScrollPos();
|
|
}
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
afterExpand: function() {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
if (me.verticalScroller) {
|
|
me.verticalScroller.restoreScrollPos();
|
|
}
|
|
if (me.horizontalScroller) {
|
|
me.horizontalScroller.restoreScrollPos();
|
|
}
|
|
},
|
|
|
|
|
|
hideHorizontalScroller: function() {
|
|
var me = this;
|
|
|
|
if (me.horizontalScroller && me.horizontalScroller.ownerCt === me) {
|
|
me.verticalScroller.setReservedSpace(0);
|
|
me.removeDocked(me.horizontalScroller, false);
|
|
me.removeCls(me.horizontalScrollerPresentCls);
|
|
me.fireEvent('scrollerhide', me.horizontalScroller, 'horizontal');
|
|
}
|
|
|
|
},
|
|
|
|
|
|
showHorizontalScroller: function() {
|
|
var me = this;
|
|
|
|
if (me.verticalScroller) {
|
|
me.verticalScroller.setReservedSpace(Ext.getScrollbarSize().height - 1);
|
|
}
|
|
if (me.horizontalScroller && me.horizontalScroller.ownerCt !== me) {
|
|
me.addDocked(me.horizontalScroller);
|
|
me.addCls(me.horizontalScrollerPresentCls);
|
|
me.fireEvent('scrollershow', me.horizontalScroller, 'horizontal');
|
|
}
|
|
},
|
|
|
|
|
|
hideVerticalScroller: function() {
|
|
var me = this;
|
|
|
|
me.setHeaderReserveOffset(false);
|
|
if (me.verticalScroller && me.verticalScroller.ownerCt === me) {
|
|
me.removeDocked(me.verticalScroller, false);
|
|
me.removeCls(me.verticalScrollerPresentCls);
|
|
me.fireEvent('scrollerhide', me.verticalScroller, 'vertical');
|
|
}
|
|
},
|
|
|
|
|
|
showVerticalScroller: function() {
|
|
var me = this;
|
|
|
|
me.setHeaderReserveOffset(true);
|
|
if (me.verticalScroller && me.verticalScroller.ownerCt !== me) {
|
|
me.addDocked(me.verticalScroller);
|
|
me.addCls(me.verticalScrollerPresentCls);
|
|
me.fireEvent('scrollershow', me.verticalScroller, 'vertical');
|
|
}
|
|
},
|
|
|
|
setHeaderReserveOffset: function (reserveOffset) {
|
|
var headerCt = this.headerCt,
|
|
layout = headerCt.layout;
|
|
|
|
|
|
if (layout && layout.reserveOffset !== reserveOffset) {
|
|
layout.reserveOffset = reserveOffset;
|
|
if (!this.suspendLayout) {
|
|
headerCt.doLayout();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
invalidateScroller: function() {
|
|
var me = this,
|
|
vScroll = me.verticalScroller,
|
|
hScroll = me.horizontalScroller;
|
|
|
|
if (vScroll) {
|
|
vScroll.invalidate();
|
|
}
|
|
if (hScroll) {
|
|
hScroll.invalidate();
|
|
}
|
|
},
|
|
|
|
|
|
onHeaderMove: function(headerCt, header, fromIdx, toIdx) {
|
|
this.view.refresh();
|
|
},
|
|
|
|
|
|
onHeaderHide: function(headerCt, header) {
|
|
this.invalidateScroller();
|
|
},
|
|
|
|
onHeaderShow: function(headerCt, header) {
|
|
this.invalidateScroller();
|
|
},
|
|
|
|
getVerticalScroller: function() {
|
|
return this.getScrollerOwner().down('gridscroller[dock=' + this.verticalScrollDock + ']');
|
|
},
|
|
|
|
getHorizontalScroller: function() {
|
|
return this.getScrollerOwner().down('gridscroller[dock=bottom]');
|
|
},
|
|
|
|
onMouseWheel: function(e) {
|
|
var me = this,
|
|
vertScroller = me.getVerticalScroller(),
|
|
horizScroller = me.getHorizontalScroller(),
|
|
scrollDelta = -me.scrollDelta,
|
|
deltas = e.getWheelDeltas(),
|
|
deltaX = scrollDelta * deltas.x,
|
|
deltaY = scrollDelta * deltas.y,
|
|
vertScrollerEl, horizScrollerEl,
|
|
vertScrollerElDom, horizScrollerElDom,
|
|
horizontalCanScrollLeft, horizontalCanScrollRight,
|
|
verticalCanScrollDown, verticalCanScrollUp;
|
|
|
|
|
|
if (horizScroller) {
|
|
horizScrollerEl = horizScroller.scrollEl;
|
|
if (horizScrollerEl) {
|
|
horizScrollerElDom = horizScrollerEl.dom;
|
|
horizontalCanScrollRight = horizScrollerElDom.scrollLeft !== horizScrollerElDom.scrollWidth - horizScrollerElDom.clientWidth;
|
|
horizontalCanScrollLeft = horizScrollerElDom.scrollLeft !== 0;
|
|
}
|
|
}
|
|
if (vertScroller) {
|
|
vertScrollerEl = vertScroller.scrollEl;
|
|
if (vertScrollerEl) {
|
|
vertScrollerElDom = vertScrollerEl.dom;
|
|
verticalCanScrollDown = vertScrollerElDom.scrollTop !== vertScrollerElDom.scrollHeight - vertScrollerElDom.clientHeight;
|
|
verticalCanScrollUp = vertScrollerElDom.scrollTop !== 0;
|
|
}
|
|
}
|
|
|
|
if (horizScroller) {
|
|
if ((deltaX < 0 && horizontalCanScrollLeft) || (deltaX > 0 && horizontalCanScrollRight)) {
|
|
e.stopEvent();
|
|
horizScroller.scrollByDeltaX(deltaX);
|
|
}
|
|
}
|
|
if (vertScroller) {
|
|
if ((deltaY < 0 && verticalCanScrollUp) || (deltaY > 0 && verticalCanScrollDown)) {
|
|
e.stopEvent();
|
|
vertScroller.scrollByDeltaY(deltaY);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onViewReady: function() {
|
|
var me = this;
|
|
me.fireEvent('viewready', me);
|
|
if (me.deferRowRender) {
|
|
me.determineScrollbars();
|
|
me.invalidateScroller();
|
|
}
|
|
},
|
|
|
|
|
|
onViewRefresh: function() {
|
|
var me = this;
|
|
|
|
|
|
if (!me.rendering) {
|
|
this.determineScrollbars();
|
|
if (this.invalidateScrollerOnRefresh) {
|
|
this.invalidateScroller();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
setScrollTop: function(top) {
|
|
var me = this,
|
|
rootCmp = me.getScrollerOwner(),
|
|
verticalScroller = me.getVerticalScroller();
|
|
|
|
rootCmp.virtualScrollTop = top;
|
|
if (verticalScroller) {
|
|
verticalScroller.setScrollTop(top);
|
|
}
|
|
},
|
|
|
|
getScrollerOwner: function() {
|
|
var rootCmp = this;
|
|
if (!this.scrollerOwner) {
|
|
rootCmp = this.up('[scrollerOwner]');
|
|
}
|
|
return rootCmp;
|
|
},
|
|
|
|
|
|
scrollByDeltaY: function(deltaY) {
|
|
var verticalScroller = this.getVerticalScroller();
|
|
|
|
if (verticalScroller) {
|
|
verticalScroller.scrollByDeltaY(deltaY);
|
|
}
|
|
},
|
|
|
|
|
|
scrollByDeltaX: function(deltaX) {
|
|
var horizontalScroller = this.getHorizontalScroller();
|
|
|
|
if (horizontalScroller) {
|
|
horizontalScroller.scrollByDeltaX(deltaX);
|
|
}
|
|
},
|
|
|
|
|
|
getLhsMarker: function() {
|
|
var me = this;
|
|
|
|
if (!me.lhsMarker) {
|
|
me.lhsMarker = Ext.DomHelper.append(me.el, {
|
|
cls: Ext.baseCSSPrefix + 'grid-resize-marker'
|
|
}, true);
|
|
}
|
|
return me.lhsMarker;
|
|
},
|
|
|
|
|
|
getRhsMarker: function() {
|
|
var me = this;
|
|
|
|
if (!me.rhsMarker) {
|
|
me.rhsMarker = Ext.DomHelper.append(me.el, {
|
|
cls: Ext.baseCSSPrefix + 'grid-resize-marker'
|
|
}, true);
|
|
}
|
|
return me.rhsMarker;
|
|
},
|
|
|
|
|
|
getSelectionModel: function(){
|
|
if (!this.selModel) {
|
|
this.selModel = {};
|
|
}
|
|
|
|
var mode = 'SINGLE',
|
|
type;
|
|
if (this.simpleSelect) {
|
|
mode = 'SIMPLE';
|
|
} else if (this.multiSelect) {
|
|
mode = 'MULTI';
|
|
}
|
|
|
|
Ext.applyIf(this.selModel, {
|
|
allowDeselect: this.allowDeselect,
|
|
mode: mode
|
|
});
|
|
|
|
if (!this.selModel.events) {
|
|
type = this.selModel.selType || this.selType;
|
|
this.selModel = Ext.create('selection.' + type, this.selModel);
|
|
}
|
|
|
|
if (!this.selModel.hasRelaySetup) {
|
|
this.relayEvents(this.selModel, [
|
|
'selectionchange', 'beforeselect', 'beforedeselect', 'select', 'deselect'
|
|
]);
|
|
this.selModel.hasRelaySetup = true;
|
|
}
|
|
|
|
|
|
|
|
if (this.disableSelection) {
|
|
this.selModel.locked = true;
|
|
}
|
|
return this.selModel;
|
|
},
|
|
|
|
onVerticalScroll: function(event, target) {
|
|
var owner = this.getScrollerOwner(),
|
|
items = owner.query('tableview'),
|
|
i = 0,
|
|
len = items.length;
|
|
|
|
for (; i < len; i++) {
|
|
items[i].el.dom.scrollTop = target.scrollTop;
|
|
}
|
|
},
|
|
|
|
onHorizontalScroll: function(event, target) {
|
|
var owner = this.getScrollerOwner(),
|
|
items = owner.query('tableview'),
|
|
center = items[1] || items[0];
|
|
|
|
center.el.dom.scrollLeft = target.scrollLeft;
|
|
this.headerCt.el.dom.scrollLeft = target.scrollLeft;
|
|
},
|
|
|
|
|
|
onStoreLoad: Ext.emptyFn,
|
|
|
|
getEditorParent: function() {
|
|
return this.body;
|
|
},
|
|
|
|
bindStore: function(store) {
|
|
var me = this;
|
|
me.store = store;
|
|
me.getView().bindStore(store);
|
|
},
|
|
|
|
beforeDestroy: function(){
|
|
|
|
|
|
|
|
Ext.destroy(this.horizontalScroller, this.verticalScroller);
|
|
this.callParent();
|
|
},
|
|
|
|
|
|
reconfigure: function(store, columns) {
|
|
var me = this,
|
|
headerCt = me.headerCt;
|
|
|
|
if (me.lockable) {
|
|
me.reconfigureLockable(store, columns);
|
|
} else {
|
|
if (columns) {
|
|
headerCt.suspendLayout = true;
|
|
headerCt.removeAll();
|
|
headerCt.add(columns);
|
|
}
|
|
if (store) {
|
|
store = Ext.StoreManager.lookup(store);
|
|
me.bindStore(store);
|
|
} else {
|
|
me.getView().refresh();
|
|
}
|
|
if (columns) {
|
|
headerCt.suspendLayout = false;
|
|
me.forceComponentLayout();
|
|
}
|
|
}
|
|
me.fireEvent('reconfigure', me);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.view.Table', {
|
|
extend: 'Ext.view.View',
|
|
alias: 'widget.tableview',
|
|
uses: [
|
|
'Ext.view.TableChunker',
|
|
'Ext.util.DelayedTask',
|
|
'Ext.util.MixedCollection'
|
|
],
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'grid-view',
|
|
|
|
|
|
itemSelector: '.' + Ext.baseCSSPrefix + 'grid-row',
|
|
|
|
cellSelector: '.' + Ext.baseCSSPrefix + 'grid-cell',
|
|
|
|
selectedItemCls: Ext.baseCSSPrefix + 'grid-row-selected',
|
|
selectedCellCls: Ext.baseCSSPrefix + 'grid-cell-selected',
|
|
focusedItemCls: Ext.baseCSSPrefix + 'grid-row-focused',
|
|
overItemCls: Ext.baseCSSPrefix + 'grid-row-over',
|
|
altRowCls: Ext.baseCSSPrefix + 'grid-row-alt',
|
|
rowClsRe: /(?:^|\s*)grid-row-(first|last|alt)(?:\s+|$)/g,
|
|
cellRe: new RegExp('x-grid-cell-([^\\s]+) ', ''),
|
|
|
|
|
|
trackOver: true,
|
|
|
|
|
|
getRowClass: null,
|
|
|
|
initComponent: function() {
|
|
var me = this;
|
|
|
|
me.scrollState = {};
|
|
me.selModel.view = me;
|
|
me.headerCt.view = me;
|
|
me.initFeatures();
|
|
me.tpl = '<div></div>';
|
|
me.callParent();
|
|
me.mon(me.store, {
|
|
load: me.onStoreLoad,
|
|
scope: me
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
onStoreLoad: function(){
|
|
var me = this;
|
|
|
|
if (me.invalidateScrollerOnRefresh) {
|
|
if (Ext.isGecko) {
|
|
if (!me.scrollToTopTask) {
|
|
me.scrollToTopTask = Ext.create('Ext.util.DelayedTask', me.scrollToTop, me);
|
|
}
|
|
me.scrollToTopTask.delay(1);
|
|
} else {
|
|
me .scrollToTop();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
scrollToTop: Ext.emptyFn,
|
|
|
|
|
|
addElListener: function(eventName, fn, scope){
|
|
this.mon(this, eventName, fn, scope, {
|
|
element: 'el'
|
|
});
|
|
},
|
|
|
|
|
|
getGridColumns: function() {
|
|
return this.headerCt.getGridColumns();
|
|
},
|
|
|
|
|
|
getHeaderAtIndex: function(index) {
|
|
return this.headerCt.getHeaderAtIndex(index);
|
|
},
|
|
|
|
|
|
getCell: function(record, column) {
|
|
var row = this.getNode(record);
|
|
return Ext.fly(row).down(column.getCellSelector());
|
|
},
|
|
|
|
|
|
getFeature: function(id) {
|
|
var features = this.featuresMC;
|
|
if (features) {
|
|
return features.get(id);
|
|
}
|
|
},
|
|
|
|
|
|
initFeatures: function() {
|
|
var me = this,
|
|
i = 0,
|
|
features,
|
|
len;
|
|
|
|
me.features = me.features || [];
|
|
features = me.features;
|
|
len = features.length;
|
|
|
|
me.featuresMC = Ext.create('Ext.util.MixedCollection');
|
|
for (; i < len; i++) {
|
|
|
|
if (!features[i].isFeature) {
|
|
features[i] = Ext.create('feature.' + features[i].ftype, features[i]);
|
|
}
|
|
|
|
features[i].view = me;
|
|
me.featuresMC.add(features[i]);
|
|
}
|
|
},
|
|
|
|
|
|
attachEventsForFeatures: function() {
|
|
var features = this.features,
|
|
ln = features.length,
|
|
i = 0;
|
|
|
|
for (; i < ln; i++) {
|
|
if (features[i].isFeature) {
|
|
features[i].attachEvents();
|
|
}
|
|
}
|
|
},
|
|
|
|
afterRender: function() {
|
|
var me = this;
|
|
|
|
me.callParent();
|
|
me.mon(me.el, {
|
|
scroll: me.fireBodyScroll,
|
|
scope: me
|
|
});
|
|
me.el.unselectable();
|
|
me.attachEventsForFeatures();
|
|
},
|
|
|
|
fireBodyScroll: function(e, t) {
|
|
this.fireEvent('bodyscroll', e, t);
|
|
},
|
|
|
|
|
|
|
|
prepareData: function(data, idx, record) {
|
|
var me = this,
|
|
orig = me.headerCt.prepareData(data, idx, record, me, me.ownerCt),
|
|
features = me.features,
|
|
ln = features.length,
|
|
i = 0,
|
|
node, feature;
|
|
|
|
for (; i < ln; i++) {
|
|
feature = features[i];
|
|
if (feature.isFeature) {
|
|
Ext.apply(orig, feature.getAdditionalData(data, idx, record, orig, me));
|
|
}
|
|
}
|
|
|
|
return orig;
|
|
},
|
|
|
|
|
|
collectData: function(records, startIndex) {
|
|
var preppedRecords = this.callParent(arguments),
|
|
headerCt = this.headerCt,
|
|
fullWidth = headerCt.getFullWidth(),
|
|
features = this.features,
|
|
ln = features.length,
|
|
o = {
|
|
rows: preppedRecords,
|
|
fullWidth: fullWidth
|
|
},
|
|
i = 0,
|
|
feature,
|
|
j = 0,
|
|
jln,
|
|
rowParams;
|
|
|
|
jln = preppedRecords.length;
|
|
|
|
|
|
if (this.getRowClass) {
|
|
for (; j < jln; j++) {
|
|
rowParams = {};
|
|
preppedRecords[j]['rowCls'] = this.getRowClass(records[j], j, rowParams, this.store);
|
|
}
|
|
}
|
|
|
|
|
|
for (; i < ln; i++) {
|
|
feature = features[i];
|
|
if (feature.isFeature && feature.collectData && !feature.disabled) {
|
|
o = feature.collectData(records, preppedRecords, startIndex, fullWidth, o);
|
|
break;
|
|
}
|
|
}
|
|
return o;
|
|
},
|
|
|
|
|
|
|
|
onHeaderResize: function(header, w, suppressFocus) {
|
|
var me = this,
|
|
el = me.el;
|
|
|
|
if (el) {
|
|
me.saveScrollState();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (Ext.isIE6 || Ext.isIE7) {
|
|
if (header.el.hasCls(Ext.baseCSSPrefix + 'column-header-first')) {
|
|
w += 1;
|
|
}
|
|
}
|
|
el.select('.' + Ext.baseCSSPrefix + 'grid-col-resizer-'+header.id).setWidth(w);
|
|
el.select('.' + Ext.baseCSSPrefix + 'grid-table-resizer').setWidth(me.headerCt.getFullWidth());
|
|
me.restoreScrollState();
|
|
if (!me.ignoreTemplate) {
|
|
me.setNewTemplate();
|
|
}
|
|
if (!suppressFocus) {
|
|
me.el.focus();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onHeaderShow: function(headerCt, header, suppressFocus) {
|
|
var me = this;
|
|
me.ignoreTemplate = true;
|
|
|
|
if (header.oldWidth) {
|
|
me.onHeaderResize(header, header.oldWidth, suppressFocus);
|
|
delete header.oldWidth;
|
|
|
|
|
|
|
|
} else if (header.width && !header.flex) {
|
|
me.onHeaderResize(header, header.width, suppressFocus);
|
|
}
|
|
delete me.ignoreTemplate;
|
|
me.setNewTemplate();
|
|
},
|
|
|
|
|
|
onHeaderHide: function(headerCt, header, suppressFocus) {
|
|
this.onHeaderResize(header, 0, suppressFocus);
|
|
},
|
|
|
|
|
|
setNewTemplate: function() {
|
|
var me = this,
|
|
columns = me.headerCt.getColumnsForTpl(true);
|
|
|
|
me.tpl = me.getTableChunker().getTableTpl({
|
|
columns: columns,
|
|
features: me.features
|
|
});
|
|
},
|
|
|
|
|
|
getTableChunker: function() {
|
|
return this.chunker || Ext.view.TableChunker;
|
|
},
|
|
|
|
|
|
addRowCls: function(rowInfo, cls) {
|
|
var row = this.getNode(rowInfo);
|
|
if (row) {
|
|
Ext.fly(row).addCls(cls);
|
|
}
|
|
},
|
|
|
|
|
|
removeRowCls: function(rowInfo, cls) {
|
|
var row = this.getNode(rowInfo);
|
|
if (row) {
|
|
Ext.fly(row).removeCls(cls);
|
|
}
|
|
},
|
|
|
|
|
|
onRowSelect : function(rowIdx) {
|
|
this.addRowCls(rowIdx, this.selectedItemCls);
|
|
},
|
|
|
|
|
|
onRowDeselect : function(rowIdx) {
|
|
var me = this;
|
|
|
|
me.removeRowCls(rowIdx, me.selectedItemCls);
|
|
me.removeRowCls(rowIdx, me.focusedItemCls);
|
|
},
|
|
|
|
onCellSelect: function(position) {
|
|
var cell = this.getCellByPosition(position);
|
|
if (cell) {
|
|
cell.addCls(this.selectedCellCls);
|
|
}
|
|
},
|
|
|
|
onCellDeselect: function(position) {
|
|
var cell = this.getCellByPosition(position);
|
|
if (cell) {
|
|
cell.removeCls(this.selectedCellCls);
|
|
}
|
|
|
|
},
|
|
|
|
onCellFocus: function(position) {
|
|
|
|
this.focusCell(position);
|
|
},
|
|
|
|
getCellByPosition: function(position) {
|
|
var row = position.row,
|
|
column = position.column,
|
|
store = this.store,
|
|
node = this.getNode(row),
|
|
header = this.headerCt.getHeaderAtIndex(column),
|
|
cellSelector,
|
|
cell = false;
|
|
|
|
if (header && node) {
|
|
cellSelector = header.getCellSelector();
|
|
cell = Ext.fly(node).down(cellSelector);
|
|
}
|
|
return cell;
|
|
},
|
|
|
|
|
|
|
|
onRowFocus: function(rowIdx, highlight, supressFocus) {
|
|
var me = this,
|
|
row = me.getNode(rowIdx);
|
|
|
|
if (highlight) {
|
|
me.addRowCls(rowIdx, me.focusedItemCls);
|
|
if (!supressFocus) {
|
|
me.focusRow(rowIdx);
|
|
}
|
|
|
|
} else {
|
|
me.removeRowCls(rowIdx, me.focusedItemCls);
|
|
}
|
|
},
|
|
|
|
|
|
focusRow: function(rowIdx) {
|
|
var me = this,
|
|
row = me.getNode(rowIdx),
|
|
el = me.el,
|
|
adjustment = 0,
|
|
panel = me.ownerCt,
|
|
rowRegion,
|
|
elRegion,
|
|
record;
|
|
|
|
if (row && el) {
|
|
elRegion = el.getRegion();
|
|
rowRegion = Ext.fly(row).getRegion();
|
|
|
|
if (rowRegion.top < elRegion.top) {
|
|
adjustment = rowRegion.top - elRegion.top;
|
|
|
|
} else if (rowRegion.bottom > elRegion.bottom) {
|
|
adjustment = rowRegion.bottom - elRegion.bottom;
|
|
}
|
|
record = me.getRecord(row);
|
|
rowIdx = me.store.indexOf(record);
|
|
|
|
if (adjustment) {
|
|
|
|
panel.scrollByDeltaY(adjustment);
|
|
}
|
|
me.fireEvent('rowfocus', record, row, rowIdx);
|
|
}
|
|
},
|
|
|
|
focusCell: function(position) {
|
|
var me = this,
|
|
cell = me.getCellByPosition(position),
|
|
el = me.el,
|
|
adjustmentY = 0,
|
|
adjustmentX = 0,
|
|
elRegion = el.getRegion(),
|
|
panel = me.ownerCt,
|
|
cellRegion,
|
|
record;
|
|
|
|
if (cell) {
|
|
cellRegion = cell.getRegion();
|
|
|
|
if (cellRegion.top < elRegion.top) {
|
|
adjustmentY = cellRegion.top - elRegion.top;
|
|
|
|
} else if (cellRegion.bottom > elRegion.bottom) {
|
|
adjustmentY = cellRegion.bottom - elRegion.bottom;
|
|
}
|
|
|
|
|
|
if (cellRegion.left < elRegion.left) {
|
|
adjustmentX = cellRegion.left - elRegion.left;
|
|
|
|
} else if (cellRegion.right > elRegion.right) {
|
|
adjustmentX = cellRegion.right - elRegion.right;
|
|
}
|
|
|
|
if (adjustmentY) {
|
|
|
|
panel.scrollByDeltaY(adjustmentY);
|
|
}
|
|
if (adjustmentX) {
|
|
panel.scrollByDeltaX(adjustmentX);
|
|
}
|
|
el.focus();
|
|
me.fireEvent('cellfocus', record, cell, position);
|
|
}
|
|
},
|
|
|
|
|
|
scrollByDelta: function(delta, dir) {
|
|
dir = dir || 'scrollTop';
|
|
var elDom = this.el.dom;
|
|
elDom[dir] = (elDom[dir] += delta);
|
|
},
|
|
|
|
onUpdate: function(ds, index) {
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
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,
|
|
headerEl = this.headerCt.el.dom;
|
|
|
|
headerEl.scrollLeft = dom.scrollLeft = state.left;
|
|
dom.scrollTop = state.top;
|
|
}
|
|
},
|
|
|
|
|
|
refresh: function() {
|
|
this.setNewTemplate();
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
processItemEvent: function(record, row, rowIndex, e) {
|
|
var me = this,
|
|
cell = e.getTarget(me.cellSelector, row),
|
|
cellIndex = cell ? cell.cellIndex : -1,
|
|
map = me.statics().EventMap,
|
|
selModel = me.getSelectionModel(),
|
|
type = e.type,
|
|
result;
|
|
|
|
if (type == 'keydown' && !cell && selModel.getCurrentPosition) {
|
|
|
|
cell = me.getCellByPosition(selModel.getCurrentPosition());
|
|
if (cell) {
|
|
cell = cell.dom;
|
|
cellIndex = cell.cellIndex;
|
|
}
|
|
}
|
|
|
|
result = me.fireEvent('uievent', type, me, cell, rowIndex, cellIndex, e);
|
|
|
|
if (result === false || me.callParent(arguments) === false) {
|
|
return false;
|
|
}
|
|
|
|
|
|
if (type == 'mouseover' || type == 'mouseout') {
|
|
return true;
|
|
}
|
|
|
|
return !(
|
|
|
|
(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)
|
|
);
|
|
},
|
|
|
|
processSpecialEvent: function(e) {
|
|
var me = this,
|
|
map = me.statics().EventMap,
|
|
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;
|
|
|
|
|
|
beforeArgs = feature.getFireEventArgs('before' + prefix + type, me, featureTarget, e);
|
|
args = feature.getFireEventArgs(prefix + type, me, featureTarget, e);
|
|
|
|
if (
|
|
|
|
(me.fireEvent.apply(me, beforeArgs) === false) ||
|
|
|
|
(panel.fireEvent.apply(panel, beforeArgs) === false) ||
|
|
|
|
(me.fireEvent.apply(me, args) === false) ||
|
|
|
|
(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,
|
|
|
|
|
|
expandToFit: function(header) {
|
|
if (header) {
|
|
var maxWidth = this.getMaxContentWidth(header);
|
|
delete header.flex;
|
|
header.setWidth(maxWidth);
|
|
}
|
|
},
|
|
|
|
|
|
getMaxContentWidth: function(header) {
|
|
var cellSelector = header.getCellInnerSelector(),
|
|
cells = this.el.query(cellSelector),
|
|
i = 0,
|
|
ln = cells.length,
|
|
maxWidth = header.el.dom.scrollWidth,
|
|
scrollWidth;
|
|
|
|
for (; i < ln; i++) {
|
|
scrollWidth = cells[i].scrollWidth;
|
|
if (scrollWidth > maxWidth) {
|
|
maxWidth = scrollWidth;
|
|
}
|
|
}
|
|
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 m = cell.className.match(this.cellRe);
|
|
if (m && m[1]) {
|
|
return Ext.getCmp(m[1]);
|
|
}
|
|
}
|
|
return false;
|
|
},
|
|
|
|
|
|
walkCells: function(pos, direction, e, preventWrap, verifierFn, scope) {
|
|
var me = this,
|
|
row = pos.row,
|
|
column = pos.column,
|
|
rowCount = me.store.getCount(),
|
|
firstCol = me.getFirstVisibleColumnIndex(),
|
|
lastCol = me.getLastVisibleColumnIndex(),
|
|
newPos = {row: row, column: column},
|
|
activeHeader = me.headerCt.getHeaderAtIndex(column);
|
|
|
|
|
|
if (!activeHeader || activeHeader.hidden) {
|
|
return false;
|
|
}
|
|
|
|
e = e || {};
|
|
direction = direction.toLowerCase();
|
|
switch (direction) {
|
|
case 'right':
|
|
|
|
if (column === lastCol) {
|
|
|
|
if (preventWrap || row === rowCount - 1) {
|
|
return false;
|
|
}
|
|
if (!e.ctrlKey) {
|
|
|
|
newPos.row = row + 1;
|
|
newPos.column = firstCol;
|
|
}
|
|
|
|
} else {
|
|
if (!e.ctrlKey) {
|
|
newPos.column = column + me.getRightGap(activeHeader);
|
|
} else {
|
|
newPos.column = lastCol;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'left':
|
|
|
|
if (column === firstCol) {
|
|
|
|
if (preventWrap || row === 0) {
|
|
return false;
|
|
}
|
|
if (!e.ctrlKey) {
|
|
|
|
newPos.row = row - 1;
|
|
newPos.column = lastCol;
|
|
}
|
|
|
|
} else {
|
|
if (!e.ctrlKey) {
|
|
newPos.column = column + me.getLeftGap(activeHeader);
|
|
} else {
|
|
newPos.column = firstCol;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'up':
|
|
|
|
if (row === 0) {
|
|
return false;
|
|
|
|
} else {
|
|
if (!e.ctrlKey) {
|
|
newPos.row = row - 1;
|
|
} else {
|
|
newPos.row = 0;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case 'down':
|
|
|
|
if (row === rowCount - 1) {
|
|
return false;
|
|
|
|
} else {
|
|
if (!e.ctrlKey) {
|
|
newPos.row = row + 1;
|
|
} else {
|
|
newPos.row = rowCount - 1;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (verifierFn && verifierFn.call(scope || window, newPos) !== true) {
|
|
return false;
|
|
} else {
|
|
return newPos;
|
|
}
|
|
},
|
|
getFirstVisibleColumnIndex: function() {
|
|
var headerCt = this.getHeaderCt(),
|
|
allColumns = headerCt.getGridColumns(),
|
|
visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
|
|
firstHeader = visHeaders[0];
|
|
|
|
return headerCt.getHeaderIndex(firstHeader);
|
|
},
|
|
|
|
getLastVisibleColumnIndex: function() {
|
|
var headerCt = this.getHeaderCt(),
|
|
allColumns = headerCt.getGridColumns(),
|
|
visHeaders = Ext.ComponentQuery.query(':not([hidden])', allColumns),
|
|
lastHeader = visHeaders[visHeaders.length - 1];
|
|
|
|
return headerCt.getHeaderIndex(lastHeader);
|
|
},
|
|
|
|
getHeaderCt: function() {
|
|
return this.headerCt;
|
|
},
|
|
|
|
getPosition: function(record, header) {
|
|
var me = this,
|
|
store = me.store,
|
|
gridCols = me.headerCt.getGridColumns();
|
|
|
|
return {
|
|
row: store.indexOf(record),
|
|
column: Ext.Array.indexOf(gridCols, header)
|
|
};
|
|
},
|
|
|
|
|
|
getRightGap: function(activeHeader) {
|
|
var headerCt = this.getHeaderCt(),
|
|
headers = headerCt.getGridColumns(),
|
|
activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
|
|
i = activeHeaderIdx + 1,
|
|
nextIdx;
|
|
|
|
for (; i <= headers.length; i++) {
|
|
if (!headers[i].hidden) {
|
|
nextIdx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return nextIdx - activeHeaderIdx;
|
|
},
|
|
|
|
beforeDestroy: function() {
|
|
if (this.rendered) {
|
|
this.el.removeAllListeners();
|
|
}
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
getLeftGap: function(activeHeader) {
|
|
var headerCt = this.getHeaderCt(),
|
|
headers = headerCt.getGridColumns(),
|
|
activeHeaderIdx = Ext.Array.indexOf(headers, activeHeader),
|
|
i = activeHeaderIdx - 1,
|
|
prevIdx;
|
|
|
|
for (; i >= 0; i--) {
|
|
if (!headers[i].hidden) {
|
|
prevIdx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return prevIdx - activeHeaderIdx;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.View', {
|
|
extend: 'Ext.view.Table',
|
|
alias: 'widget.gridview',
|
|
|
|
|
|
stripeRows: true,
|
|
|
|
invalidateScrollerOnRefresh: true,
|
|
|
|
|
|
scrollToTop : function(){
|
|
if (this.rendered) {
|
|
var section = this.ownerCt,
|
|
verticalScroller = section.verticalScroller;
|
|
|
|
if (verticalScroller) {
|
|
verticalScroller.scrollToTop();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onAdd: function(ds, records, index) {
|
|
this.callParent(arguments);
|
|
this.doStripeRows(index);
|
|
},
|
|
|
|
|
|
onRemove: function(ds, records, index) {
|
|
this.callParent(arguments);
|
|
this.doStripeRows(index);
|
|
},
|
|
|
|
onUpdate: function(ds, record, operation) {
|
|
var index = ds.indexOf(record);
|
|
this.callParent(arguments);
|
|
this.doStripeRows(index, index);
|
|
},
|
|
|
|
|
|
doStripeRows: function(startRow, endRow) {
|
|
|
|
if (this.stripeRows) {
|
|
var rows = this.getNodes(startRow, endRow),
|
|
rowsLn = rows.length,
|
|
i = 0,
|
|
row;
|
|
|
|
for (; i < rowsLn; i++) {
|
|
row = rows[i];
|
|
|
|
row.className = row.className.replace(this.rowClsRe, ' ');
|
|
startRow++;
|
|
|
|
if (startRow % 2 === 0) {
|
|
row.className += (' ' + this.altRowCls);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
refresh: function(firstPass) {
|
|
this.callParent(arguments);
|
|
this.doStripeRows(0);
|
|
|
|
var g = this.up('gridpanel');
|
|
if (g && this.invalidateScrollerOnRefresh) {
|
|
g.invalidateScroller();
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.Panel', {
|
|
extend: 'Ext.panel.Table',
|
|
requires: ['Ext.grid.View'],
|
|
alias: ['widget.gridpanel', 'widget.grid'],
|
|
alternateClassName: ['Ext.list.ListView', 'Ext.ListView', 'Ext.grid.GridPanel'],
|
|
viewType: 'gridview',
|
|
|
|
lockable: false,
|
|
|
|
|
|
|
|
normalCfgCopy: ['invalidateScrollerOnRefresh', 'verticalScroller', 'verticalScrollDock', 'verticalScrollerType', 'scroll'],
|
|
lockedCfgCopy: ['invalidateScrollerOnRefresh'],
|
|
|
|
|
|
|
|
initComponent: function() {
|
|
var me = this;
|
|
|
|
if (me.columnLines) {
|
|
me.setColumnLines(me.columnLines);
|
|
}
|
|
|
|
me.callParent();
|
|
},
|
|
|
|
setColumnLines: function(show) {
|
|
var me = this,
|
|
method = (show) ? 'addClsWithUI' : 'removeClsWithUI';
|
|
|
|
me[method]('with-col-lines');
|
|
}
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ext.define('Ext.grid.RowEditor', {
|
|
extend: 'Ext.form.Panel',
|
|
requires: [
|
|
'Ext.tip.ToolTip',
|
|
'Ext.util.HashMap',
|
|
'Ext.util.KeyNav'
|
|
],
|
|
|
|
saveBtnText : 'Update',
|
|
cancelBtnText: 'Cancel',
|
|
errorsText: 'Errors',
|
|
dirtyText: 'You need to commit or cancel your changes',
|
|
|
|
lastScrollLeft: 0,
|
|
lastScrollTop: 0,
|
|
|
|
border: false,
|
|
|
|
|
|
|
|
hideMode: 'offsets',
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
form;
|
|
|
|
me.cls = Ext.baseCSSPrefix + 'grid-row-editor';
|
|
|
|
me.layout = {
|
|
type: 'hbox',
|
|
align: 'middle'
|
|
};
|
|
|
|
|
|
|
|
me.columns = Ext.create('Ext.util.HashMap');
|
|
me.columns.getKey = function(columnHeader) {
|
|
var f;
|
|
if (columnHeader.getEditor) {
|
|
f = columnHeader.getEditor();
|
|
if (f) {
|
|
return f.id;
|
|
}
|
|
}
|
|
return columnHeader.id;
|
|
};
|
|
me.mon(me.columns, {
|
|
add: me.onFieldAdd,
|
|
remove: me.onFieldRemove,
|
|
replace: me.onFieldReplace,
|
|
scope: me
|
|
});
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (me.fields) {
|
|
me.setField(me.fields);
|
|
delete me.fields;
|
|
}
|
|
|
|
form = me.getForm();
|
|
form.trackResetOnLoad = true;
|
|
},
|
|
|
|
onFieldChange: function() {
|
|
var me = this,
|
|
form = me.getForm(),
|
|
valid = form.isValid();
|
|
if (me.errorSummary && me.isVisible()) {
|
|
me[valid ? 'hideToolTip' : 'showToolTip']();
|
|
}
|
|
if (me.floatingButtons) {
|
|
me.floatingButtons.child('#update').setDisabled(!valid);
|
|
}
|
|
me.isValid = valid;
|
|
},
|
|
|
|
afterRender: function() {
|
|
var me = this,
|
|
plugin = me.editingPlugin;
|
|
|
|
me.callParent(arguments);
|
|
me.mon(me.renderTo, 'scroll', me.onCtScroll, me, { buffer: 100 });
|
|
|
|
|
|
me.mon(me.el, {
|
|
click: Ext.emptyFn,
|
|
stopPropagation: true
|
|
});
|
|
|
|
me.el.swallowEvent([
|
|
'keypress',
|
|
'keydown'
|
|
]);
|
|
|
|
me.keyNav = Ext.create('Ext.util.KeyNav', me.el, {
|
|
enter: plugin.completeEdit,
|
|
esc: plugin.onEscKey,
|
|
scope: plugin
|
|
});
|
|
|
|
me.mon(plugin.view, {
|
|
beforerefresh: me.onBeforeViewRefresh,
|
|
refresh: me.onViewRefresh,
|
|
scope: me
|
|
});
|
|
},
|
|
|
|
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,
|
|
viewDom = view.el.dom,
|
|
context = me.context,
|
|
idx;
|
|
|
|
viewDom.appendChild(me.el.dom);
|
|
|
|
|
|
if (context && (idx = context.store.indexOf(context.record)) >= 0) {
|
|
context.row = view.getNode(idx);
|
|
me.reposition();
|
|
if (me.tooltip && me.tooltip.isVisible()) {
|
|
me.tooltip.setTarget(context.row);
|
|
}
|
|
} else {
|
|
me.editingPlugin.cancelEdit();
|
|
}
|
|
},
|
|
|
|
onCtScroll: function(e, target) {
|
|
var me = this,
|
|
scrollTop = target.scrollTop,
|
|
scrollLeft = target.scrollLeft;
|
|
|
|
if (scrollTop !== me.lastScrollTop) {
|
|
me.lastScrollTop = scrollTop;
|
|
if ((me.tooltip && me.tooltip.isVisible()) || me.hiddenTip) {
|
|
me.repositionTip();
|
|
}
|
|
}
|
|
if (scrollLeft !== me.lastScrollLeft) {
|
|
me.lastScrollLeft = scrollLeft;
|
|
me.reposition();
|
|
}
|
|
},
|
|
|
|
onColumnAdd: function(column) {
|
|
this.setField(column);
|
|
},
|
|
|
|
onColumnRemove: function(column) {
|
|
this.columns.remove(column);
|
|
},
|
|
|
|
onColumnResize: function(column, width) {
|
|
column.getEditor().setWidth(width - 2);
|
|
if (this.isVisible()) {
|
|
this.reposition();
|
|
}
|
|
},
|
|
|
|
onColumnHide: function(column) {
|
|
column.getEditor().hide();
|
|
if (this.isVisible()) {
|
|
this.reposition();
|
|
}
|
|
},
|
|
|
|
onColumnShow: function(column) {
|
|
var field = column.getEditor();
|
|
field.setWidth(column.getWidth() - 2).show();
|
|
if (this.isVisible()) {
|
|
this.reposition();
|
|
}
|
|
},
|
|
|
|
onColumnMove: function(column, fromIdx, toIdx) {
|
|
var field = column.getEditor();
|
|
if (this.items.indexOf(field) != toIdx) {
|
|
this.move(fromIdx, toIdx);
|
|
}
|
|
},
|
|
|
|
onFieldAdd: function(map, fieldId, column) {
|
|
var me = this,
|
|
colIdx = me.editingPlugin.grid.headerCt.getHeaderIndex(column),
|
|
field = column.getEditor({ xtype: 'displayfield' });
|
|
|
|
me.insert(colIdx, field);
|
|
},
|
|
|
|
onFieldRemove: function(map, fieldId, column) {
|
|
var me = this,
|
|
field = column.getEditor(),
|
|
fieldEl = field.el;
|
|
me.remove(field, false);
|
|
if (fieldEl) {
|
|
fieldEl.remove();
|
|
}
|
|
},
|
|
|
|
onFieldReplace: function(map, fieldId, column, oldColumn) {
|
|
var me = this;
|
|
me.onFieldRemove(map, fieldId, oldColumn);
|
|
},
|
|
|
|
clearFields: function() {
|
|
var me = this,
|
|
map = me.columns;
|
|
map.each(function(fieldId) {
|
|
map.removeAtKey(fieldId);
|
|
});
|
|
},
|
|
|
|
getFloatingButtons: function() {
|
|
var me = this,
|
|
cssPrefix = Ext.baseCSSPrefix,
|
|
btnsCss = cssPrefix + 'grid-row-editor-buttons',
|
|
plugin = me.editingPlugin,
|
|
btns;
|
|
|
|
if (!me.floatingButtons) {
|
|
btns = me.floatingButtons = Ext.create('Ext.Container', {
|
|
renderTpl: [
|
|
'<div class="{baseCls}-ml"></div>',
|
|
'<div class="{baseCls}-mr"></div>',
|
|
'<div class="{baseCls}-bl"></div>',
|
|
'<div class="{baseCls}-br"></div>',
|
|
'<div class="{baseCls}-bc"></div>'
|
|
],
|
|
|
|
renderTo: me.el,
|
|
baseCls: btnsCss,
|
|
layout: {
|
|
type: 'hbox',
|
|
align: 'middle'
|
|
},
|
|
defaults: {
|
|
margins: '0 1 0 1'
|
|
},
|
|
items: [{
|
|
itemId: 'update',
|
|
flex: 1,
|
|
xtype: 'button',
|
|
handler: plugin.completeEdit,
|
|
scope: plugin,
|
|
text: me.saveBtnText,
|
|
disabled: !me.isValid
|
|
}, {
|
|
flex: 1,
|
|
xtype: 'button',
|
|
handler: plugin.cancelEdit,
|
|
scope: plugin,
|
|
text: me.cancelBtnText
|
|
}]
|
|
});
|
|
|
|
|
|
me.mon(btns.el, {
|
|
|
|
|
|
mousedown: Ext.emptyFn,
|
|
click: Ext.emptyFn,
|
|
stopEvent: true
|
|
});
|
|
}
|
|
return me.floatingButtons;
|
|
},
|
|
|
|
reposition: function(animateConfig) {
|
|
var me = this,
|
|
context = me.context,
|
|
row = context && Ext.get(context.row),
|
|
btns = me.getFloatingButtons(),
|
|
btnEl = btns.el,
|
|
grid = me.editingPlugin.grid,
|
|
viewEl = grid.view.el,
|
|
scroller = grid.verticalScroller,
|
|
|
|
|
|
|
|
mainBodyWidth = grid.headerCt.getFullWidth(),
|
|
scrollerWidth = grid.getWidth(),
|
|
|
|
|
|
|
|
width = Math.min(mainBodyWidth, scrollerWidth),
|
|
scrollLeft = grid.view.el.dom.scrollLeft,
|
|
btnWidth = btns.getWidth(),
|
|
left = (width - btnWidth) / 2 + scrollLeft,
|
|
y, rowH, newHeight,
|
|
|
|
invalidateScroller = function() {
|
|
if (scroller) {
|
|
scroller.invalidate();
|
|
btnEl.scrollIntoView(viewEl, false);
|
|
}
|
|
if (animateConfig && animateConfig.callback) {
|
|
animateConfig.callback.call(animateConfig.scope || me);
|
|
}
|
|
};
|
|
|
|
|
|
if (row && Ext.isElement(row.dom)) {
|
|
|
|
|
|
row.scrollIntoView(viewEl, false);
|
|
|
|
|
|
|
|
|
|
y = row.getXY()[1] - 5;
|
|
rowH = row.getHeight();
|
|
newHeight = rowH + 10;
|
|
|
|
|
|
|
|
|
|
|
|
if (Ext.isIE) {
|
|
newHeight += 2;
|
|
}
|
|
|
|
|
|
if (me.getHeight() != newHeight) {
|
|
me.setHeight(newHeight);
|
|
me.el.setLeft(0);
|
|
}
|
|
|
|
if (animateConfig) {
|
|
var animObj = {
|
|
to: {
|
|
y: y
|
|
},
|
|
duration: animateConfig.duration || 125,
|
|
listeners: {
|
|
afteranimate: function() {
|
|
invalidateScroller();
|
|
y = row.getXY()[1] - 5;
|
|
me.el.setY(y);
|
|
}
|
|
}
|
|
};
|
|
me.animate(animObj);
|
|
} else {
|
|
me.el.setY(y);
|
|
invalidateScroller();
|
|
}
|
|
}
|
|
if (me.getWidth() != mainBodyWidth) {
|
|
me.setWidth(mainBodyWidth);
|
|
}
|
|
btnEl.setLeft(left);
|
|
},
|
|
|
|
getEditor: function(fieldInfo) {
|
|
var me = this;
|
|
|
|
if (Ext.isNumber(fieldInfo)) {
|
|
|
|
|
|
|
|
return me.query('>[isFormField]')[fieldInfo];
|
|
} else if (fieldInfo instanceof Ext.grid.column.Column) {
|
|
return fieldInfo.getEditor();
|
|
}
|
|
},
|
|
|
|
removeField: function(field) {
|
|
var me = this;
|
|
|
|
|
|
field = me.getEditor(field);
|
|
me.mun(field, 'validitychange', me.onValidityChange, me);
|
|
|
|
|
|
|
|
me.columns.removeKey(field.id);
|
|
},
|
|
|
|
setField: function(column) {
|
|
var me = this,
|
|
field;
|
|
|
|
if (Ext.isArray(column)) {
|
|
Ext.Array.forEach(column, me.setField, me);
|
|
return;
|
|
}
|
|
|
|
|
|
field = column.getEditor(null, {
|
|
xtype: 'displayfield',
|
|
|
|
|
|
getModelData: function() {
|
|
return null;
|
|
}
|
|
});
|
|
field.margins = '0 0 0 2';
|
|
field.setWidth(column.getDesiredWidth() - 2);
|
|
me.mon(field, 'change', me.onFieldChange, me);
|
|
|
|
|
|
|
|
me.columns.add(field.id, column);
|
|
if (column.hidden) {
|
|
me.onColumnHide(column);
|
|
}
|
|
if (me.isVisible() && me.context) {
|
|
me.renderColumnData(field, me.context.record);
|
|
}
|
|
},
|
|
|
|
loadRecord: function(record) {
|
|
var me = this,
|
|
form = me.getForm();
|
|
form.loadRecord(record);
|
|
if (form.isValid()) {
|
|
me.hideToolTip();
|
|
} else {
|
|
me.showToolTip();
|
|
}
|
|
|
|
|
|
Ext.Array.forEach(me.query('>displayfield'), function(field) {
|
|
me.renderColumnData(field, record);
|
|
}, me);
|
|
},
|
|
|
|
renderColumnData: function(field, record) {
|
|
var me = this,
|
|
grid = me.editingPlugin.grid,
|
|
headerCt = grid.headerCt,
|
|
view = grid.view,
|
|
store = view.store,
|
|
column = me.columns.get(field.id),
|
|
value = record.get(column.dataIndex);
|
|
|
|
|
|
if (column.renderer) {
|
|
var metaData = { tdCls: '', style: '' },
|
|
rowIdx = store.indexOf(record),
|
|
colIdx = headerCt.getHeaderIndex(column);
|
|
|
|
value = column.renderer.call(
|
|
column.scope || headerCt.ownerCt,
|
|
value,
|
|
metaData,
|
|
record,
|
|
rowIdx,
|
|
colIdx,
|
|
store,
|
|
view
|
|
);
|
|
}
|
|
|
|
field.setRawValue(value);
|
|
field.resetOriginalValue();
|
|
},
|
|
|
|
beforeEdit: function() {
|
|
var me = this;
|
|
|
|
if (me.isVisible() && !me.autoCancel && me.isDirty()) {
|
|
me.showToolTip();
|
|
return false;
|
|
}
|
|
},
|
|
|
|
|
|
startEdit: function(record, columnHeader) {
|
|
var me = this,
|
|
grid = me.editingPlugin.grid,
|
|
view = grid.getView(),
|
|
store = grid.store,
|
|
context = me.context = Ext.apply(me.editingPlugin.context, {
|
|
view: grid.getView(),
|
|
store: store
|
|
});
|
|
|
|
|
|
context.grid.getSelectionModel().select(record);
|
|
|
|
|
|
me.loadRecord(record);
|
|
|
|
if (!me.isVisible()) {
|
|
me.show();
|
|
me.focusContextCell();
|
|
} else {
|
|
me.reposition({
|
|
callback: this.focusContextCell
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
focusContextCell: function() {
|
|
var field = this.getEditor(this.context.colIdx);
|
|
if (field && field.focus) {
|
|
field.focus();
|
|
}
|
|
},
|
|
|
|
cancelEdit: function() {
|
|
var me = this,
|
|
form = me.getForm();
|
|
|
|
me.hide();
|
|
form.clearInvalid();
|
|
form.reset();
|
|
},
|
|
|
|
completeEdit: function() {
|
|
var me = this,
|
|
form = me.getForm();
|
|
|
|
if (!form.isValid()) {
|
|
return;
|
|
}
|
|
|
|
form.updateRecord(me.context.record);
|
|
me.hide();
|
|
return true;
|
|
},
|
|
|
|
onShow: function() {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
me.reposition();
|
|
},
|
|
|
|
onHide: function() {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
me.hideToolTip();
|
|
me.invalidateScroller();
|
|
if (me.context) {
|
|
me.context.view.focus();
|
|
me.context = null;
|
|
}
|
|
},
|
|
|
|
isDirty: function() {
|
|
var me = this,
|
|
form = me.getForm();
|
|
return form.isDirty();
|
|
},
|
|
|
|
getToolTip: function() {
|
|
var me = this,
|
|
tip;
|
|
|
|
if (!me.tooltip) {
|
|
tip = me.tooltip = Ext.createWidget('tooltip', {
|
|
cls: Ext.baseCSSPrefix + 'grid-row-editor-errors',
|
|
title: me.errorsText,
|
|
autoHide: false,
|
|
closable: true,
|
|
closeAction: 'disable',
|
|
anchor: 'left'
|
|
});
|
|
}
|
|
return me.tooltip;
|
|
},
|
|
|
|
hideToolTip: function() {
|
|
var me = this,
|
|
tip = me.getToolTip();
|
|
if (tip.rendered) {
|
|
tip.disable();
|
|
}
|
|
me.hiddenTip = false;
|
|
},
|
|
|
|
showToolTip: function() {
|
|
var me = this,
|
|
tip = me.getToolTip(),
|
|
context = me.context,
|
|
row = Ext.get(context.row),
|
|
viewEl = context.grid.view.el;
|
|
|
|
tip.setTarget(row);
|
|
tip.showAt([-10000, -10000]);
|
|
tip.body.update(me.getErrors());
|
|
tip.mouseOffset = [viewEl.getWidth() - row.getWidth() + me.lastScrollLeft + 15, 0];
|
|
me.repositionTip();
|
|
tip.doLayout();
|
|
tip.enable();
|
|
},
|
|
|
|
repositionTip: function() {
|
|
var me = this,
|
|
tip = me.getToolTip(),
|
|
context = me.context,
|
|
row = Ext.get(context.row),
|
|
viewEl = context.grid.view.el,
|
|
viewHeight = viewEl.getHeight(),
|
|
viewTop = me.lastScrollTop,
|
|
viewBottom = viewTop + viewHeight,
|
|
rowHeight = row.getHeight(),
|
|
rowTop = row.dom.offsetTop,
|
|
rowBottom = rowTop + rowHeight;
|
|
|
|
if (rowBottom > viewTop && rowTop < viewBottom) {
|
|
tip.show();
|
|
me.hiddenTip = false;
|
|
} else {
|
|
tip.hide();
|
|
me.hiddenTip = true;
|
|
}
|
|
},
|
|
|
|
getErrors: function() {
|
|
var me = this,
|
|
dirtyText = !me.autoCancel && me.isDirty() ? me.dirtyText + '<br />' : '',
|
|
errors = [];
|
|
|
|
Ext.Array.forEach(me.query('>[isFormField]'), function(field) {
|
|
errors = errors.concat(
|
|
Ext.Array.map(field.getErrors(), function(e) {
|
|
return '<li>' + e + '</li>';
|
|
})
|
|
);
|
|
}, me);
|
|
|
|
return dirtyText + '<ul>' + errors.join('') + '</ul>';
|
|
},
|
|
|
|
invalidateScroller: function() {
|
|
var me = this,
|
|
context = me.context,
|
|
scroller = context.grid.verticalScroller;
|
|
|
|
if (scroller) {
|
|
scroller.invalidate();
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.header.Container', {
|
|
extend: 'Ext.container.Container',
|
|
uses: [
|
|
'Ext.grid.ColumnLayout',
|
|
'Ext.grid.column.Column',
|
|
'Ext.menu.Menu',
|
|
'Ext.menu.CheckItem',
|
|
'Ext.menu.Separator',
|
|
'Ext.grid.plugin.HeaderResizer',
|
|
'Ext.grid.plugin.HeaderReorderer'
|
|
],
|
|
border: true,
|
|
|
|
alias: 'widget.headercontainer',
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'grid-header-ct',
|
|
dock: 'top',
|
|
|
|
|
|
weight: 100,
|
|
defaultType: 'gridcolumn',
|
|
|
|
defaultWidth: 100,
|
|
|
|
|
|
sortAscText: 'Sort Ascending',
|
|
sortDescText: 'Sort Descending',
|
|
sortClearText: 'Clear Sort',
|
|
columnsText: 'Columns',
|
|
|
|
lastHeaderCls: Ext.baseCSSPrefix + 'column-header-last',
|
|
firstHeaderCls: Ext.baseCSSPrefix + 'column-header-first',
|
|
headerOpenCls: Ext.baseCSSPrefix + 'column-header-open',
|
|
|
|
|
|
triStateSort: false,
|
|
|
|
ddLock: false,
|
|
|
|
dragging: false,
|
|
|
|
|
|
|
|
|
|
sortable: true,
|
|
|
|
initComponent: function() {
|
|
var me = this;
|
|
|
|
me.headerCounter = 0;
|
|
me.plugins = me.plugins || [];
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!me.isHeader) {
|
|
me.resizer = Ext.create('Ext.grid.plugin.HeaderResizer');
|
|
me.reorderer = Ext.create('Ext.grid.plugin.HeaderReorderer');
|
|
if (!me.enableColumnResize) {
|
|
me.resizer.disable();
|
|
}
|
|
if (!me.enableColumnMove) {
|
|
me.reorderer.disable();
|
|
}
|
|
me.plugins.push(me.reorderer, me.resizer);
|
|
}
|
|
|
|
|
|
if (me.isHeader && !me.items) {
|
|
me.layout = 'auto';
|
|
}
|
|
|
|
else {
|
|
me.layout = {
|
|
type: 'gridcolumn',
|
|
availableSpaceOffset: me.availableSpaceOffset,
|
|
align: 'stretchmax',
|
|
resetStretch: true
|
|
};
|
|
}
|
|
me.defaults = me.defaults || {};
|
|
Ext.applyIf(me.defaults, {
|
|
width: me.defaultWidth,
|
|
triStateSort: me.triStateSort,
|
|
sortable: me.sortable
|
|
});
|
|
me.callParent();
|
|
me.addEvents(
|
|
|
|
'columnresize',
|
|
|
|
|
|
'headerclick',
|
|
|
|
|
|
'headertriggerclick',
|
|
|
|
|
|
'columnmove',
|
|
|
|
'columnhide',
|
|
|
|
'columnshow',
|
|
|
|
'sortchange',
|
|
|
|
'menucreate'
|
|
);
|
|
},
|
|
|
|
onDestroy: function() {
|
|
Ext.destroy(this.resizer, this.reorderer);
|
|
this.callParent();
|
|
},
|
|
|
|
applyDefaults: function(config){
|
|
|
|
if (config && !config.isComponent && config.xtype == 'rownumberer') {
|
|
return config;
|
|
}
|
|
return this.callParent([config]);
|
|
},
|
|
|
|
applyColumnsState: function(columns) {
|
|
if (!columns || !columns.length) {
|
|
return;
|
|
}
|
|
|
|
var me = this,
|
|
i = 0,
|
|
index,
|
|
col;
|
|
|
|
Ext.each(columns, function (columnState) {
|
|
col = me.down('gridcolumn[headerId=' + columnState.id + ']');
|
|
if (col) {
|
|
index = me.items.indexOf(col);
|
|
if (i !== index) {
|
|
me.moveHeader(index, i);
|
|
}
|
|
|
|
if (col.applyColumnState) {
|
|
col.applyColumnState(columnState);
|
|
}
|
|
++i;
|
|
}
|
|
});
|
|
},
|
|
|
|
getColumnsState: function () {
|
|
var me = this,
|
|
columns = [],
|
|
state;
|
|
|
|
me.items.each(function (col) {
|
|
state = col.getColumnState && col.getColumnState();
|
|
if (state) {
|
|
columns.push(state);
|
|
}
|
|
});
|
|
|
|
return columns;
|
|
},
|
|
|
|
|
|
|
|
|
|
onAdd: function(c) {
|
|
var me = this;
|
|
if (!c.headerId) {
|
|
c.headerId = c.initialConfig.id || ('h' + (++me.headerCounter));
|
|
}
|
|
me.callParent(arguments);
|
|
me.purgeCache();
|
|
},
|
|
|
|
|
|
|
|
|
|
onRemove: function(c) {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
me.purgeCache();
|
|
},
|
|
|
|
afterRender: function() {
|
|
this.callParent();
|
|
var store = this.up('[store]').store,
|
|
sorters = store.sorters,
|
|
first = sorters.first(),
|
|
hd;
|
|
|
|
if (first) {
|
|
hd = this.down('gridcolumn[dataIndex=' + first.property +']');
|
|
if (hd) {
|
|
hd.setSortState(first.direction, false, true);
|
|
}
|
|
}
|
|
},
|
|
|
|
afterLayout: function() {
|
|
if (!this.isHeader) {
|
|
var me = this,
|
|
topHeaders = me.query('>gridcolumn:not([hidden])'),
|
|
viewEl,
|
|
firstHeaderEl,
|
|
lastHeaderEl;
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (topHeaders.length) {
|
|
firstHeaderEl = topHeaders[0].el;
|
|
if (firstHeaderEl !== me.pastFirstHeaderEl) {
|
|
if (me.pastFirstHeaderEl) {
|
|
me.pastFirstHeaderEl.removeCls(me.firstHeaderCls);
|
|
}
|
|
firstHeaderEl.addCls(me.firstHeaderCls);
|
|
me.pastFirstHeaderEl = firstHeaderEl;
|
|
}
|
|
|
|
lastHeaderEl = topHeaders[topHeaders.length - 1].el;
|
|
if (lastHeaderEl !== me.pastLastHeaderEl) {
|
|
if (me.pastLastHeaderEl) {
|
|
me.pastLastHeaderEl.removeCls(me.lastHeaderCls);
|
|
}
|
|
lastHeaderEl.addCls(me.lastHeaderCls);
|
|
me.pastLastHeaderEl = lastHeaderEl;
|
|
}
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
onHeaderShow: function(header, preventLayout) {
|
|
|
|
var me = this,
|
|
gridSection = me.ownerCt,
|
|
menu = me.getMenu(),
|
|
topItems, topItemsVisible,
|
|
colCheckItem,
|
|
itemToEnable,
|
|
len, i;
|
|
|
|
if (menu) {
|
|
|
|
colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
|
|
if (colCheckItem) {
|
|
colCheckItem.setChecked(true, true);
|
|
}
|
|
|
|
|
|
topItems = menu.query('#columnItem>menucheckitem[checked]');
|
|
topItemsVisible = topItems.length;
|
|
if ((me.getVisibleGridColumns().length > 1) && me.disabledMenuItems && me.disabledMenuItems.length) {
|
|
if (topItemsVisible == 1) {
|
|
Ext.Array.remove(me.disabledMenuItems, topItems[0]);
|
|
}
|
|
for (i = 0, len = me.disabledMenuItems.length; i < len; i++) {
|
|
itemToEnable = me.disabledMenuItems[i];
|
|
if (!itemToEnable.isDestroyed) {
|
|
itemToEnable[itemToEnable.menu ? 'enableCheckChange' : 'enable']();
|
|
}
|
|
}
|
|
if (topItemsVisible == 1) {
|
|
me.disabledMenuItems = topItems;
|
|
} else {
|
|
me.disabledMenuItems = [];
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (!header.isGroupHeader) {
|
|
if (me.view) {
|
|
me.view.onHeaderShow(me, header, true);
|
|
}
|
|
if (gridSection) {
|
|
gridSection.onHeaderShow(me, header);
|
|
}
|
|
}
|
|
me.fireEvent('columnshow', me, header);
|
|
|
|
|
|
if (preventLayout !== true) {
|
|
me.doLayout();
|
|
}
|
|
},
|
|
|
|
doComponentLayout: function(){
|
|
var me = this;
|
|
if (me.view && me.view.saveScrollState) {
|
|
me.view.saveScrollState();
|
|
}
|
|
me.callParent(arguments);
|
|
if (me.view && me.view.restoreScrollState) {
|
|
me.view.restoreScrollState();
|
|
}
|
|
},
|
|
|
|
onHeaderHide: function(header, suppressLayout) {
|
|
|
|
var me = this,
|
|
gridSection = me.ownerCt,
|
|
menu = me.getMenu(),
|
|
colCheckItem;
|
|
|
|
if (menu) {
|
|
|
|
|
|
colCheckItem = menu.down('menucheckitem[headerId=' + header.id + ']');
|
|
if (colCheckItem) {
|
|
colCheckItem.setChecked(false, true);
|
|
}
|
|
me.setDisabledItems();
|
|
}
|
|
|
|
|
|
if (!header.isGroupHeader) {
|
|
if (me.view) {
|
|
me.view.onHeaderHide(me, header, true);
|
|
}
|
|
if (gridSection) {
|
|
gridSection.onHeaderHide(me, header);
|
|
}
|
|
|
|
|
|
if (!suppressLayout) {
|
|
me.doLayout();
|
|
}
|
|
}
|
|
me.fireEvent('columnhide', me, header);
|
|
},
|
|
|
|
setDisabledItems: function(){
|
|
var me = this,
|
|
menu = me.getMenu(),
|
|
i = 0,
|
|
len,
|
|
itemsToDisable,
|
|
itemToDisable;
|
|
|
|
|
|
itemsToDisable = menu.query('#columnItem>menucheckitem[checked]');
|
|
if ((itemsToDisable.length === 1)) {
|
|
if (!me.disabledMenuItems) {
|
|
me.disabledMenuItems = [];
|
|
}
|
|
|
|
|
|
if ((me.getVisibleGridColumns().length === 1) && itemsToDisable[0].menu) {
|
|
itemsToDisable = itemsToDisable.concat(itemsToDisable[0].menu.query('menucheckitem[checked]'));
|
|
}
|
|
|
|
len = itemsToDisable.length;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
itemToDisable = itemsToDisable[i];
|
|
if (!Ext.Array.contains(me.disabledMenuItems, itemToDisable)) {
|
|
|
|
|
|
|
|
itemToDisable.disabled = false;
|
|
itemToDisable[itemToDisable.menu ? 'disableCheckChange' : 'disable']();
|
|
me.disabledMenuItems.push(itemToDisable);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
tempLock: function() {
|
|
this.ddLock = true;
|
|
Ext.Function.defer(function() {
|
|
this.ddLock = false;
|
|
}, 200, this);
|
|
},
|
|
|
|
onHeaderResize: function(header, w, suppressFocus) {
|
|
this.tempLock();
|
|
if (this.view && this.view.rendered) {
|
|
this.view.onHeaderResize(header, w, suppressFocus);
|
|
}
|
|
},
|
|
|
|
onHeaderClick: function(header, e, t) {
|
|
this.fireEvent("headerclick", this, header, e, t);
|
|
},
|
|
|
|
onHeaderTriggerClick: function(header, e, t) {
|
|
|
|
if (this.fireEvent("headertriggerclick", this, header, e, t) !== false) {
|
|
this.showMenuBy(t, header);
|
|
}
|
|
},
|
|
|
|
showMenuBy: function(t, header) {
|
|
var menu = this.getMenu(),
|
|
ascItem = menu.down('#ascItem'),
|
|
descItem = menu.down('#descItem'),
|
|
sortableMth;
|
|
|
|
menu.activeHeader = menu.ownerCt = header;
|
|
menu.setFloatParent(header);
|
|
|
|
header.titleContainer.addCls(this.headerOpenCls);
|
|
|
|
|
|
sortableMth = header.sortable ? 'enable' : 'disable';
|
|
if (ascItem) {
|
|
ascItem[sortableMth]();
|
|
}
|
|
if (descItem) {
|
|
descItem[sortableMth]();
|
|
}
|
|
menu.showBy(t);
|
|
},
|
|
|
|
|
|
onMenuDeactivate: function() {
|
|
var menu = this.getMenu();
|
|
|
|
menu.activeHeader.titleContainer.removeCls(this.headerOpenCls);
|
|
},
|
|
|
|
moveHeader: function(fromIdx, toIdx) {
|
|
|
|
|
|
this.tempLock();
|
|
this.onHeaderMoved(this.move(fromIdx, toIdx), fromIdx, toIdx);
|
|
},
|
|
|
|
purgeCache: function() {
|
|
var me = this;
|
|
|
|
delete me.gridDataColumns;
|
|
delete me.hideableColumns;
|
|
|
|
|
|
if (me.menu) {
|
|
me.menu.destroy();
|
|
delete me.menu;
|
|
}
|
|
},
|
|
|
|
onHeaderMoved: function(header, fromIdx, toIdx) {
|
|
var me = this,
|
|
gridSection = me.ownerCt;
|
|
|
|
if (gridSection && gridSection.onHeaderMove) {
|
|
gridSection.onHeaderMove(me, header, fromIdx, toIdx);
|
|
}
|
|
me.fireEvent("columnmove", me, header, fromIdx, toIdx);
|
|
},
|
|
|
|
|
|
getMenu: function() {
|
|
var me = this;
|
|
|
|
if (!me.menu) {
|
|
me.menu = Ext.create('Ext.menu.Menu', {
|
|
hideOnParentHide: false,
|
|
items: me.getMenuItems(),
|
|
listeners: {
|
|
deactivate: me.onMenuDeactivate,
|
|
scope: me
|
|
}
|
|
});
|
|
me.setDisabledItems();
|
|
me.fireEvent('menucreate', me, me.menu);
|
|
}
|
|
return me.menu;
|
|
},
|
|
|
|
|
|
getMenuItems: function() {
|
|
var me = this,
|
|
menuItems = [],
|
|
hideableColumns = me.enableColumnHide ? me.getColumnMenu(me) : null;
|
|
|
|
if (me.sortable) {
|
|
menuItems = [{
|
|
itemId: 'ascItem',
|
|
text: me.sortAscText,
|
|
cls: Ext.baseCSSPrefix + 'hmenu-sort-asc',
|
|
handler: me.onSortAscClick,
|
|
scope: me
|
|
},{
|
|
itemId: 'descItem',
|
|
text: me.sortDescText,
|
|
cls: Ext.baseCSSPrefix + 'hmenu-sort-desc',
|
|
handler: me.onSortDescClick,
|
|
scope: me
|
|
}];
|
|
}
|
|
if (hideableColumns && hideableColumns.length) {
|
|
menuItems.push('-', {
|
|
itemId: 'columnItem',
|
|
text: me.columnsText,
|
|
cls: Ext.baseCSSPrefix + 'cols-icon',
|
|
menu: hideableColumns
|
|
});
|
|
}
|
|
return menuItems;
|
|
},
|
|
|
|
|
|
onSortAscClick: function() {
|
|
var menu = this.getMenu(),
|
|
activeHeader = menu.activeHeader;
|
|
|
|
activeHeader.setSortState('ASC');
|
|
},
|
|
|
|
|
|
onSortDescClick: function() {
|
|
var menu = this.getMenu(),
|
|
activeHeader = menu.activeHeader;
|
|
|
|
activeHeader.setSortState('DESC');
|
|
},
|
|
|
|
|
|
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 = Ext.create('Ext.menu.CheckItem', {
|
|
text: item.text,
|
|
checked: !item.hidden,
|
|
hideOnClick: false,
|
|
headerId: item.id,
|
|
menu: item.isGroupHeader ? this.getColumnMenu(item) : undefined,
|
|
checkHandler: this.onColumnCheckChange,
|
|
scope: this
|
|
});
|
|
if (itemsLn === 1) {
|
|
menuItem.disabled = true;
|
|
}
|
|
menuItems.push(menuItem);
|
|
|
|
|
|
|
|
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']();
|
|
},
|
|
|
|
|
|
getColumnsForTpl: function(flushCache) {
|
|
var cols = [],
|
|
headers = this.getGridColumns(flushCache),
|
|
headersLn = headers.length,
|
|
i = 0,
|
|
header,
|
|
width;
|
|
|
|
for (; i < headersLn; i++) {
|
|
header = headers[i];
|
|
|
|
if (header.hidden || header.up('headercontainer[hidden=true]')) {
|
|
width = 0;
|
|
} else {
|
|
width = header.getDesiredWidth();
|
|
|
|
|
|
|
|
if ((i === 0) && (Ext.isIE6 || Ext.isIE7)) {
|
|
width += 1;
|
|
}
|
|
}
|
|
cols.push({
|
|
dataIndex: header.dataIndex,
|
|
align: header.align,
|
|
width: width,
|
|
id: header.id,
|
|
cls: header.tdCls,
|
|
columnId: header.getItemId()
|
|
});
|
|
}
|
|
return cols;
|
|
},
|
|
|
|
|
|
getColumnCount: function() {
|
|
return this.getGridColumns().length;
|
|
},
|
|
|
|
|
|
getFullWidth: function(flushCache) {
|
|
var fullWidth = 0,
|
|
headers = this.getVisibleGridColumns(flushCache),
|
|
headersLn = headers.length,
|
|
i = 0;
|
|
|
|
for (; i < headersLn; i++) {
|
|
if (!isNaN(headers[i].width)) {
|
|
|
|
if (headers[i].getDesiredWidth) {
|
|
fullWidth += headers[i].getDesiredWidth();
|
|
|
|
} else {
|
|
fullWidth += headers[i].getWidth();
|
|
}
|
|
}
|
|
}
|
|
return fullWidth;
|
|
},
|
|
|
|
|
|
clearOtherSortStates: function(activeHeader) {
|
|
var headers = this.getGridColumns(),
|
|
headersLn = headers.length,
|
|
i = 0,
|
|
oldSortState;
|
|
|
|
for (; i < headersLn; i++) {
|
|
if (headers[i] !== activeHeader) {
|
|
oldSortState = headers[i].sortState;
|
|
|
|
headers[i].setSortState(null, true);
|
|
|
|
|
|
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getVisibleGridColumns: function(refreshCache) {
|
|
return Ext.ComponentQuery.query(':not([hidden])', this.getGridColumns(refreshCache));
|
|
},
|
|
|
|
|
|
getGridColumns: function(refreshCache) {
|
|
var me = this,
|
|
result = refreshCache ? null : me.gridDataColumns;
|
|
|
|
|
|
if (!result) {
|
|
me.gridDataColumns = result = [];
|
|
me.cascade(function(c) {
|
|
if ((c !== me) && !c.isGroupHeader) {
|
|
result.push(c);
|
|
}
|
|
});
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
|
|
getHideableColumns: function(refreshCache) {
|
|
var me = this,
|
|
result = refreshCache ? null : me.hideableColumns;
|
|
|
|
if (!result) {
|
|
result = me.hideableColumns = me.query('[hideable]');
|
|
}
|
|
return result;
|
|
},
|
|
|
|
|
|
getHeaderIndex: function(header) {
|
|
var columns = this.getGridColumns();
|
|
return Ext.Array.indexOf(columns, header);
|
|
},
|
|
|
|
|
|
getHeaderAtIndex: function(index) {
|
|
var columns = this.getGridColumns();
|
|
return columns[index];
|
|
},
|
|
|
|
|
|
prepareData: function(data, rowIdx, record, view, panel) {
|
|
var obj = {},
|
|
headers = this.gridDataColumns || this.getGridColumns(),
|
|
headersLn = headers.length,
|
|
colIdx = 0,
|
|
header,
|
|
headerId,
|
|
renderer,
|
|
value,
|
|
metaData,
|
|
store = panel.store;
|
|
|
|
for (; colIdx < headersLn; colIdx++) {
|
|
metaData = {
|
|
tdCls: '',
|
|
style: ''
|
|
};
|
|
header = headers[colIdx];
|
|
headerId = header.id;
|
|
renderer = header.renderer;
|
|
value = data[header.dataIndex];
|
|
|
|
|
|
|
|
if (typeof renderer === "string") {
|
|
header.renderer = renderer = Ext.util.Format[renderer];
|
|
}
|
|
|
|
if (typeof renderer === "function") {
|
|
value = renderer.call(
|
|
header.scope || this.ownerCt,
|
|
value,
|
|
|
|
|
|
metaData,
|
|
record,
|
|
rowIdx,
|
|
colIdx,
|
|
store,
|
|
view
|
|
);
|
|
}
|
|
|
|
|
|
obj[headerId+'-modified'] = record.isModified(header.dataIndex) ? Ext.baseCSSPrefix + 'grid-dirty-cell' : '';
|
|
obj[headerId+'-tdCls'] = metaData.tdCls;
|
|
obj[headerId+'-tdAttr'] = metaData.tdAttr;
|
|
obj[headerId+'-style'] = metaData.style;
|
|
if (value === undefined || value === null || value === '') {
|
|
value = ' ';
|
|
}
|
|
obj[headerId] = value;
|
|
}
|
|
return obj;
|
|
},
|
|
|
|
expandToFit: function(header) {
|
|
if (this.view) {
|
|
this.view.expandToFit(header);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.column.Column', {
|
|
extend: 'Ext.grid.header.Container',
|
|
alias: 'widget.gridcolumn',
|
|
requires: ['Ext.util.KeyNav'],
|
|
alternateClassName: 'Ext.grid.Column',
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'column-header ' + Ext.baseCSSPrefix + 'unselectable',
|
|
|
|
|
|
hoverCls: Ext.baseCSSPrefix + 'column-header-over',
|
|
|
|
handleWidth: 5,
|
|
|
|
sortState: null,
|
|
|
|
possibleSortStates: ['ASC', 'DESC'],
|
|
|
|
renderTpl:
|
|
'<div id="{id}-titleContainer" class="' + Ext.baseCSSPrefix + 'column-header-inner">' +
|
|
'<span id="{id}-textEl" class="' + Ext.baseCSSPrefix + 'column-header-text">' +
|
|
'{text}' +
|
|
'</span>' +
|
|
'<tpl if="!values.menuDisabled">'+
|
|
'<div id="{id}-triggerEl" class="' + Ext.baseCSSPrefix + 'column-header-trigger"></div>'+
|
|
'</tpl>' +
|
|
'</div>',
|
|
|
|
|
|
|
|
|
|
dataIndex: null,
|
|
|
|
|
|
text: ' ',
|
|
|
|
|
|
sortable: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hideable: true,
|
|
|
|
|
|
menuDisabled: false,
|
|
|
|
|
|
renderer: false,
|
|
|
|
|
|
align: 'left',
|
|
|
|
|
|
draggable: true,
|
|
|
|
|
|
|
|
initDraggable: Ext.emptyFn,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
isHeader: true,
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
i,
|
|
len,
|
|
item;
|
|
|
|
if (Ext.isDefined(me.header)) {
|
|
me.text = me.header;
|
|
delete me.header;
|
|
}
|
|
|
|
|
|
|
|
|
|
if (me.flex) {
|
|
me.minWidth = me.minWidth || Ext.grid.plugin.HeaderResizer.prototype.minColWidth;
|
|
}
|
|
|
|
|
|
else {
|
|
me.minWidth = me.width;
|
|
}
|
|
|
|
if (!me.triStateSort) {
|
|
me.possibleSortStates.length = 2;
|
|
}
|
|
|
|
|
|
if (Ext.isDefined(me.columns)) {
|
|
me.isGroupHeader = true;
|
|
|
|
|
|
|
|
me.items = me.columns;
|
|
delete me.columns;
|
|
delete me.flex;
|
|
me.width = 0;
|
|
|
|
|
|
for (i = 0, len = me.items.length; i < len; i++) {
|
|
item = me.items[i];
|
|
if (!item.hidden) {
|
|
me.width += item.width || Ext.grid.header.Container.prototype.defaultWidth;
|
|
}
|
|
}
|
|
me.minWidth = me.width;
|
|
|
|
me.cls = (me.cls||'') + ' ' + Ext.baseCSSPrefix + 'group-header';
|
|
me.sortable = false;
|
|
me.resizable = false;
|
|
me.align = 'center';
|
|
}
|
|
|
|
me.addChildEls('titleContainer', 'triggerEl', 'textEl');
|
|
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
onAdd: function(childHeader) {
|
|
childHeader.isSubHeader = true;
|
|
childHeader.addCls(Ext.baseCSSPrefix + 'group-sub-header');
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
onRemove: function(childHeader) {
|
|
childHeader.isSubHeader = false;
|
|
childHeader.removeCls(Ext.baseCSSPrefix + 'group-sub-header');
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
initRenderData: function() {
|
|
var me = this;
|
|
|
|
Ext.applyIf(me.renderData, {
|
|
text: me.text,
|
|
menuDisabled: me.menuDisabled
|
|
});
|
|
return me.callParent(arguments);
|
|
},
|
|
|
|
applyColumnState: function (state) {
|
|
var me = this,
|
|
defined = Ext.isDefined;
|
|
|
|
|
|
me.applyColumnsState(state.columns);
|
|
|
|
|
|
|
|
if (defined(state.hidden)) {
|
|
me.hidden = state.hidden;
|
|
}
|
|
if (defined(state.locked)) {
|
|
me.locked = state.locked;
|
|
}
|
|
if (defined(state.sortable)) {
|
|
me.sortable = state.sortable;
|
|
}
|
|
if (defined(state.width)) {
|
|
delete me.flex;
|
|
me.width = state.width;
|
|
} else if (defined(state.flex)) {
|
|
delete me.width;
|
|
me.flex = state.flex;
|
|
}
|
|
},
|
|
|
|
getColumnState: function () {
|
|
var me = this,
|
|
columns = [],
|
|
state = {
|
|
id: me.headerId
|
|
};
|
|
|
|
me.savePropsToState(['hidden', 'sortable', 'locked', 'flex', 'width'], state);
|
|
|
|
if (me.isGroupHeader) {
|
|
me.items.each(function(column){
|
|
columns.push(column.getColumnState());
|
|
});
|
|
if (columns.length) {
|
|
state.columns = columns;
|
|
}
|
|
} else if (me.isSubHeader && me.ownerCt.hidden) {
|
|
|
|
delete me.hidden;
|
|
}
|
|
|
|
if ('width' in state) {
|
|
delete state.flex;
|
|
}
|
|
return state;
|
|
},
|
|
|
|
|
|
setText: function(text) {
|
|
this.text = text;
|
|
if (this.rendered) {
|
|
this.textEl.update(text);
|
|
}
|
|
},
|
|
|
|
|
|
|
|
getOwnerHeaderCt: function() {
|
|
return this.up(':not([isHeader])');
|
|
},
|
|
|
|
|
|
getIndex: function() {
|
|
return this.isGroupColumn ? false : this.getOwnerHeaderCt().getHeaderIndex(this);
|
|
},
|
|
|
|
onRender: function() {
|
|
var me = this,
|
|
grid = me.up('tablepanel');
|
|
|
|
|
|
|
|
if (grid && (!me.sortable || grid.sortableColumns === false) && !me.groupable && !me.lockable && (grid.enableColumnHide === false || !me.getOwnerHeaderCt().getHideableColumns().length)) {
|
|
me.menuDisabled = true;
|
|
}
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
afterRender: function() {
|
|
var me = this,
|
|
el = me.el;
|
|
|
|
me.callParent(arguments);
|
|
|
|
el.addCls(Ext.baseCSSPrefix + 'column-header-align-' + me.align).addClsOnOver(me.overCls);
|
|
|
|
me.mon(el, {
|
|
click: me.onElClick,
|
|
dblclick: me.onElDblClick,
|
|
scope: me
|
|
});
|
|
|
|
|
|
|
|
if (!Ext.isIE8 || !Ext.isStrict) {
|
|
me.mon(me.getFocusEl(), {
|
|
focus: me.onTitleMouseOver,
|
|
blur: me.onTitleMouseOut,
|
|
scope: me
|
|
});
|
|
}
|
|
|
|
me.mon(me.titleContainer, {
|
|
mouseenter: me.onTitleMouseOver,
|
|
mouseleave: me.onTitleMouseOut,
|
|
scope: me
|
|
});
|
|
|
|
me.keyNav = Ext.create('Ext.util.KeyNav', el, {
|
|
enter: me.onEnterKey,
|
|
down: me.onDownKey,
|
|
scope: me
|
|
});
|
|
},
|
|
|
|
|
|
setWidth: function(width, doLayout) {
|
|
var me = this,
|
|
headerCt = me.ownerCt,
|
|
siblings,
|
|
len, i,
|
|
oldWidth = me.getWidth(),
|
|
groupWidth = 0,
|
|
sibling;
|
|
|
|
if (width !== oldWidth) {
|
|
me.oldWidth = oldWidth;
|
|
|
|
|
|
|
|
me.minWidth = me.width = width;
|
|
|
|
|
|
if (headerCt.isGroupHeader) {
|
|
siblings = headerCt.items.items;
|
|
len = siblings.length;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
sibling = siblings[i];
|
|
if (!sibling.hidden) {
|
|
groupWidth += (sibling === me) ? width : sibling.getWidth();
|
|
}
|
|
}
|
|
headerCt.setWidth(groupWidth, doLayout);
|
|
} else if (doLayout !== false) {
|
|
|
|
headerCt.doLayout();
|
|
}
|
|
}
|
|
},
|
|
|
|
afterComponentLayout: function(width, height) {
|
|
var me = this,
|
|
ownerHeaderCt = this.getOwnerHeaderCt();
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
|
|
|
|
if (width && !me.isGroupHeader && ownerHeaderCt) {
|
|
ownerHeaderCt.onHeaderResize(me, width, true);
|
|
}
|
|
if (me.oldWidth && (width !== me.oldWidth)) {
|
|
ownerHeaderCt.fireEvent('columnresize', ownerHeaderCt, this, width);
|
|
}
|
|
delete me.oldWidth;
|
|
},
|
|
|
|
|
|
|
|
|
|
setPadding: function(headerHeight) {
|
|
var me = this,
|
|
lineHeight = Ext.util.TextMetrics.measure(me.textEl.dom, me.text).height;
|
|
|
|
|
|
if (!me.isGroupHeader) {
|
|
if (me.titleContainer.getHeight() < headerHeight) {
|
|
me.titleContainer.dom.style.height = headerHeight + 'px';
|
|
}
|
|
}
|
|
headerHeight = me.titleContainer.getViewSize().height;
|
|
|
|
|
|
if (lineHeight) {
|
|
me.titleContainer.setStyle({
|
|
paddingTop: Math.max(((headerHeight - lineHeight) / 2), 0) + 'px'
|
|
});
|
|
}
|
|
|
|
|
|
if (Ext.isIE && me.triggerEl) {
|
|
me.triggerEl.setHeight(headerHeight);
|
|
}
|
|
},
|
|
|
|
onDestroy: function() {
|
|
var me = this;
|
|
|
|
Ext.destroy(me.textEl, me.keyNav);
|
|
delete me.keyNav;
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
onTitleMouseOver: function() {
|
|
this.titleContainer.addCls(this.hoverCls);
|
|
},
|
|
|
|
onTitleMouseOut: function() {
|
|
this.titleContainer.removeCls(this.hoverCls);
|
|
},
|
|
|
|
onDownKey: function(e) {
|
|
if (this.triggerEl) {
|
|
this.onElClick(e, this.triggerEl.dom || this.el.dom);
|
|
}
|
|
},
|
|
|
|
onEnterKey: function(e) {
|
|
this.onElClick(e, this.el.dom);
|
|
},
|
|
|
|
|
|
onElDblClick: function(e, t) {
|
|
var me = this,
|
|
ownerCt = me.ownerCt;
|
|
if (ownerCt && Ext.Array.indexOf(ownerCt.items, me) !== 0 && me.isOnLeftEdge(e) ) {
|
|
ownerCt.expandToFit(me.previousSibling('gridcolumn'));
|
|
}
|
|
},
|
|
|
|
onElClick: function(e, t) {
|
|
|
|
|
|
var me = this,
|
|
ownerHeaderCt = me.getOwnerHeaderCt();
|
|
|
|
if (ownerHeaderCt && !ownerHeaderCt.ddLock) {
|
|
|
|
|
|
if (me.triggerEl && (e.target === me.triggerEl.dom || t === me.triggerEl.dom || e.within(me.triggerEl))) {
|
|
ownerHeaderCt.onHeaderTriggerClick(me, e, t);
|
|
|
|
} else if (e.getKey() || (!me.isOnLeftEdge(e) && !me.isOnRightEdge(e))) {
|
|
me.toggleSortState();
|
|
ownerHeaderCt.onHeaderClick(me, e, t);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
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 ds = this.up('tablepanel').store;
|
|
ds.sort({
|
|
property: this.getSortParam(),
|
|
direction: state
|
|
});
|
|
},
|
|
|
|
|
|
getSortParam: function() {
|
|
return this.dataIndex;
|
|
},
|
|
|
|
|
|
|
|
setSortState: function(state, skipClear, initial) {
|
|
var me = this,
|
|
colSortClsPrefix = Ext.baseCSSPrefix + 'column-header-sort-',
|
|
ascCls = colSortClsPrefix + 'ASC',
|
|
descCls = colSortClsPrefix + 'DESC',
|
|
nullCls = colSortClsPrefix + 'null',
|
|
ownerHeaderCt = me.getOwnerHeaderCt(),
|
|
oldSortState = me.sortState;
|
|
|
|
if (oldSortState !== state && me.getSortParam()) {
|
|
me.addCls(colSortClsPrefix + state);
|
|
|
|
if (state && !initial) {
|
|
me.doSort(state);
|
|
}
|
|
switch (state) {
|
|
case 'DESC':
|
|
me.removeCls([ascCls, nullCls]);
|
|
break;
|
|
case 'ASC':
|
|
me.removeCls([descCls, nullCls]);
|
|
break;
|
|
case null:
|
|
me.removeCls([ascCls, descCls]);
|
|
break;
|
|
}
|
|
if (ownerHeaderCt && !me.triStateSort && !skipClear) {
|
|
ownerHeaderCt.clearOtherSortStates(me);
|
|
}
|
|
me.sortState = state;
|
|
ownerHeaderCt.fireEvent('sortchange', ownerHeaderCt, me, state);
|
|
}
|
|
},
|
|
|
|
hide: function() {
|
|
var me = this,
|
|
items,
|
|
len, i,
|
|
lb,
|
|
newWidth = 0,
|
|
ownerHeaderCt = me.getOwnerHeaderCt();
|
|
|
|
|
|
me.oldWidth = me.getWidth();
|
|
|
|
|
|
if (me.isGroupHeader) {
|
|
items = me.items.items;
|
|
me.callParent(arguments);
|
|
ownerHeaderCt.onHeaderHide(me);
|
|
for (i = 0, len = items.length; i < len; i++) {
|
|
items[i].hidden = true;
|
|
ownerHeaderCt.onHeaderHide(items[i], true);
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
lb = me.ownerCt.componentLayout.layoutBusy;
|
|
me.ownerCt.componentLayout.layoutBusy = true;
|
|
me.callParent(arguments);
|
|
me.ownerCt.componentLayout.layoutBusy = lb;
|
|
|
|
|
|
ownerHeaderCt.onHeaderHide(me);
|
|
|
|
if (me.ownerCt.isGroupHeader) {
|
|
|
|
items = me.ownerCt.query('>:not([hidden])');
|
|
if (!items.length) {
|
|
me.ownerCt.hide();
|
|
}
|
|
|
|
else {
|
|
for (i = 0, len = items.length; i < len; i++) {
|
|
newWidth += items[i].getWidth();
|
|
}
|
|
me.ownerCt.minWidth = newWidth;
|
|
me.ownerCt.setWidth(newWidth);
|
|
}
|
|
}
|
|
},
|
|
|
|
show: function() {
|
|
var me = this,
|
|
ownerCt = me.ownerCt,
|
|
ownerCtCompLayout = ownerCt.componentLayout,
|
|
ownerCtCompLayoutBusy = ownerCtCompLayout.layoutBusy,
|
|
ownerCtLayout = ownerCt.layout,
|
|
ownerCtLayoutBusy = ownerCtLayout.layoutBusy,
|
|
items,
|
|
len, i,
|
|
item,
|
|
newWidth = 0;
|
|
|
|
|
|
|
|
|
|
ownerCtCompLayout.layoutBusy = ownerCtLayout.layoutBusy = true;
|
|
|
|
me.callParent(arguments);
|
|
|
|
ownerCtCompLayout.layoutBusy = ownerCtCompLayoutBusy;
|
|
ownerCtLayout.layoutBusy = ownerCtLayoutBusy;
|
|
|
|
|
|
if (me.isSubHeader) {
|
|
if (!ownerCt.isVisible()) {
|
|
ownerCt.show();
|
|
}
|
|
}
|
|
|
|
|
|
if (me.isGroupHeader && !me.query(':not([hidden])').length) {
|
|
items = me.query('>*');
|
|
for (i = 0, len = items.length; i < len; i++) {
|
|
item = items[i];
|
|
item.preventLayout = true;
|
|
item.show();
|
|
newWidth += item.getWidth();
|
|
delete item.preventLayout;
|
|
}
|
|
me.setWidth(newWidth);
|
|
}
|
|
|
|
|
|
if (ownerCt.isGroupHeader && me.preventLayout !== true) {
|
|
items = ownerCt.query('>:not([hidden])');
|
|
for (i = 0, len = items.length; i < len; i++) {
|
|
newWidth += items[i].getWidth();
|
|
}
|
|
ownerCt.minWidth = newWidth;
|
|
ownerCt.setWidth(newWidth);
|
|
}
|
|
|
|
|
|
ownerCt = me.getOwnerHeaderCt();
|
|
if (ownerCt) {
|
|
ownerCt.onHeaderShow(me, me.preventLayout);
|
|
}
|
|
},
|
|
|
|
getDesiredWidth: function() {
|
|
var me = this;
|
|
if (me.rendered && me.componentLayout && me.componentLayout.lastComponentSize) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return me.componentLayout.lastComponentSize.width;
|
|
|
|
|
|
|
|
}
|
|
else if (me.flex) {
|
|
|
|
return me.width;
|
|
}
|
|
else {
|
|
return me.width;
|
|
}
|
|
},
|
|
|
|
getCellSelector: function() {
|
|
return '.' + Ext.baseCSSPrefix + 'grid-cell-' + this.getItemId();
|
|
},
|
|
|
|
getCellInnerSelector: function() {
|
|
return this.getCellSelector() + ' .' + Ext.baseCSSPrefix + 'grid-cell-inner';
|
|
},
|
|
|
|
isOnLeftEdge: function(e) {
|
|
return (e.getXY()[0] - this.el.getLeft() <= this.handleWidth);
|
|
},
|
|
|
|
isOnRightEdge: function(e) {
|
|
return (this.el.getRight() - e.getXY()[0] <= this.handleWidth);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.RowNumberer', {
|
|
extend: 'Ext.grid.column.Column',
|
|
alias: 'widget.rownumberer',
|
|
|
|
|
|
text: " ",
|
|
|
|
|
|
width: 23,
|
|
|
|
|
|
sortable: false,
|
|
|
|
align: 'right',
|
|
|
|
constructor : function(config){
|
|
this.callParent(arguments);
|
|
if (this.rowspan) {
|
|
this.renderer = Ext.Function.bind(this.renderer, this);
|
|
}
|
|
},
|
|
|
|
|
|
resizable: false,
|
|
hideable: false,
|
|
menuDisabled: true,
|
|
dataIndex: '',
|
|
cls: Ext.baseCSSPrefix + 'row-numberer',
|
|
rowspan: undefined,
|
|
|
|
|
|
renderer: function(value, metaData, record, rowIdx, colIdx, store) {
|
|
if (this.rowspan){
|
|
metaData.cellAttr = 'rowspan="'+this.rowspan+'"';
|
|
}
|
|
|
|
metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
|
|
return store.indexOfTotal(record) + 1;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.view.DropZone', {
|
|
extend: 'Ext.dd.DropZone',
|
|
|
|
indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
|
|
indicatorCls: 'x-grid-drop-indicator',
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
Ext.apply(me, config);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!me.ddGroup) {
|
|
me.ddGroup = 'view-dd-zone-' + me.view.id;
|
|
}
|
|
|
|
|
|
|
|
|
|
me.callParent([me.view.el]);
|
|
},
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
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 = Ext.createWidget('component', {
|
|
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;
|
|
},
|
|
|
|
|
|
containsRecordAtOffset: function(records, record, offset) {
|
|
if (!record) {
|
|
return false;
|
|
}
|
|
var view = this.view,
|
|
recordIndex = view.indexOf(record),
|
|
nodeBefore = view.getNode(recordIndex + offset),
|
|
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,
|
|
indicator, 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);
|
|
|
|
|
|
me.overRecord = overRecord;
|
|
me.currentPosition = pos;
|
|
}
|
|
} else {
|
|
me.invalidateDrop();
|
|
}
|
|
},
|
|
|
|
invalidateDrop: function() {
|
|
if (this.valid) {
|
|
this.valid = false;
|
|
this.getIndicator().hide();
|
|
}
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
|
|
notifyOut: function(node, dragZone, e, data) {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
delete me.overRecord;
|
|
delete me.currentPosition;
|
|
if (me.indicator) {
|
|
me.indicator.hide();
|
|
}
|
|
},
|
|
|
|
|
|
onContainerOver : function(dd, e, data) {
|
|
var me = this,
|
|
view = me.view,
|
|
count = view.store.getCount();
|
|
|
|
|
|
if (count) {
|
|
me.positionIndicator(view.getNode(count - 1), data, e);
|
|
}
|
|
|
|
|
|
else {
|
|
delete me.overRecord;
|
|
delete me.currentPosition;
|
|
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(node, dragZone, e, data) {
|
|
var me = this,
|
|
dropped = false,
|
|
|
|
|
|
|
|
|
|
|
|
processDrop = function () {
|
|
me.invalidateDrop();
|
|
me.handleNodeDrop(data, me.overRecord, me.currentPosition);
|
|
dropped = true;
|
|
me.fireViewEvent('drop', node, data, me.overRecord, me.currentPosition);
|
|
},
|
|
performOperation = false;
|
|
|
|
if (me.valid) {
|
|
performOperation = me.fireViewEvent('beforedrop', node, data, me.overRecord, me.currentPosition, processDrop);
|
|
if (performOperation !== false) {
|
|
|
|
if (!dropped) {
|
|
processDrop();
|
|
}
|
|
}
|
|
}
|
|
return performOperation;
|
|
},
|
|
|
|
destroy: function(){
|
|
Ext.destroy(this.indicator);
|
|
delete this.indicator;
|
|
this.callParent();
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.ViewDropZone', {
|
|
extend: 'Ext.view.DropZone',
|
|
|
|
indicatorHtml: '<div class="x-grid-drop-indicator-left"></div><div class="x-grid-drop-indicator-right"></div>',
|
|
indicatorCls: 'x-grid-drop-indicator',
|
|
|
|
handleNodeDrop : function(data, record, position) {
|
|
var view = this.view,
|
|
store = view.getStore(),
|
|
index, records, i, len;
|
|
|
|
|
|
if (data.copy) {
|
|
records = data.records;
|
|
data.records = [];
|
|
for (i = 0, len = records.length; i < len; i++) {
|
|
data.records.push(records[i].copy(records[i].getId()));
|
|
}
|
|
} else {
|
|
|
|
data.view.store.remove(data.records, data.view === view);
|
|
}
|
|
|
|
index = store.indexOf(record);
|
|
|
|
|
|
if (position !== 'before') {
|
|
index++;
|
|
}
|
|
store.insert(index, data.records);
|
|
view.getSelectionModel().select(data.records);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.column.Action', {
|
|
extend: 'Ext.grid.column.Column',
|
|
alias: ['widget.actioncolumn'],
|
|
alternateClassName: 'Ext.grid.ActionColumn',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
header: ' ',
|
|
|
|
actionIdRe: new RegExp(Ext.baseCSSPrefix + 'action-col-(\\d+)'),
|
|
|
|
|
|
altText: '',
|
|
|
|
sortable: false,
|
|
|
|
constructor: function(config) {
|
|
var me = this,
|
|
cfg = Ext.apply({}, config),
|
|
items = cfg.items || [me],
|
|
l = items.length,
|
|
i,
|
|
item;
|
|
|
|
|
|
delete cfg.items;
|
|
me.callParent([cfg]);
|
|
|
|
|
|
me.items = items;
|
|
|
|
|
|
|
|
me.renderer = function(v, meta) {
|
|
|
|
v = Ext.isFunction(cfg.renderer) ? cfg.renderer.apply(this, arguments)||'' : '';
|
|
|
|
meta.tdCls += ' ' + Ext.baseCSSPrefix + 'action-col-cell';
|
|
for (i = 0; i < l; i++) {
|
|
item = items[i];
|
|
item.disable = Ext.Function.bind(me.disableAction, me, [i]);
|
|
item.enable = Ext.Function.bind(me.enableAction, me, [i]);
|
|
v += '<img alt="' + (item.altText || me.altText) + '" src="' + (item.icon || Ext.BLANK_IMAGE_URL) +
|
|
'" class="' + Ext.baseCSSPrefix + 'action-col-icon ' + Ext.baseCSSPrefix + 'action-col-' + String(i) + ' ' + (item.disabled ? Ext.baseCSSPrefix + 'item-disabled' : ' ') + (item.iconCls || '') +
|
|
' ' + (Ext.isFunction(item.getClass) ? item.getClass.apply(item.scope||me.scope||me, arguments) : (me.iconCls || '')) + '"' +
|
|
((item.tooltip) ? ' data-qtip="' + item.tooltip + '"' : '') + ' />';
|
|
}
|
|
return v;
|
|
};
|
|
},
|
|
|
|
|
|
enableAction: function(index) {
|
|
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);
|
|
},
|
|
|
|
|
|
disableAction: function(index) {
|
|
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);
|
|
},
|
|
|
|
destroy: function() {
|
|
delete this.items;
|
|
delete this.renderer;
|
|
return this.callParent(arguments);
|
|
},
|
|
|
|
|
|
processEvent : function(type, view, cell, recordIndex, cellIndex, e){
|
|
var me = this,
|
|
match = e.getTarget().className.match(me.actionIdRe),
|
|
item, fn;
|
|
|
|
if (match) {
|
|
item = me.items[parseInt(match[1], 10)];
|
|
if (item) {
|
|
if (type == 'click') {
|
|
fn = item.handler || me.handler;
|
|
if (fn && !item.disabled) {
|
|
fn.call(item.scope || me.scope || me, view, recordIndex, cellIndex, item, e);
|
|
}
|
|
} else if (type == 'mousedown' && item.stopSelection !== false) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return me.callParent(arguments);
|
|
},
|
|
|
|
cascade: function(fn, scope) {
|
|
fn.call(scope||this, this);
|
|
},
|
|
|
|
|
|
getRefItems: function() {
|
|
return [];
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.column.Boolean', {
|
|
extend: 'Ext.grid.column.Column',
|
|
alias: ['widget.booleancolumn'],
|
|
alternateClassName: 'Ext.grid.BooleanColumn',
|
|
|
|
|
|
trueText: 'true',
|
|
|
|
|
|
falseText: 'false',
|
|
|
|
|
|
undefinedText: ' ',
|
|
|
|
constructor: function(cfg){
|
|
this.callParent(arguments);
|
|
var trueText = this.trueText,
|
|
falseText = this.falseText,
|
|
undefinedText = this.undefinedText;
|
|
|
|
this.renderer = function(value){
|
|
if(value === undefined){
|
|
return undefinedText;
|
|
}
|
|
if(!value || value === 'false'){
|
|
return falseText;
|
|
}
|
|
return trueText;
|
|
};
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.column.Date', {
|
|
extend: 'Ext.grid.column.Column',
|
|
alias: ['widget.datecolumn'],
|
|
requires: ['Ext.Date'],
|
|
alternateClassName: 'Ext.grid.DateColumn',
|
|
|
|
|
|
|
|
initComponent: function(){
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
if (!me.format) {
|
|
me.format = Ext.Date.defaultFormat;
|
|
}
|
|
me.renderer = Ext.util.Format.dateRenderer(me.format);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.column.Number', {
|
|
extend: 'Ext.grid.column.Column',
|
|
alias: ['widget.numbercolumn'],
|
|
requires: ['Ext.util.Format'],
|
|
alternateClassName: 'Ext.grid.NumberColumn',
|
|
|
|
|
|
format : '0,000.00',
|
|
|
|
constructor: function(cfg) {
|
|
this.callParent(arguments);
|
|
this.renderer = Ext.util.Format.numberRenderer(this.format);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.column.Template', {
|
|
extend: 'Ext.grid.column.Column',
|
|
alias: ['widget.templatecolumn'],
|
|
requires: ['Ext.XTemplate'],
|
|
alternateClassName: 'Ext.grid.TemplateColumn',
|
|
|
|
|
|
|
|
constructor: function(cfg){
|
|
var me = this,
|
|
tpl;
|
|
|
|
me.callParent(arguments);
|
|
tpl = me.tpl = (!Ext.isPrimitive(me.tpl) && me.tpl.compile) ? me.tpl : Ext.create('Ext.XTemplate', me.tpl);
|
|
|
|
me.renderer = function(value, p, record) {
|
|
var data = Ext.apply({}, record.data, record.getAssociatedData());
|
|
return tpl.apply(data);
|
|
};
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.feature.Feature', {
|
|
extend: 'Ext.util.Observable',
|
|
alias: 'feature.feature',
|
|
|
|
isFeature: true,
|
|
disabled: false,
|
|
|
|
|
|
hasFeatureEvent: true,
|
|
|
|
|
|
eventPrefix: null,
|
|
|
|
|
|
eventSelector: null,
|
|
|
|
|
|
view: null,
|
|
|
|
|
|
grid: null,
|
|
|
|
|
|
collectData: false,
|
|
|
|
getFeatureTpl: function() {
|
|
return '';
|
|
},
|
|
|
|
|
|
getFireEventArgs: function(eventName, view, featureTarget, e) {
|
|
return [eventName, view, featureTarget, e];
|
|
},
|
|
|
|
|
|
attachEvents: function() {
|
|
|
|
},
|
|
|
|
getFragmentTpl: function() {
|
|
return;
|
|
},
|
|
|
|
|
|
mutateMetaRowTpl: function(metaRowTplArray) {
|
|
|
|
},
|
|
|
|
|
|
getMetaRowTplFragments: function() {
|
|
return {};
|
|
},
|
|
|
|
getTableFragments: function() {
|
|
return {};
|
|
},
|
|
|
|
|
|
getAdditionalData: function(data, idx, record, orig) {
|
|
return {};
|
|
},
|
|
|
|
|
|
enable: function() {
|
|
this.disabled = false;
|
|
},
|
|
|
|
|
|
disable: function() {
|
|
this.disabled = true;
|
|
}
|
|
|
|
});
|
|
|
|
Ext.define('Ext.grid.feature.AbstractSummary', {
|
|
|
|
|
|
|
|
extend: 'Ext.grid.feature.Feature',
|
|
|
|
alias: 'feature.abstractsummary',
|
|
|
|
|
|
|
|
|
|
showSummaryRow: true,
|
|
|
|
|
|
nestedIdRe: /\{\{id\}([\w\-]*)\}/g,
|
|
|
|
|
|
toggleSummaryRow: function(visible){
|
|
this.showSummaryRow = !!visible;
|
|
},
|
|
|
|
|
|
getSummaryFragments: function(){
|
|
var fragments = {};
|
|
if (this.showSummaryRow) {
|
|
Ext.apply(fragments, {
|
|
printSummaryRow: Ext.bind(this.printSummaryRow, this)
|
|
});
|
|
}
|
|
return fragments;
|
|
},
|
|
|
|
|
|
printSummaryRow: function(index){
|
|
var inner = this.view.getTableChunker().metaRowTpl.join(''),
|
|
prefix = Ext.baseCSSPrefix;
|
|
|
|
inner = inner.replace(prefix + 'grid-row', prefix + 'grid-row-summary');
|
|
inner = inner.replace('{{id}}', '{gridSummaryValue}');
|
|
inner = inner.replace(this.nestedIdRe, '{id$1}');
|
|
inner = inner.replace('{[this.embedRowCls()]}', '{rowCls}');
|
|
inner = inner.replace('{[this.embedRowAttr()]}', '{rowAttr}');
|
|
inner = Ext.create('Ext.XTemplate', inner, {
|
|
firstOrLastCls: Ext.view.TableChunker.firstOrLastCls
|
|
});
|
|
|
|
return inner.applyTemplate({
|
|
columns: this.getPrintData(index)
|
|
});
|
|
},
|
|
|
|
|
|
getColumnValue: function(column, summaryData){
|
|
var comp = Ext.getCmp(column.id),
|
|
value = summaryData[column.id],
|
|
renderer = comp.summaryRenderer;
|
|
|
|
if (renderer) {
|
|
value = renderer.call(
|
|
comp.scope || this,
|
|
value,
|
|
summaryData,
|
|
column.dataIndex
|
|
);
|
|
}
|
|
return value;
|
|
},
|
|
|
|
|
|
getSummary: function(store, type, field, group){
|
|
if (type) {
|
|
if (Ext.isFunction(type)) {
|
|
return store.aggregate(type, null, group);
|
|
}
|
|
|
|
switch (type) {
|
|
case 'count':
|
|
return store.count(group);
|
|
case 'min':
|
|
return store.min(field, group);
|
|
case 'max':
|
|
return store.max(field, group);
|
|
case 'sum':
|
|
return store.sum(field, group);
|
|
case 'average':
|
|
return store.average(field, group);
|
|
default:
|
|
return group ? {} : '';
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.feature.Chunking', {
|
|
extend: 'Ext.grid.feature.Feature',
|
|
alias: 'feature.chunking',
|
|
|
|
chunkSize: 20,
|
|
rowHeight: Ext.isIE ? 27 : 26,
|
|
visibleChunk: 0,
|
|
hasFeatureEvent: false,
|
|
attachEvents: function() {
|
|
var grid = this.view.up('gridpanel'),
|
|
scroller = grid.down('gridscroller[dock=right]');
|
|
scroller.el.on('scroll', this.onBodyScroll, this, {buffer: 300});
|
|
|
|
},
|
|
|
|
onBodyScroll: function(e, t) {
|
|
var view = this.view,
|
|
top = t.scrollTop,
|
|
nextChunk = Math.floor(top / this.rowHeight / this.chunkSize);
|
|
if (nextChunk !== this.visibleChunk) {
|
|
|
|
this.visibleChunk = nextChunk;
|
|
view.refresh();
|
|
view.el.dom.scrollTop = top;
|
|
|
|
view.el.dom.scrollTop = top;
|
|
}
|
|
},
|
|
|
|
collectData: function(records, preppedRecords, startIndex, fullWidth, orig) {
|
|
var o = {
|
|
fullWidth: orig.fullWidth,
|
|
chunks: []
|
|
},
|
|
|
|
|
|
recordCount = orig.rows.length,
|
|
start = 0,
|
|
i = 0,
|
|
visibleChunk = this.visibleChunk,
|
|
chunk,
|
|
rows,
|
|
chunkLength;
|
|
|
|
for (; start < recordCount; start+=this.chunkSize, i++) {
|
|
if (start+this.chunkSize > recordCount) {
|
|
chunkLength = recordCount - start;
|
|
} else {
|
|
chunkLength = this.chunkSize;
|
|
}
|
|
|
|
if (i >= visibleChunk - 1 && i <= visibleChunk + 1) {
|
|
rows = orig.rows.slice(start, start+this.chunkSize);
|
|
} else {
|
|
rows = [];
|
|
}
|
|
o.chunks.push({
|
|
rows: rows,
|
|
fullWidth: fullWidth,
|
|
chunkHeight: chunkLength * this.rowHeight
|
|
});
|
|
}
|
|
|
|
|
|
return o;
|
|
},
|
|
|
|
getTableFragments: function() {
|
|
return {
|
|
openTableWrap: function() {
|
|
return '<tpl for="chunks"><div class="' + Ext.baseCSSPrefix + 'grid-chunk" style="height: {chunkHeight}px;">';
|
|
},
|
|
closeTableWrap: function() {
|
|
return '</div></tpl>';
|
|
}
|
|
};
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.feature.Grouping', {
|
|
extend: 'Ext.grid.feature.Feature',
|
|
alias: 'feature.grouping',
|
|
|
|
eventPrefix: 'group',
|
|
eventSelector: '.' + Ext.baseCSSPrefix + 'grid-group-hd',
|
|
|
|
constructor: function() {
|
|
var me = this;
|
|
|
|
me.collapsedState = {};
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
groupHeaderTpl: 'Group: {name}',
|
|
|
|
|
|
depthToIndent: 17,
|
|
|
|
collapsedCls: Ext.baseCSSPrefix + 'grid-group-collapsed',
|
|
hdCollapsedCls: Ext.baseCSSPrefix + 'grid-group-hd-collapsed',
|
|
|
|
|
|
groupByText : 'Group By This Field',
|
|
|
|
showGroupsText : 'Show in Groups',
|
|
|
|
|
|
hideGroupedHeader : false,
|
|
|
|
|
|
startCollapsed : false,
|
|
|
|
|
|
enableGroupingMenu : true,
|
|
|
|
|
|
enableNoGroups : true,
|
|
|
|
enable: function() {
|
|
var me = this,
|
|
view = me.view,
|
|
store = view.store,
|
|
groupToggleMenuItem;
|
|
|
|
me.lastGroupField = me.getGroupField();
|
|
|
|
if (me.lastGroupIndex) {
|
|
store.group(me.lastGroupIndex);
|
|
}
|
|
me.callParent();
|
|
groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
|
|
groupToggleMenuItem.setChecked(true, true);
|
|
me.refreshIf();
|
|
},
|
|
|
|
disable: function() {
|
|
var me = this,
|
|
view = me.view,
|
|
store = view.store,
|
|
remote = store.remoteGroup,
|
|
groupToggleMenuItem,
|
|
lastGroup;
|
|
|
|
lastGroup = store.groupers.first();
|
|
if (lastGroup) {
|
|
me.lastGroupIndex = lastGroup.property;
|
|
me.block();
|
|
store.clearGrouping();
|
|
me.unblock();
|
|
}
|
|
|
|
me.callParent();
|
|
groupToggleMenuItem = me.view.headerCt.getMenu().down('#groupToggleMenuItem');
|
|
groupToggleMenuItem.setChecked(true, true);
|
|
groupToggleMenuItem.setChecked(false, true);
|
|
if (!remote) {
|
|
view.refresh();
|
|
}
|
|
},
|
|
|
|
refreshIf: function() {
|
|
if (this.blockRefresh !== true) {
|
|
this.view.refresh();
|
|
}
|
|
},
|
|
|
|
getFeatureTpl: function(values, parent, x, xcount) {
|
|
var me = this;
|
|
|
|
return [
|
|
'<tpl if="typeof rows !== \'undefined\'">',
|
|
|
|
'<tr class="' + Ext.baseCSSPrefix + 'grid-group-hd ' + (me.startCollapsed ? me.hdCollapsedCls : '') + ' {hdCollapsedCls}"><td class="' + Ext.baseCSSPrefix + 'grid-cell" colspan="' + parent.columns.length + '" {[this.indentByDepth(values)]}><div class="' + Ext.baseCSSPrefix + 'grid-cell-inner"><div class="' + Ext.baseCSSPrefix + 'grid-group-title">{collapsed}' + me.groupHeaderTpl + '</div></div></td></tr>',
|
|
|
|
'<tr id="{viewId}-gp-{name}" class="' + Ext.baseCSSPrefix + 'grid-group-body ' + (me.startCollapsed ? me.collapsedCls : '') + ' {collapsedCls}"><td colspan="' + parent.columns.length + '">{[this.recurse(values)]}</td></tr>',
|
|
'</tpl>'
|
|
].join('');
|
|
},
|
|
|
|
getFragmentTpl: function() {
|
|
return {
|
|
indentByDepth: this.indentByDepth,
|
|
depthToIndent: this.depthToIndent
|
|
};
|
|
},
|
|
|
|
indentByDepth: function(values) {
|
|
var depth = values.depth || 0;
|
|
return 'style="padding-left:'+ depth * this.depthToIndent + 'px;"';
|
|
},
|
|
|
|
|
|
|
|
destroy: function() {
|
|
var me = this;
|
|
|
|
delete me.view;
|
|
delete me.prunedHeader;
|
|
},
|
|
|
|
|
|
attachEvents: function() {
|
|
var me = this,
|
|
view = me.view;
|
|
|
|
view.on({
|
|
scope: me,
|
|
groupclick: me.onGroupClick,
|
|
rowfocus: me.onRowFocus
|
|
});
|
|
view.store.on('groupchange', me.onGroupChange, me);
|
|
|
|
me.pruneGroupedHeader();
|
|
|
|
if (me.enableGroupingMenu) {
|
|
me.injectGroupingMenu();
|
|
}
|
|
me.lastGroupField = me.getGroupField();
|
|
me.block();
|
|
me.onGroupChange();
|
|
me.unblock();
|
|
},
|
|
|
|
injectGroupingMenu: function() {
|
|
var me = this,
|
|
view = me.view,
|
|
headerCt = view.headerCt;
|
|
headerCt.showMenuBy = me.showMenuBy;
|
|
headerCt.getMenuItems = me.getMenuItems();
|
|
},
|
|
|
|
showMenuBy: function(t, header) {
|
|
var menu = this.getMenu(),
|
|
groupMenuItem = menu.down('#groupMenuItem'),
|
|
groupableMth = header.groupable === false ? 'disable' : 'enable';
|
|
|
|
groupMenuItem[groupableMth]();
|
|
Ext.grid.header.Container.prototype.showMenuBy.apply(this, arguments);
|
|
},
|
|
|
|
getMenuItems: function() {
|
|
var me = this,
|
|
groupByText = me.groupByText,
|
|
disabled = me.disabled,
|
|
showGroupsText = me.showGroupsText,
|
|
enableNoGroups = me.enableNoGroups,
|
|
groupMenuItemClick = Ext.Function.bind(me.onGroupMenuItemClick, me),
|
|
groupToggleMenuItemClick = Ext.Function.bind(me.onGroupToggleMenuItemClick, me);
|
|
|
|
|
|
return function() {
|
|
var o = Ext.grid.header.Container.prototype.getMenuItems.call(this);
|
|
o.push('-', {
|
|
iconCls: Ext.baseCSSPrefix + 'group-by-icon',
|
|
itemId: 'groupMenuItem',
|
|
text: groupByText,
|
|
handler: groupMenuItemClick
|
|
});
|
|
if (enableNoGroups) {
|
|
o.push({
|
|
itemId: 'groupToggleMenuItem',
|
|
text: showGroupsText,
|
|
checked: !disabled,
|
|
checkHandler: groupToggleMenuItemClick
|
|
});
|
|
}
|
|
return o;
|
|
};
|
|
},
|
|
|
|
|
|
|
|
onGroupMenuItemClick: function(menuItem, e) {
|
|
var me = this,
|
|
menu = menuItem.parentMenu,
|
|
hdr = menu.activeHeader,
|
|
view = me.view,
|
|
store = view.store,
|
|
remote = store.remoteGroup;
|
|
|
|
delete me.lastGroupIndex;
|
|
me.block();
|
|
me.enable();
|
|
store.group(hdr.dataIndex);
|
|
me.pruneGroupedHeader();
|
|
me.unblock();
|
|
if (!remote) {
|
|
view.refresh();
|
|
}
|
|
},
|
|
|
|
block: function(){
|
|
this.blockRefresh = this.view.blockRefresh = true;
|
|
},
|
|
|
|
unblock: function(){
|
|
this.blockRefresh = this.view.blockRefresh = false;
|
|
},
|
|
|
|
|
|
onGroupToggleMenuItemClick: function(menuItem, checked) {
|
|
this[checked ? 'enable' : 'disable']();
|
|
},
|
|
|
|
|
|
pruneGroupedHeader: function() {
|
|
var me = this,
|
|
view = me.view,
|
|
store = view.store,
|
|
groupField = me.getGroupField(),
|
|
headerCt = view.headerCt,
|
|
header = headerCt.down('header[dataIndex=' + groupField + ']');
|
|
|
|
if (header) {
|
|
if (me.prunedHeader) {
|
|
me.prunedHeader.show();
|
|
}
|
|
me.prunedHeader = header;
|
|
header.hide();
|
|
}
|
|
},
|
|
|
|
getGroupField: function(){
|
|
var group = this.view.store.groupers.first();
|
|
if (group) {
|
|
return group.property;
|
|
}
|
|
return '';
|
|
},
|
|
|
|
|
|
onRowFocus: function(rowIdx) {
|
|
var node = this.view.getNode(rowIdx),
|
|
groupBd = Ext.fly(node).up('.' + this.collapsedCls);
|
|
|
|
if (groupBd) {
|
|
|
|
|
|
this.expand(groupBd);
|
|
}
|
|
},
|
|
|
|
|
|
expand: function(groupBd) {
|
|
var me = this,
|
|
view = me.view,
|
|
grid = view.up('gridpanel'),
|
|
groupBdDom = Ext.getDom(groupBd);
|
|
|
|
me.collapsedState[groupBdDom.id] = false;
|
|
|
|
groupBd.removeCls(me.collapsedCls);
|
|
groupBd.prev().removeCls(me.hdCollapsedCls);
|
|
|
|
grid.determineScrollbars();
|
|
grid.invalidateScroller();
|
|
view.fireEvent('groupexpand');
|
|
},
|
|
|
|
|
|
collapse: function(groupBd) {
|
|
var me = this,
|
|
view = me.view,
|
|
grid = view.up('gridpanel'),
|
|
groupBdDom = Ext.getDom(groupBd);
|
|
|
|
me.collapsedState[groupBdDom.id] = true;
|
|
|
|
groupBd.addCls(me.collapsedCls);
|
|
groupBd.prev().addCls(me.hdCollapsedCls);
|
|
|
|
grid.determineScrollbars();
|
|
grid.invalidateScroller();
|
|
view.fireEvent('groupcollapse');
|
|
},
|
|
|
|
onGroupChange: function(){
|
|
var me = this,
|
|
field = me.getGroupField(),
|
|
menuItem;
|
|
|
|
if (me.hideGroupedHeader) {
|
|
if (me.lastGroupField) {
|
|
menuItem = me.getMenuItem(me.lastGroupField);
|
|
if (menuItem) {
|
|
menuItem.setChecked(true);
|
|
}
|
|
}
|
|
if (field) {
|
|
menuItem = me.getMenuItem(field);
|
|
if (menuItem) {
|
|
menuItem.setChecked(false);
|
|
}
|
|
}
|
|
}
|
|
if (me.blockRefresh !== true) {
|
|
me.view.refresh();
|
|
}
|
|
me.lastGroupField = field;
|
|
},
|
|
|
|
|
|
getMenuItem: function(dataIndex){
|
|
var view = this.view,
|
|
header = view.headerCt.down('gridcolumn[dataIndex=' + dataIndex + ']'),
|
|
menu = view.headerCt.getMenu();
|
|
|
|
return menu.down('menuitem[headerId='+ header.id +']');
|
|
},
|
|
|
|
|
|
onGroupClick: function(view, group, idx, foo, e) {
|
|
var me = this,
|
|
toggleCls = me.toggleCls,
|
|
groupBd = Ext.fly(group.nextSibling, '_grouping');
|
|
|
|
if (groupBd.hasCls(me.collapsedCls)) {
|
|
me.expand(groupBd);
|
|
} else {
|
|
me.collapse(groupBd);
|
|
}
|
|
},
|
|
|
|
|
|
getMetaRowTplFragments: function() {
|
|
return {
|
|
isRow: this.isRow,
|
|
closeRow: this.closeRow
|
|
};
|
|
},
|
|
|
|
|
|
|
|
isRow: function() {
|
|
return '<tpl if="typeof rows === \'undefined\'">';
|
|
},
|
|
|
|
|
|
|
|
closeRow: function() {
|
|
return '</tpl>';
|
|
},
|
|
|
|
|
|
mutateMetaRowTpl: function(metaRowTpl) {
|
|
metaRowTpl.unshift('{[this.isRow()]}');
|
|
metaRowTpl.push('{[this.closeRow()]}');
|
|
},
|
|
|
|
|
|
|
|
getAdditionalData: function(data, idx, record, orig) {
|
|
var view = this.view,
|
|
hCt = view.headerCt,
|
|
col = hCt.items.getAt(0),
|
|
o = {},
|
|
tdAttrKey = col.id + '-tdAttr';
|
|
|
|
|
|
o[tdAttrKey] = this.indentByDepth(data) + " " + (orig[tdAttrKey] ? orig[tdAttrKey] : '');
|
|
o.collapsed = 'true';
|
|
return o;
|
|
},
|
|
|
|
|
|
getGroupRows: function(group, records, preppedRecords, fullWidth) {
|
|
var me = this,
|
|
children = group.children,
|
|
rows = group.rows = [],
|
|
view = me.view;
|
|
group.viewId = view.id;
|
|
|
|
Ext.Array.each(records, function(record, idx) {
|
|
if (Ext.Array.indexOf(children, record) != -1) {
|
|
rows.push(Ext.apply(preppedRecords[idx], {
|
|
depth: 1
|
|
}));
|
|
}
|
|
});
|
|
delete group.children;
|
|
group.fullWidth = fullWidth;
|
|
if (me.collapsedState[view.id + '-gp-' + group.name]) {
|
|
group.collapsedCls = me.collapsedCls;
|
|
group.hdCollapsedCls = me.hdCollapsedCls;
|
|
}
|
|
|
|
return group;
|
|
},
|
|
|
|
|
|
collectData: function(records, preppedRecords, startIndex, fullWidth, o) {
|
|
var me = this,
|
|
store = me.view.store,
|
|
groups;
|
|
|
|
if (!me.disabled && store.isGrouped()) {
|
|
groups = store.getGroups();
|
|
Ext.Array.each(groups, function(group, idx){
|
|
me.getGroupRows(group, records, preppedRecords, fullWidth);
|
|
}, me);
|
|
return {
|
|
rows: groups,
|
|
fullWidth: fullWidth
|
|
};
|
|
}
|
|
return o;
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getFireEventArgs: function(type, view, featureTarget, e) {
|
|
var returnArray = [type, view, featureTarget],
|
|
groupBd = Ext.fly(featureTarget.nextSibling, '_grouping'),
|
|
groupBdId = Ext.getDom(groupBd).id,
|
|
prefix = view.id + '-gp-',
|
|
groupName = groupBdId.substr(prefix.length);
|
|
|
|
returnArray.push(groupName, e);
|
|
|
|
return returnArray;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.feature.GroupingSummary', {
|
|
|
|
|
|
|
|
extend: 'Ext.grid.feature.Grouping',
|
|
|
|
alias: 'feature.groupingsummary',
|
|
|
|
mixins: {
|
|
summary: 'Ext.grid.feature.AbstractSummary'
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
getFeatureTpl: function() {
|
|
var tpl = this.callParent(arguments);
|
|
|
|
if (this.showSummaryRow) {
|
|
|
|
tpl = tpl.replace('</tpl>', '');
|
|
tpl += '{[this.printSummaryRow(xindex)]}</tpl>';
|
|
}
|
|
return tpl;
|
|
},
|
|
|
|
|
|
getFragmentTpl: function() {
|
|
var me = this,
|
|
fragments = me.callParent();
|
|
|
|
Ext.apply(fragments, me.getSummaryFragments());
|
|
if (me.showSummaryRow) {
|
|
|
|
me.summaryGroups = me.view.store.getGroups();
|
|
me.summaryData = me.generateSummaryData();
|
|
}
|
|
return fragments;
|
|
},
|
|
|
|
|
|
getPrintData: function(index){
|
|
var me = this,
|
|
columns = me.view.headerCt.getColumnsForTpl(),
|
|
i = 0,
|
|
length = columns.length,
|
|
data = [],
|
|
name = me.summaryGroups[index - 1].name,
|
|
active = me.summaryData[name],
|
|
column;
|
|
|
|
for (; i < length; ++i) {
|
|
column = columns[i];
|
|
column.gridSummaryValue = this.getColumnValue(column, active);
|
|
data.push(column);
|
|
}
|
|
return data;
|
|
},
|
|
|
|
|
|
generateSummaryData: function(){
|
|
var me = this,
|
|
data = {},
|
|
remoteData = {},
|
|
store = me.view.store,
|
|
groupField = this.getGroupField(),
|
|
reader = store.proxy.reader,
|
|
groups = me.summaryGroups,
|
|
columns = me.view.headerCt.getColumnsForTpl(),
|
|
remote,
|
|
i,
|
|
length,
|
|
fieldData,
|
|
root,
|
|
key,
|
|
comp;
|
|
|
|
for (i = 0, length = groups.length; i < length; ++i) {
|
|
data[groups[i].name] = {};
|
|
}
|
|
|
|
|
|
if (me.remoteRoot && reader.rawData) {
|
|
|
|
root = reader.root;
|
|
reader.root = me.remoteRoot;
|
|
reader.buildExtractors(true);
|
|
Ext.Array.each(reader.getRoot(reader.rawData), function(value) {
|
|
remoteData[value[groupField]] = value;
|
|
});
|
|
|
|
reader.root = root;
|
|
reader.buildExtractors(true);
|
|
}
|
|
|
|
for (i = 0, length = columns.length; i < length; ++i) {
|
|
comp = Ext.getCmp(columns[i].id);
|
|
fieldData = me.getSummary(store, comp.summaryType, comp.dataIndex, true);
|
|
|
|
for (key in fieldData) {
|
|
if (fieldData.hasOwnProperty(key)) {
|
|
data[key][comp.id] = fieldData[key];
|
|
}
|
|
}
|
|
|
|
for (key in remoteData) {
|
|
if (remoteData.hasOwnProperty(key)) {
|
|
remote = remoteData[key][comp.dataIndex];
|
|
if (remote !== undefined && data[key] !== undefined) {
|
|
data[key][comp.id] = remote;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return data;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.feature.RowBody', {
|
|
extend: 'Ext.grid.feature.Feature',
|
|
alias: 'feature.rowbody',
|
|
rowBodyHiddenCls: Ext.baseCSSPrefix + 'grid-row-body-hidden',
|
|
rowBodyTrCls: Ext.baseCSSPrefix + 'grid-rowbody-tr',
|
|
rowBodyTdCls: Ext.baseCSSPrefix + 'grid-cell-rowbody',
|
|
rowBodyDivCls: Ext.baseCSSPrefix + 'grid-rowbody',
|
|
|
|
eventPrefix: 'rowbody',
|
|
eventSelector: '.' + Ext.baseCSSPrefix + 'grid-rowbody-tr',
|
|
|
|
getRowBody: function(values) {
|
|
return [
|
|
'<tr class="' + this.rowBodyTrCls + ' {rowBodyCls}">',
|
|
'<td class="' + this.rowBodyTdCls + '" colspan="{rowBodyColspan}">',
|
|
'<div class="' + this.rowBodyDivCls + '">{rowBody}</div>',
|
|
'</td>',
|
|
'</tr>'
|
|
].join('');
|
|
},
|
|
|
|
|
|
getMetaRowTplFragments: function() {
|
|
return {
|
|
getRowBody: this.getRowBody,
|
|
rowBodyTrCls: this.rowBodyTrCls,
|
|
rowBodyTdCls: this.rowBodyTdCls,
|
|
rowBodyDivCls: this.rowBodyDivCls
|
|
};
|
|
},
|
|
|
|
mutateMetaRowTpl: function(metaRowTpl) {
|
|
metaRowTpl.push('{[this.getRowBody(values)]}');
|
|
},
|
|
|
|
|
|
getAdditionalData: function(data, idx, record, orig) {
|
|
var headerCt = this.view.headerCt,
|
|
colspan = headerCt.getColumnCount();
|
|
|
|
return {
|
|
rowBody: "",
|
|
rowBodyCls: this.rowBodyCls,
|
|
rowBodyColspan: colspan
|
|
};
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.feature.RowWrap', {
|
|
extend: 'Ext.grid.feature.Feature',
|
|
alias: 'feature.rowwrap',
|
|
|
|
|
|
hasFeatureEvent: false,
|
|
|
|
mutateMetaRowTpl: function(metaRowTpl) {
|
|
|
|
|
|
metaRowTpl[0] = metaRowTpl[0].replace(Ext.baseCSSPrefix + 'grid-row', '');
|
|
metaRowTpl[0] = metaRowTpl[0].replace("{[this.embedRowCls()]}", "");
|
|
|
|
metaRowTpl.unshift('<table class="' + Ext.baseCSSPrefix + 'grid-table ' + Ext.baseCSSPrefix + 'grid-table-resizer" style="width: {[this.embedFullWidth()]}px;">');
|
|
|
|
metaRowTpl.unshift('<tr class="' + Ext.baseCSSPrefix + 'grid-row {[this.embedRowCls()]}"><td colspan="{[this.embedColSpan()]}"><div class="' + Ext.baseCSSPrefix + 'grid-rowwrap-div">');
|
|
|
|
|
|
metaRowTpl.push('</table>');
|
|
|
|
metaRowTpl.push('</div></td></tr>');
|
|
},
|
|
|
|
embedColSpan: function() {
|
|
return '{colspan}';
|
|
},
|
|
|
|
embedFullWidth: function() {
|
|
return '{fullWidth}';
|
|
},
|
|
|
|
getAdditionalData: function(data, idx, record, orig) {
|
|
var headerCt = this.view.headerCt,
|
|
colspan = headerCt.getColumnCount(),
|
|
fullWidth = headerCt.getFullWidth(),
|
|
items = headerCt.query('gridcolumn'),
|
|
itemsLn = items.length,
|
|
i = 0,
|
|
o = {
|
|
colspan: colspan,
|
|
fullWidth: fullWidth
|
|
},
|
|
id,
|
|
tdClsKey,
|
|
colResizerCls;
|
|
|
|
for (; i < itemsLn; i++) {
|
|
id = items[i].id;
|
|
tdClsKey = id + '-tdCls';
|
|
colResizerCls = Ext.baseCSSPrefix + 'grid-col-resizer-'+id;
|
|
|
|
|
|
|
|
o[tdClsKey] = colResizerCls + " " + (orig[tdClsKey] ? orig[tdClsKey] : '');
|
|
|
|
o[id+'-tdAttr'] = " style=\"width: " + (items[i].hidden ? 0 : items[i].getDesiredWidth()) + "px;\" ";
|
|
if (orig[id+'-tdAttr']) {
|
|
o[id+'-tdAttr'] += orig[id+'-tdAttr'];
|
|
}
|
|
|
|
}
|
|
|
|
return o;
|
|
},
|
|
|
|
getMetaRowTplFragments: function() {
|
|
return {
|
|
embedFullWidth: this.embedFullWidth,
|
|
embedColSpan: this.embedColSpan
|
|
};
|
|
}
|
|
|
|
});
|
|
|
|
Ext.define('Ext.grid.feature.Summary', {
|
|
|
|
|
|
|
|
extend: 'Ext.grid.feature.AbstractSummary',
|
|
|
|
alias: 'feature.summary',
|
|
|
|
|
|
|
|
|
|
getFragmentTpl: function() {
|
|
|
|
this.summaryData = this.generateSummaryData();
|
|
return this.getSummaryFragments();
|
|
},
|
|
|
|
|
|
getTableFragments: function(){
|
|
if (this.showSummaryRow) {
|
|
return {
|
|
closeRows: this.closeRows
|
|
};
|
|
}
|
|
},
|
|
|
|
|
|
closeRows: function() {
|
|
return '</tpl>{[this.printSummaryRow()]}';
|
|
},
|
|
|
|
|
|
getPrintData: function(index){
|
|
var me = this,
|
|
columns = me.view.headerCt.getColumnsForTpl(),
|
|
i = 0,
|
|
length = columns.length,
|
|
data = [],
|
|
active = me.summaryData,
|
|
column;
|
|
|
|
for (; i < length; ++i) {
|
|
column = columns[i];
|
|
column.gridSummaryValue = this.getColumnValue(column, active);
|
|
data.push(column);
|
|
}
|
|
return data;
|
|
},
|
|
|
|
|
|
generateSummaryData: function(){
|
|
var me = this,
|
|
data = {},
|
|
store = me.view.store,
|
|
columns = me.view.headerCt.getColumnsForTpl(),
|
|
i = 0,
|
|
length = columns.length,
|
|
fieldData,
|
|
key,
|
|
comp;
|
|
|
|
for (i = 0, length = columns.length; i < length; ++i) {
|
|
comp = Ext.getCmp(columns[i].id);
|
|
data[comp.id] = me.getSummary(store, comp.summaryType, comp.dataIndex, false);
|
|
}
|
|
return data;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.header.DragZone', {
|
|
extend: 'Ext.dd.DragZone',
|
|
colHeaderCls: Ext.baseCSSPrefix + 'column-header',
|
|
maxProxyWidth: 120,
|
|
|
|
constructor: function(headerCt) {
|
|
this.headerCt = headerCt;
|
|
this.ddGroup = this.getDDGroup();
|
|
this.callParent([headerCt.el]);
|
|
this.proxy.el.addCls(Ext.baseCSSPrefix + 'grid-col-dd');
|
|
},
|
|
|
|
getDDGroup: function() {
|
|
return 'header-dd-zone-' + this.headerCt.up('[scrollerOwner]').id;
|
|
},
|
|
|
|
getDragData: function(e) {
|
|
var header = e.getTarget('.'+this.colHeaderCls),
|
|
headerCmp;
|
|
|
|
if (header) {
|
|
headerCmp = Ext.getCmp(header.id);
|
|
if (!this.headerCt.dragging && headerCmp.draggable && !(headerCmp.isOnLeftEdge(e) || headerCmp.isOnRightEdge(e))) {
|
|
var ddel = document.createElement('div');
|
|
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;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.header.DropZone', {
|
|
extend: 'Ext.dd.DropZone',
|
|
colHeaderCls: Ext.baseCSSPrefix + 'column-header',
|
|
proxyOffsets: [-4, -9],
|
|
|
|
constructor: function(headerCt){
|
|
this.headerCt = headerCt;
|
|
this.ddGroup = this.getDDGroup();
|
|
this.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.topIndicator = Ext.DomHelper.append(Ext.getBody(), {
|
|
cls: "col-move-top",
|
|
html: " "
|
|
}, true);
|
|
}
|
|
return this.topIndicator;
|
|
},
|
|
|
|
getBottomIndicator: function() {
|
|
if (!this.bottomIndicator) {
|
|
this.bottomIndicator = Ext.DomHelper.append(Ext.getBody(), {
|
|
cls: "col-move-bottom",
|
|
html: " "
|
|
}, true);
|
|
}
|
|
return this.bottomIndicator;
|
|
},
|
|
|
|
getLocation: function(e, t) {
|
|
var x = e.getXY()[0],
|
|
region = Ext.fly(t).getRegion(),
|
|
pos, header;
|
|
|
|
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(draggedHeader, node, e){
|
|
var location = this.getLocation(e, node),
|
|
header = location.header,
|
|
pos = location.pos,
|
|
nextHd = draggedHeader.nextSibling('gridcolumn:not([hidden])'),
|
|
prevHd = draggedHeader.previousSibling('gridcolumn:not([hidden])'),
|
|
region, topIndicator, bottomIndicator, topAnchor, bottomAnchor,
|
|
topXY, bottomXY, headerCtEl, minX, maxX;
|
|
|
|
|
|
if (!header.draggable && header.getIndex() == 0) {
|
|
return false;
|
|
}
|
|
|
|
this.lastLocation = location;
|
|
|
|
if ((draggedHeader !== header) &&
|
|
((pos === "before" && nextHd !== header) ||
|
|
(pos === "after" && prevHd !== header)) &&
|
|
!header.isDescendantOf(draggedHeader)) {
|
|
|
|
|
|
|
|
|
|
var allDropZones = Ext.dd.DragDropManager.getRelated(this),
|
|
ln = allDropZones.length,
|
|
i = 0,
|
|
dropZone;
|
|
|
|
for (; i < ln; i++) {
|
|
dropZone = allDropZones[i];
|
|
if (dropZone !== this && dropZone.invalidateDrop) {
|
|
dropZone.invalidateDrop();
|
|
}
|
|
}
|
|
|
|
|
|
this.valid = true;
|
|
topIndicator = this.getTopIndicator();
|
|
bottomIndicator = this.getBottomIndicator();
|
|
if (pos === 'before') {
|
|
topAnchor = 'tl';
|
|
bottomAnchor = 'bl';
|
|
} else {
|
|
topAnchor = 'tr';
|
|
bottomAnchor = 'br';
|
|
}
|
|
topXY = header.el.getAnchorXY(topAnchor);
|
|
bottomXY = header.el.getAnchorXY(bottomAnchor);
|
|
|
|
|
|
headerCtEl = this.headerCt.el;
|
|
minX = headerCtEl.getLeft();
|
|
maxX = headerCtEl.getRight();
|
|
|
|
topXY[0] = Ext.Number.constrain(topXY[0], minX, maxX);
|
|
bottomXY[0] = Ext.Number.constrain(bottomXY[0], minX, maxX);
|
|
|
|
|
|
|
|
topXY[0] -= 4;
|
|
topXY[1] -= 9;
|
|
bottomXY[0] -= 4;
|
|
|
|
|
|
topIndicator.setXY(topXY);
|
|
bottomIndicator.setXY(bottomXY);
|
|
topIndicator.show();
|
|
bottomIndicator.show();
|
|
|
|
} else {
|
|
this.invalidateDrop();
|
|
}
|
|
},
|
|
|
|
invalidateDrop: function() {
|
|
this.valid = false;
|
|
this.hideIndicators();
|
|
},
|
|
|
|
onNodeOver: function(node, dragZone, e, data) {
|
|
if (data.header.el.dom !== node) {
|
|
this.positionIndicator(data.header, node, e);
|
|
}
|
|
return this.valid ? this.dropAllowed : this.dropNotAllowed;
|
|
},
|
|
|
|
hideIndicators: function() {
|
|
this.getTopIndicator().hide();
|
|
this.getBottomIndicator().hide();
|
|
},
|
|
|
|
onNodeOut: function() {
|
|
this.hideIndicators();
|
|
},
|
|
|
|
onNodeDrop: function(node, dragZone, e, data) {
|
|
if (this.valid) {
|
|
this.invalidateDrop();
|
|
var hd = data.header,
|
|
lastLocation = this.lastLocation,
|
|
fromCt = hd.ownerCt,
|
|
fromIdx = fromCt.items.indexOf(hd),
|
|
toCt = lastLocation.header.ownerCt,
|
|
toIdx = toCt.items.indexOf(lastLocation.header),
|
|
headerCt = this.headerCt,
|
|
groupCt,
|
|
scrollerOwner;
|
|
|
|
if (lastLocation.pos === 'after') {
|
|
toIdx++;
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && toCt.lockedCt) {
|
|
scrollerOwner = fromCt.up('[scrollerOwner]');
|
|
scrollerOwner.lock(hd, toIdx);
|
|
} else if (fromCt !== toCt && fromCt.lockableInjected && toCt.lockableInjected && fromCt.lockedCt) {
|
|
scrollerOwner = fromCt.up('[scrollerOwner]');
|
|
scrollerOwner.unlock(hd, toIdx);
|
|
} else {
|
|
|
|
|
|
if ((fromCt === toCt) && (toIdx > fromCt.items.indexOf(hd))) {
|
|
toIdx--;
|
|
}
|
|
|
|
|
|
if (fromCt !== toCt) {
|
|
fromCt.suspendLayout = true;
|
|
fromCt.remove(hd, false);
|
|
fromCt.suspendLayout = false;
|
|
}
|
|
|
|
|
|
if (fromCt.isGroupHeader) {
|
|
if (!fromCt.items.getCount()) {
|
|
groupCt = fromCt.ownerCt;
|
|
groupCt.suspendLayout = true;
|
|
groupCt.remove(fromCt, false);
|
|
fromCt.el.dom.parentNode.removeChild(fromCt.el.dom);
|
|
groupCt.suspendLayout = false;
|
|
} else {
|
|
fromCt.minWidth = fromCt.getWidth() - hd.getWidth();
|
|
fromCt.setWidth(fromCt.minWidth);
|
|
}
|
|
}
|
|
|
|
|
|
toCt.suspendLayout = true;
|
|
if (fromCt === toCt) {
|
|
toCt.move(fromIdx, toIdx);
|
|
} else {
|
|
toCt.insert(toIdx, hd);
|
|
}
|
|
toCt.suspendLayout = false;
|
|
|
|
|
|
|
|
|
|
if (toCt.isGroupHeader) {
|
|
hd.savedFlex = hd.flex;
|
|
delete hd.flex;
|
|
hd.width = hd.getWidth();
|
|
|
|
|
|
toCt.minWidth = toCt.getWidth() + hd.getWidth() - (hd.savedFlex ? 1 : 0);
|
|
toCt.setWidth(toCt.minWidth);
|
|
} else {
|
|
if (hd.savedFlex) {
|
|
hd.flex = hd.savedFlex;
|
|
delete hd.width;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
headerCt.purgeCache();
|
|
headerCt.doLayout();
|
|
headerCt.onHeaderMoved(hd, fromIdx, toIdx);
|
|
|
|
if (!fromCt.items.getCount()) {
|
|
fromCt.destroy();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.plugin.Editing', {
|
|
alias: 'editing.editing',
|
|
|
|
requires: [
|
|
'Ext.grid.column.Column',
|
|
'Ext.util.KeyNav'
|
|
],
|
|
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
|
|
clicksToEdit: 2,
|
|
|
|
|
|
defaultFieldXType: 'textfield',
|
|
|
|
|
|
editStyle: '',
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
Ext.apply(me, config);
|
|
|
|
me.addEvents(
|
|
|
|
'beforeedit',
|
|
|
|
|
|
'edit',
|
|
|
|
|
|
'validateedit'
|
|
);
|
|
me.mixins.observable.constructor.call(me);
|
|
|
|
me.relayEvents(me, ['afteredit'], 'after');
|
|
},
|
|
|
|
|
|
init: function(grid) {
|
|
var me = this;
|
|
|
|
me.grid = grid;
|
|
me.view = grid.view;
|
|
me.initEvents();
|
|
me.mon(grid, 'reconfigure', me.onReconfigure, me);
|
|
me.onReconfigure();
|
|
|
|
grid.relayEvents(me, ['beforeedit', 'edit', 'validateedit']);
|
|
|
|
|
|
grid.isEditable = true;
|
|
grid.editingPlugin = grid.view.editingPlugin = me;
|
|
},
|
|
|
|
|
|
onReconfigure: function(){
|
|
this.initFieldAccessors(this.view.getGridColumns());
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
var me = this,
|
|
grid = me.grid,
|
|
headerCt = grid.headerCt,
|
|
events = grid.events;
|
|
|
|
Ext.destroy(me.keyNav);
|
|
me.removeFieldAccessors(grid.getView().getGridColumns());
|
|
|
|
|
|
me.clearListeners();
|
|
|
|
delete me.grid.editingPlugin;
|
|
delete me.grid.view.editingPlugin;
|
|
delete me.grid;
|
|
delete me.view;
|
|
delete me.editor;
|
|
delete me.keyNav;
|
|
},
|
|
|
|
|
|
getEditStyle: function() {
|
|
return this.editStyle;
|
|
},
|
|
|
|
|
|
initFieldAccessors: function(column) {
|
|
var me = this;
|
|
|
|
if (Ext.isArray(column)) {
|
|
Ext.Array.forEach(column, me.initFieldAccessors, me);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
Ext.applyIf(column, {
|
|
getEditor: function(record, defaultField) {
|
|
return me.getColumnField(this, defaultField);
|
|
},
|
|
|
|
setEditor: function(field) {
|
|
me.setColumnField(this, field);
|
|
}
|
|
});
|
|
},
|
|
|
|
|
|
removeFieldAccessors: function(column) {
|
|
var me = this;
|
|
|
|
if (Ext.isArray(column)) {
|
|
Ext.Array.forEach(column, me.removeFieldAccessors, me);
|
|
return;
|
|
}
|
|
|
|
delete column.getEditor;
|
|
delete column.setEditor;
|
|
},
|
|
|
|
|
|
|
|
getColumnField: function(columnHeader, defaultField) {
|
|
var field = columnHeader.field;
|
|
|
|
if (!field && columnHeader.editor) {
|
|
field = columnHeader.editor;
|
|
delete columnHeader.editor;
|
|
}
|
|
|
|
if (!field && defaultField) {
|
|
field = defaultField;
|
|
}
|
|
|
|
if (field) {
|
|
if (Ext.isString(field)) {
|
|
field = { xtype: field };
|
|
}
|
|
if (Ext.isObject(field) && !field.isFormField) {
|
|
field = Ext.ComponentManager.create(field, this.defaultFieldXType);
|
|
columnHeader.field = field;
|
|
}
|
|
|
|
Ext.apply(field, {
|
|
name: columnHeader.dataIndex
|
|
});
|
|
|
|
return field;
|
|
}
|
|
},
|
|
|
|
|
|
|
|
setColumnField: function(column, field) {
|
|
if (Ext.isObject(field) && !field.isFormField) {
|
|
field = Ext.ComponentManager.create(field, this.defaultFieldXType);
|
|
}
|
|
column.field = field;
|
|
},
|
|
|
|
|
|
initEvents: function() {
|
|
var me = this;
|
|
me.initEditTriggers();
|
|
me.initCancelTriggers();
|
|
},
|
|
|
|
|
|
initCancelTriggers: Ext.emptyFn,
|
|
|
|
|
|
initEditTriggers: function() {
|
|
var me = this,
|
|
view = me.view,
|
|
clickEvent = me.clicksToEdit === 1 ? 'click' : 'dblclick';
|
|
|
|
|
|
me.mon(view, 'cell' + clickEvent, me.startEditByClick, me);
|
|
view.on('render', function() {
|
|
me.keyNav = Ext.create('Ext.util.KeyNav', view.el, {
|
|
enter: me.onEnterKey,
|
|
esc: me.onEscKey,
|
|
scope: me
|
|
});
|
|
}, me, { single: true });
|
|
},
|
|
|
|
|
|
onEnterKey: function(e) {
|
|
var me = this,
|
|
grid = me.grid,
|
|
selModel = grid.getSelectionModel(),
|
|
record,
|
|
columnHeader = grid.headerCt.getHeaderAtIndex(0);
|
|
|
|
|
|
|
|
if (selModel.getCurrentPosition) {
|
|
pos = selModel.getCurrentPosition();
|
|
record = grid.store.getAt(pos.row);
|
|
columnHeader = grid.headerCt.getHeaderAtIndex(pos.column);
|
|
}
|
|
|
|
else {
|
|
record = selModel.getLastSelected();
|
|
}
|
|
me.startEdit(record, columnHeader);
|
|
},
|
|
|
|
|
|
onEscKey: function(e) {
|
|
this.cancelEdit();
|
|
},
|
|
|
|
|
|
startEditByClick: function(view, cell, colIdx, record, row, rowIdx, e) {
|
|
this.startEdit(record, view.getHeaderAtIndex(colIdx));
|
|
},
|
|
|
|
|
|
beforeEdit: Ext.emptyFn,
|
|
|
|
|
|
startEdit: function(record, columnHeader) {
|
|
var me = this,
|
|
context = me.getEditingContext(record, columnHeader);
|
|
|
|
if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
|
|
return false;
|
|
}
|
|
|
|
me.context = context;
|
|
me.editing = true;
|
|
},
|
|
|
|
|
|
getEditingContext: function(record, columnHeader) {
|
|
var me = this,
|
|
grid = me.grid,
|
|
store = grid.store,
|
|
rowIdx,
|
|
colIdx,
|
|
view = grid.getView(),
|
|
value;
|
|
|
|
|
|
if (Ext.isNumber(record)) {
|
|
rowIdx = record;
|
|
record = store.getAt(rowIdx);
|
|
} else {
|
|
rowIdx = store.indexOf(record);
|
|
}
|
|
if (Ext.isNumber(columnHeader)) {
|
|
colIdx = columnHeader;
|
|
columnHeader = grid.headerCt.getHeaderAtIndex(colIdx);
|
|
} else {
|
|
colIdx = columnHeader.getIndex();
|
|
}
|
|
|
|
value = record.get(columnHeader.dataIndex);
|
|
return {
|
|
grid: grid,
|
|
record: record,
|
|
field: columnHeader.dataIndex,
|
|
value: value,
|
|
row: view.getNode(rowIdx),
|
|
column: columnHeader,
|
|
rowIdx: rowIdx,
|
|
colIdx: colIdx
|
|
};
|
|
},
|
|
|
|
|
|
cancelEdit: function() {
|
|
this.editing = false;
|
|
},
|
|
|
|
|
|
completeEdit: function() {
|
|
var me = this;
|
|
|
|
if (me.editing && me.validateEdit()) {
|
|
me.fireEvent('edit', me.context);
|
|
}
|
|
|
|
delete me.context;
|
|
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',
|
|
requires: ['Ext.grid.CellEditor', 'Ext.util.DelayedTask'],
|
|
|
|
constructor: function() {
|
|
|
|
|
|
|
|
this.callParent(arguments);
|
|
this.editors = Ext.create('Ext.util.MixedCollection', false, function(editor) {
|
|
return editor.editorId;
|
|
});
|
|
this.editTask = Ext.create('Ext.util.DelayedTask');
|
|
},
|
|
|
|
onReconfigure: function(){
|
|
this.editors.clear();
|
|
this.callParent();
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
var me = this;
|
|
me.editTask.cancel();
|
|
me.editors.each(Ext.destroy, Ext);
|
|
me.editors.clear();
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
onBodyScroll: function() {
|
|
var ed = this.getActiveEditor();
|
|
if (ed && ed.field) {
|
|
if (ed.field.triggerBlur) {
|
|
ed.field.triggerBlur();
|
|
} else {
|
|
ed.field.blur();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
|
|
initCancelTriggers: function() {
|
|
var me = this,
|
|
grid = me.grid,
|
|
view = grid.view;
|
|
|
|
view.addElListener('mousewheel', me.cancelEdit, me);
|
|
me.mon(view, 'bodyscroll', me.onBodyScroll, me);
|
|
me.mon(grid, {
|
|
columnresize: me.cancelEdit,
|
|
columnmove: me.cancelEdit,
|
|
scope: me
|
|
});
|
|
},
|
|
|
|
|
|
startEdit: function(record, columnHeader) {
|
|
var me = this,
|
|
value = record.get(columnHeader.dataIndex),
|
|
context = me.getEditingContext(record, columnHeader),
|
|
ed;
|
|
|
|
record = context.record;
|
|
columnHeader = context.column;
|
|
|
|
|
|
|
|
me.completeEdit();
|
|
|
|
context.originalValue = context.value = value;
|
|
if (me.beforeEdit(context) === false || me.fireEvent('beforeedit', context) === false || context.cancel) {
|
|
return false;
|
|
}
|
|
|
|
|
|
if (columnHeader && !columnHeader.getEditor(record)) {
|
|
return false;
|
|
}
|
|
|
|
ed = me.getEditor(record, columnHeader);
|
|
if (ed) {
|
|
me.context = context;
|
|
me.setActiveEditor(ed);
|
|
me.setActiveRecord(record);
|
|
me.setActiveColumn(columnHeader);
|
|
|
|
|
|
me.editTask.delay(15, ed.startEdit, ed, [me.getCell(record, columnHeader), value]);
|
|
} else {
|
|
|
|
|
|
|
|
|
|
me.grid.getView().getEl(columnHeader).focus((Ext.isWebKit || Ext.isIE) ? 10 : false);
|
|
}
|
|
},
|
|
|
|
completeEdit: function() {
|
|
var activeEd = this.getActiveEditor();
|
|
if (activeEd) {
|
|
activeEd.completeEdit();
|
|
}
|
|
},
|
|
|
|
|
|
setActiveEditor: function(ed) {
|
|
this.activeEditor = ed;
|
|
},
|
|
|
|
getActiveEditor: function() {
|
|
return this.activeEditor;
|
|
},
|
|
|
|
setActiveColumn: function(column) {
|
|
this.activeColumn = column;
|
|
},
|
|
|
|
getActiveColumn: function() {
|
|
return this.activeColumn;
|
|
},
|
|
|
|
setActiveRecord: function(record) {
|
|
this.activeRecord = record;
|
|
},
|
|
|
|
getActiveRecord: function() {
|
|
return this.activeRecord;
|
|
},
|
|
|
|
getEditor: function(record, column) {
|
|
var me = this,
|
|
editors = me.editors,
|
|
editorId = column.getItemId(),
|
|
editor = editors.getByKey(editorId);
|
|
|
|
if (editor) {
|
|
return editor;
|
|
} else {
|
|
editor = column.getEditor(record);
|
|
if (!editor) {
|
|
return false;
|
|
}
|
|
|
|
|
|
if (!(editor instanceof Ext.grid.CellEditor)) {
|
|
editor = Ext.create('Ext.grid.CellEditor', {
|
|
editorId: editorId,
|
|
field: editor
|
|
});
|
|
}
|
|
editor.parentEl = me.grid.getEditorParent();
|
|
|
|
editor.on({
|
|
scope: me,
|
|
specialkey: me.onSpecialKey,
|
|
complete: me.onEditComplete,
|
|
canceledit: me.cancelEdit
|
|
});
|
|
editors.add(editor);
|
|
return editor;
|
|
}
|
|
},
|
|
|
|
|
|
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 grid = this.grid,
|
|
sm;
|
|
if (e.getKey() === e.TAB) {
|
|
e.stopEvent();
|
|
sm = grid.getSelectionModel();
|
|
if (sm.onEditorTab) {
|
|
sm.onEditorTab(this, e);
|
|
}
|
|
}
|
|
},
|
|
|
|
onEditComplete : function(ed, value, startValue) {
|
|
var me = this,
|
|
grid = me.grid,
|
|
sm = grid.getSelectionModel(),
|
|
activeColumn = me.getActiveColumn(),
|
|
dataIndex;
|
|
|
|
if (activeColumn) {
|
|
dataIndex = activeColumn.dataIndex;
|
|
|
|
me.setActiveEditor(null);
|
|
me.setActiveColumn(null);
|
|
me.setActiveRecord(null);
|
|
delete sm.wasEditing;
|
|
|
|
if (!me.validateEdit()) {
|
|
return;
|
|
}
|
|
|
|
|
|
if (value !== startValue) {
|
|
me.context.record.set(dataIndex, value);
|
|
|
|
} else {
|
|
grid.getView().getEl(activeColumn).focus();
|
|
}
|
|
me.context.value = value;
|
|
me.fireEvent('edit', me, me.context);
|
|
}
|
|
},
|
|
|
|
|
|
cancelEdit: function() {
|
|
var me = this,
|
|
activeEd = me.getActiveEditor(),
|
|
viewEl = me.grid.getView().getEl(me.getActiveColumn());
|
|
|
|
me.setActiveEditor(null);
|
|
me.setActiveColumn(null);
|
|
me.setActiveRecord(null);
|
|
if (activeEd) {
|
|
activeEd.cancelEdit();
|
|
viewEl.focus();
|
|
}
|
|
},
|
|
|
|
|
|
startEditByPosition: function(position) {
|
|
var me = this,
|
|
grid = me.grid,
|
|
sm = grid.getSelectionModel(),
|
|
editRecord = grid.store.getAt(position.row),
|
|
editColumnHeader = grid.headerCt.getHeaderAtIndex(position.column);
|
|
|
|
if (sm.selectByPosition) {
|
|
sm.selectByPosition(position);
|
|
}
|
|
me.startEdit(editRecord, editColumnHeader);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.plugin.DragDrop', {
|
|
extend: 'Ext.AbstractPlugin',
|
|
alias: 'plugin.gridviewdragdrop',
|
|
|
|
uses: [
|
|
'Ext.view.DragZone',
|
|
'Ext.grid.ViewDropZone'
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
dragText : '{0} selected row{1}',
|
|
|
|
|
|
ddGroup : "GridDD",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
enableDrop: true,
|
|
|
|
|
|
enableDrag: true,
|
|
|
|
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;
|
|
|
|
if (me.enableDrag) {
|
|
me.dragZone = Ext.create('Ext.view.DragZone', {
|
|
view: view,
|
|
ddGroup: me.dragGroup || me.ddGroup,
|
|
dragText: me.dragText
|
|
});
|
|
}
|
|
|
|
if (me.enableDrop) {
|
|
me.dropZone = Ext.create('Ext.grid.ViewDropZone', {
|
|
view: view,
|
|
ddGroup: me.dropGroup || me.ddGroup
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.plugin.HeaderReorderer', {
|
|
extend: 'Ext.util.Observable',
|
|
requires: ['Ext.grid.header.DragZone', 'Ext.grid.header.DropZone'],
|
|
alias: 'plugin.gridheaderreorderer',
|
|
|
|
init: function(headerCt) {
|
|
this.headerCt = headerCt;
|
|
headerCt.on('render', this.onHeaderCtRender, this);
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
Ext.destroy(this.dragZone, this.dropZone);
|
|
},
|
|
|
|
onHeaderCtRender: function() {
|
|
this.dragZone = Ext.create('Ext.grid.header.DragZone', this.headerCt);
|
|
this.dropZone = Ext.create('Ext.grid.header.DropZone', this.headerCt);
|
|
if (this.disabled) {
|
|
this.dragZone.disable();
|
|
}
|
|
},
|
|
|
|
enable: function() {
|
|
this.disabled = false;
|
|
if (this.dragZone) {
|
|
this.dragZone.enable();
|
|
}
|
|
},
|
|
|
|
disable: function() {
|
|
this.disabled = true;
|
|
if (this.dragZone) {
|
|
this.dragZone.disable();
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.plugin.HeaderResizer', {
|
|
extend: 'Ext.util.Observable',
|
|
requires: ['Ext.dd.DragTracker', 'Ext.util.Region'],
|
|
alias: 'plugin.gridheaderresizer',
|
|
|
|
disabled: false,
|
|
|
|
|
|
configs: {
|
|
dynamic: true
|
|
},
|
|
|
|
colHeaderCls: Ext.baseCSSPrefix + 'column-header',
|
|
|
|
minColWidth: 40,
|
|
maxColWidth: 1000,
|
|
wResizeCursor: 'col-resize',
|
|
eResizeCursor: 'col-resize',
|
|
|
|
|
|
|
|
|
|
|
|
init: function(headerCt) {
|
|
this.headerCt = headerCt;
|
|
headerCt.on('render', this.afterHeaderRender, this, {single: true});
|
|
},
|
|
|
|
|
|
destroy: function() {
|
|
if (this.tracker) {
|
|
this.tracker.destroy();
|
|
}
|
|
},
|
|
|
|
afterHeaderRender: function() {
|
|
var headerCt = this.headerCt,
|
|
el = headerCt.el;
|
|
|
|
headerCt.mon(el, 'mousemove', this.onHeaderCtMouseMove, this);
|
|
|
|
this.tracker = Ext.create('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
|
|
});
|
|
},
|
|
|
|
|
|
|
|
|
|
onHeaderCtMouseMove: function(e, t) {
|
|
if (this.headerCt.dragging) {
|
|
if (this.activeHd) {
|
|
this.activeHd.el.dom.style.cursor = '';
|
|
delete this.activeHd;
|
|
}
|
|
} else {
|
|
var headerEl = e.getTarget('.' + this.colHeaderCls, 3, true),
|
|
overHeader, resizeHeader;
|
|
|
|
if (headerEl){
|
|
overHeader = Ext.getCmp(headerEl.id);
|
|
|
|
|
|
if (overHeader.isOnLeftEdge(e)) {
|
|
resizeHeader = overHeader.previousNode('gridcolumn:not([hidden])');
|
|
|
|
}
|
|
|
|
else if (overHeader.isOnRightEdge(e)) {
|
|
resizeHeader = overHeader;
|
|
}
|
|
|
|
else {
|
|
resizeHeader = null;
|
|
}
|
|
|
|
|
|
if (resizeHeader) {
|
|
|
|
|
|
|
|
if (resizeHeader.isGroupHeader) {
|
|
resizeHeader = resizeHeader.down(':not([isGroupHeader]):not([hidden]):last');
|
|
}
|
|
|
|
|
|
|
|
if (resizeHeader && !(resizeHeader.fixed || (resizeHeader.resizable === false) || this.disabled)) {
|
|
this.activeHd = resizeHeader;
|
|
overHeader.el.dom.style.cursor = this.eResizeCursor;
|
|
}
|
|
|
|
} else {
|
|
overHeader.el.dom.style.cursor = '';
|
|
delete this.activeHd;
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onBeforeStart : function(e){
|
|
var t = e.getTarget();
|
|
|
|
this.dragHd = this.activeHd;
|
|
|
|
if (!!this.dragHd && !Ext.fly(t).hasCls('x-column-header-trigger') && !this.headerCt.dragging) {
|
|
|
|
this.tracker.constrainTo = this.getConstrainRegion();
|
|
return true;
|
|
} else {
|
|
this.headerCt.dragging = false;
|
|
return false;
|
|
}
|
|
},
|
|
|
|
|
|
getConstrainRegion: function() {
|
|
var dragHdEl = this.dragHd.el,
|
|
region = Ext.util.Region.getRegion(dragHdEl);
|
|
|
|
return region.adjust(
|
|
0,
|
|
this.maxColWidth - dragHdEl.getWidth(),
|
|
0,
|
|
this.minColWidth
|
|
);
|
|
},
|
|
|
|
|
|
|
|
onStart: function(e){
|
|
var me = this,
|
|
dragHd = me.dragHd,
|
|
dragHdEl = dragHd.el,
|
|
width = dragHdEl.getWidth(),
|
|
headerCt = me.headerCt,
|
|
t = e.getTarget();
|
|
|
|
if (me.dragHd && !Ext.fly(t).hasCls('x-column-header-trigger')) {
|
|
headerCt.dragging = true;
|
|
}
|
|
|
|
me.origWidth = width;
|
|
|
|
|
|
if (!me.dynamic) {
|
|
var xy = dragHdEl.getXY(),
|
|
gridSection = headerCt.up('[scrollerOwner]'),
|
|
dragHct = me.dragHd.up(':not([isGroupHeader])'),
|
|
firstSection = dragHct.up(),
|
|
lhsMarker = gridSection.getLhsMarker(),
|
|
rhsMarker = gridSection.getRhsMarker(),
|
|
el = rhsMarker.parent(),
|
|
offsetLeft = el.getLeft(true),
|
|
offsetTop = el.getTop(true),
|
|
topLeft = el.translatePoints(xy),
|
|
markerHeight = firstSection.body.getHeight() + headerCt.getHeight(),
|
|
top = topLeft.top - offsetTop;
|
|
|
|
lhsMarker.setTop(top);
|
|
rhsMarker.setTop(top);
|
|
lhsMarker.setHeight(markerHeight);
|
|
rhsMarker.setHeight(markerHeight);
|
|
lhsMarker.setLeft(topLeft.left - offsetLeft);
|
|
rhsMarker.setLeft(topLeft.left + width - offsetLeft);
|
|
}
|
|
},
|
|
|
|
|
|
onDrag: function(e){
|
|
if (!this.dynamic) {
|
|
var xy = this.tracker.getXY('point'),
|
|
gridSection = this.headerCt.up('[scrollerOwner]'),
|
|
rhsMarker = gridSection.getRhsMarker(),
|
|
el = rhsMarker.parent(),
|
|
topLeft = el.translatePoints(xy),
|
|
offsetLeft = el.getLeft(true);
|
|
|
|
rhsMarker.setLeft(topLeft.left - offsetLeft);
|
|
|
|
} else {
|
|
this.doResize();
|
|
}
|
|
},
|
|
|
|
onEnd: function(e){
|
|
this.headerCt.dragging = false;
|
|
if (this.dragHd) {
|
|
if (!this.dynamic) {
|
|
var dragHd = this.dragHd,
|
|
gridSection = this.headerCt.up('[scrollerOwner]'),
|
|
lhsMarker = gridSection.getLhsMarker(),
|
|
rhsMarker = gridSection.getRhsMarker(),
|
|
currWidth = dragHd.getWidth(),
|
|
offset = this.tracker.getOffset('point'),
|
|
offscreen = -9999;
|
|
|
|
|
|
lhsMarker.setLeft(offscreen);
|
|
rhsMarker.setLeft(offscreen);
|
|
}
|
|
this.doResize();
|
|
}
|
|
},
|
|
|
|
doResize: function() {
|
|
if (this.dragHd) {
|
|
var dragHd = this.dragHd,
|
|
nextHd,
|
|
offset = this.tracker.getOffset('point');
|
|
|
|
|
|
if (dragHd.flex) {
|
|
delete dragHd.flex;
|
|
}
|
|
|
|
this.headerCt.suspendLayout = true;
|
|
dragHd.setWidth(this.origWidth + offset[0], false);
|
|
|
|
|
|
|
|
|
|
|
|
if (this.headerCt.forceFit) {
|
|
nextHd = dragHd.nextNode('gridcolumn:not([hidden]):not([isGroupHeader])');
|
|
if (nextHd) {
|
|
delete nextHd.flex;
|
|
nextHd.setWidth(nextHd.getWidth() - offset[0], false);
|
|
}
|
|
}
|
|
this.headerCt.suspendLayout = false;
|
|
this.headerCt.doComponentLayout(this.headerCt.getFullWidth());
|
|
}
|
|
},
|
|
|
|
disable: function() {
|
|
this.disabled = true;
|
|
if (this.tracker) {
|
|
this.tracker.disable();
|
|
}
|
|
},
|
|
|
|
enable: function() {
|
|
this.disabled = false;
|
|
if (this.tracker) {
|
|
this.tracker.enable();
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.grid.plugin.RowEditing', {
|
|
extend: 'Ext.grid.plugin.Editing',
|
|
alias: 'plugin.rowediting',
|
|
|
|
requires: [
|
|
'Ext.grid.RowEditor'
|
|
],
|
|
|
|
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() {
|
|
var me = this;
|
|
Ext.destroy(me.editor);
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
startEdit: function(record, columnHeader) {
|
|
var me = this,
|
|
editor = me.getEditor();
|
|
|
|
if (me.callParent(arguments) === false) {
|
|
return false;
|
|
}
|
|
|
|
|
|
if (editor.beforeEdit() !== false) {
|
|
editor.startEdit(me.context.record, me.context.column);
|
|
}
|
|
},
|
|
|
|
|
|
cancelEdit: function() {
|
|
var me = this;
|
|
|
|
if (me.editing) {
|
|
me.getEditor().cancelEdit();
|
|
me.callParent(arguments);
|
|
|
|
me.fireEvent('canceledit', me.context);
|
|
}
|
|
},
|
|
|
|
|
|
completeEdit: function() {
|
|
var me = this;
|
|
|
|
if (me.editing && me.validateEdit()) {
|
|
me.editing = false;
|
|
me.fireEvent('edit', me.context);
|
|
}
|
|
},
|
|
|
|
|
|
validateEdit: function() {
|
|
var me = this,
|
|
editor = me.editor,
|
|
context = me.context,
|
|
record = context.record,
|
|
newValues = {},
|
|
originalValues = {},
|
|
name;
|
|
|
|
editor.items.each(function(item) {
|
|
name = item.name;
|
|
|
|
newValues[name] = item.getValue();
|
|
originalValues[name] = record.get(name);
|
|
});
|
|
|
|
Ext.apply(context, {
|
|
newValues : newValues,
|
|
originalValues : originalValues
|
|
});
|
|
|
|
return me.callParent(arguments) && me.getEditor().completeEdit();
|
|
},
|
|
|
|
|
|
getEditor: function() {
|
|
var me = this;
|
|
|
|
if (!me.editor) {
|
|
me.editor = me.initEditor();
|
|
}
|
|
return me.editor;
|
|
},
|
|
|
|
|
|
initEditor: function() {
|
|
var me = this,
|
|
grid = me.grid,
|
|
view = me.view,
|
|
headerCt = grid.headerCt;
|
|
|
|
return Ext.create('Ext.grid.RowEditor', {
|
|
autoCancel: me.autoCancel,
|
|
errorSummary: me.errorSummary,
|
|
fields: headerCt.getGridColumns(),
|
|
hidden: true,
|
|
|
|
|
|
editingPlugin: me,
|
|
renderTo: view.el
|
|
});
|
|
},
|
|
|
|
|
|
initEditTriggers: function() {
|
|
var me = this,
|
|
grid = me.grid,
|
|
view = me.view,
|
|
headerCt = grid.headerCt,
|
|
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(headerCt, {
|
|
add: me.onColumnAdd,
|
|
remove: me.onColumnRemove,
|
|
columnresize: me.onColumnResize,
|
|
columnhide: me.onColumnHide,
|
|
columnshow: me.onColumnShow,
|
|
columnmove: me.onColumnMove,
|
|
scope: me
|
|
});
|
|
}, me, { 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.startEditByClick.apply(me, arguments);
|
|
}
|
|
},
|
|
|
|
|
|
onColumnAdd: function(ct, column) {
|
|
if (column.isHeader) {
|
|
var me = this,
|
|
editor;
|
|
|
|
me.initFieldAccessors(column);
|
|
editor = me.getEditor();
|
|
|
|
if (editor && editor.onColumnAdd) {
|
|
editor.onColumnAdd(column);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onColumnRemove: function(ct, column) {
|
|
if (column.isHeader) {
|
|
var me = this,
|
|
editor = me.getEditor();
|
|
|
|
if (editor && editor.onColumnRemove) {
|
|
editor.onColumnRemove(column);
|
|
}
|
|
me.removeFieldAccessors(column);
|
|
}
|
|
},
|
|
|
|
|
|
onColumnResize: function(ct, column, width) {
|
|
if (column.isHeader) {
|
|
var me = this,
|
|
editor = me.getEditor();
|
|
|
|
if (editor && editor.onColumnResize) {
|
|
editor.onColumnResize(column, width);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onColumnHide: function(ct, column) {
|
|
|
|
var me = this,
|
|
editor = me.getEditor();
|
|
|
|
if (editor && editor.onColumnHide) {
|
|
editor.onColumnHide(column);
|
|
}
|
|
},
|
|
|
|
|
|
onColumnShow: function(ct, column) {
|
|
|
|
var me = this,
|
|
editor = me.getEditor();
|
|
|
|
if (editor && editor.onColumnShow) {
|
|
editor.onColumnShow(column);
|
|
}
|
|
},
|
|
|
|
|
|
onColumnMove: function(ct, column, fromIdx, toIdx) {
|
|
|
|
var me = this,
|
|
editor = me.getEditor();
|
|
|
|
if (editor && editor.onColumnMove) {
|
|
editor.onColumnMove(column, fromIdx, toIdx);
|
|
}
|
|
},
|
|
|
|
|
|
setColumnField: function(column, field) {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
me.getEditor().setField(column.field, column);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.grid.property.Grid', {
|
|
|
|
extend: 'Ext.grid.Panel',
|
|
|
|
alias: 'widget.propertygrid',
|
|
|
|
alternateClassName: 'Ext.grid.PropertyGrid',
|
|
|
|
uses: [
|
|
'Ext.grid.plugin.CellEditing',
|
|
'Ext.grid.property.Store',
|
|
'Ext.grid.property.HeaderContainer',
|
|
'Ext.XTemplate',
|
|
'Ext.grid.CellEditor',
|
|
'Ext.form.field.Date',
|
|
'Ext.form.field.Text',
|
|
'Ext.form.field.Number'
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
valueField: 'value',
|
|
|
|
|
|
nameField: 'name',
|
|
|
|
|
|
|
|
|
|
enableColumnMove: false,
|
|
columnLines: true,
|
|
stripeRows: false,
|
|
trackMouseOver: false,
|
|
clicksToEdit: 1,
|
|
enableHdMenu: false,
|
|
|
|
|
|
initComponent : function(){
|
|
var me = this;
|
|
|
|
me.addCls(Ext.baseCSSPrefix + 'property-grid');
|
|
me.plugins = me.plugins || [];
|
|
|
|
|
|
me.plugins.push(Ext.create('Ext.grid.plugin.CellEditing', {
|
|
clicksToEdit: me.clicksToEdit,
|
|
|
|
|
|
startEdit: function(record, column) {
|
|
|
|
return this.self.prototype.startEdit.call(this, record, me.headerCt.child('#' + me.valueField));
|
|
}
|
|
}));
|
|
|
|
me.selModel = {
|
|
selType: 'cellmodel',
|
|
onCellSelect: function(position) {
|
|
if (position.column != 1) {
|
|
position.column = 1;
|
|
}
|
|
return this.self.prototype.onCellSelect.call(this, position);
|
|
}
|
|
};
|
|
me.customRenderers = me.customRenderers || {};
|
|
me.customEditors = me.customEditors || {};
|
|
|
|
|
|
if (!me.store) {
|
|
me.propStore = me.store = Ext.create('Ext.grid.property.Store', me, me.source);
|
|
}
|
|
|
|
me.store.sort('name', 'ASC');
|
|
me.columns = Ext.create('Ext.grid.property.HeaderContainer', me, me.store);
|
|
|
|
me.addEvents(
|
|
|
|
'beforepropertychange',
|
|
|
|
'propertychange'
|
|
);
|
|
me.callParent();
|
|
|
|
|
|
me.getView().walkCells = this.walkCells;
|
|
|
|
|
|
me.editors = {
|
|
'date' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Date', {selectOnFocus: true})}),
|
|
'string' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Text', {selectOnFocus: true})}),
|
|
'number' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.Number', {selectOnFocus: true})}),
|
|
'boolean' : Ext.create('Ext.grid.CellEditor', { field: Ext.create('Ext.form.field.ComboBox', {
|
|
editable: false,
|
|
store: [[ true, me.headerCt.trueText ], [false, me.headerCt.falseText ]]
|
|
})})
|
|
};
|
|
|
|
|
|
me.store.on('update', me.onUpdate, me);
|
|
},
|
|
|
|
|
|
onUpdate : function(store, record, operation) {
|
|
var me = this,
|
|
v, oldValue;
|
|
|
|
if (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) {
|
|
if (direction == 'left') {
|
|
direction = 'up';
|
|
} else if (direction == 'right') {
|
|
direction = 'down';
|
|
}
|
|
pos = Ext.view.Table.prototype.walkCells.call(this, pos, direction, e, preventWrap, verifierFn, scope);
|
|
if (!pos.column) {
|
|
pos.column = 1;
|
|
}
|
|
return pos;
|
|
},
|
|
|
|
|
|
|
|
getCellEditor : function(record, column) {
|
|
var me = this,
|
|
propName = record.get(me.nameField),
|
|
val = record.get(me.valueField),
|
|
editor = me.customEditors[propName];
|
|
|
|
|
|
|
|
if (editor) {
|
|
if (!(editor instanceof Ext.grid.CellEditor)) {
|
|
if (!(editor instanceof Ext.form.field.Base)) {
|
|
editor = Ext.ComponentManager.create(editor, 'textfield');
|
|
}
|
|
editor = me.customEditors[propName] = Ext.create('Ext.grid.CellEditor', { field: editor });
|
|
}
|
|
} else if (Ext.isDate(val)) {
|
|
editor = me.editors.date;
|
|
} else if (Ext.isNumber(val)) {
|
|
editor = me.editors.number;
|
|
} else if (Ext.isBoolean(val)) {
|
|
editor = me.editors['boolean'];
|
|
} else {
|
|
editor = me.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) {
|
|
this.source = source;
|
|
this.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',
|
|
|
|
|
|
constructor : function(grid, store) {
|
|
var me = this;
|
|
|
|
me.grid = grid;
|
|
me.store = store;
|
|
me.callParent([{
|
|
items: [{
|
|
header: me.nameText,
|
|
width: grid.nameColumnWidth || me.nameWidth,
|
|
sortable: true,
|
|
dataIndex: grid.nameField,
|
|
renderer: Ext.Function.bind(me.renderProp, me),
|
|
itemId: grid.nameField,
|
|
menuDisabled :true,
|
|
tdCls: me.nameColumnCls
|
|
}, {
|
|
header: me.valueText,
|
|
renderer: Ext.Function.bind(me.renderCell, me),
|
|
getEditor: Ext.Function.bind(me.getCellEditor, me),
|
|
flex: 1,
|
|
fixed: true,
|
|
dataIndex: grid.valueField,
|
|
itemId: grid.valueField,
|
|
menuDisabled: true
|
|
}]
|
|
}]);
|
|
},
|
|
|
|
getCellEditor: function(record){
|
|
return this.grid.getCellEditor(record, this);
|
|
},
|
|
|
|
|
|
|
|
renderProp : function(v) {
|
|
return this.getPropertyName(v);
|
|
},
|
|
|
|
|
|
|
|
renderCell : function(val, meta, rec) {
|
|
var me = this,
|
|
renderer = me.grid.customRenderers[rec.get(me.grid.nameField)],
|
|
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) {
|
|
var pn = this.grid.propertyNames;
|
|
return pn && pn[name] ? pn[name] : 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',
|
|
|
|
uses: ['Ext.data.reader.Reader', 'Ext.data.proxy.Proxy', 'Ext.data.ResultSet', 'Ext.grid.property.Property'],
|
|
|
|
|
|
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 = Ext.create('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 = Ext.create('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 Ext.create('Ext.data.ResultSet', result);
|
|
},
|
|
|
|
|
|
isEditableValue: function(val){
|
|
return Ext.isPrimitive(val) || Ext.isDate(val);
|
|
}
|
|
});
|
|
}
|
|
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);
|
|
},
|
|
|
|
|
|
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.component.Body', {
|
|
|
|
|
|
|
|
alias: ['layout.body'],
|
|
|
|
extend: 'Ext.layout.component.Component',
|
|
|
|
uses: ['Ext.layout.container.Container'],
|
|
|
|
|
|
|
|
type: 'body',
|
|
|
|
onLayout: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner;
|
|
|
|
|
|
me.setTargetSize(width, height);
|
|
|
|
|
|
me.setBodySize.apply(me, arguments);
|
|
|
|
|
|
if (owner && owner.layout && owner.layout.isLayout) {
|
|
if (!Ext.isNumber(owner.height) || !Ext.isNumber(owner.width)) {
|
|
owner.layout.bindToOwnerCtComponent = true;
|
|
}
|
|
else {
|
|
owner.layout.bindToOwnerCtComponent = false;
|
|
}
|
|
}
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
setBodySize: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
frameSize = owner.frameSize,
|
|
isNumber = Ext.isNumber;
|
|
|
|
if (isNumber(width)) {
|
|
width -= owner.el.getFrameWidth('lr') - frameSize.left - frameSize.right;
|
|
}
|
|
if (isNumber(height)) {
|
|
height -= owner.el.getFrameWidth('tb') - frameSize.top - frameSize.bottom;
|
|
}
|
|
|
|
me.setElementSize(owner.body, width, height);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.layout.component.FieldSet', {
|
|
extend: 'Ext.layout.component.Body',
|
|
alias: ['layout.fieldset'],
|
|
|
|
type: 'fieldset',
|
|
|
|
doContainerLayout: function() {
|
|
|
|
if (!this.owner.collapsed) {
|
|
this.callParent();
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.layout.component.Tab', {
|
|
|
|
alias: ['layout.tab'],
|
|
|
|
extend: 'Ext.layout.component.Button',
|
|
|
|
|
|
|
|
beforeLayout: function() {
|
|
var me = this, dirty = me.lastClosable !== me.owner.closable;
|
|
|
|
if (dirty) {
|
|
delete me.adjWidth;
|
|
}
|
|
|
|
return this.callParent(arguments) || dirty;
|
|
},
|
|
|
|
onLayout: function () {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
me.lastClosable = me.owner.closable;
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.component.field.File', {
|
|
alias: ['layout.filefield'],
|
|
extend: 'Ext.layout.component.field.Field',
|
|
|
|
type: 'filefield',
|
|
|
|
sizeBodyContents: function(width, height) {
|
|
var me = this,
|
|
owner = me.owner;
|
|
|
|
if (!owner.buttonOnly) {
|
|
|
|
|
|
me.setElementSize(owner.inputEl, Ext.isNumber(width) ? width - owner.button.getWidth() - owner.buttonMargin : width);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.component.field.Slider', {
|
|
|
|
|
|
|
|
alias: ['layout.sliderfield'],
|
|
|
|
extend: 'Ext.layout.component.field.Field',
|
|
|
|
|
|
|
|
type: 'sliderfield',
|
|
|
|
sizeBodyContents: function(width, height) {
|
|
var owner = this.owner,
|
|
thumbs = owner.thumbs,
|
|
length = thumbs.length,
|
|
inputEl = owner.inputEl,
|
|
innerEl = owner.innerEl,
|
|
endEl = owner.endEl,
|
|
i = 0;
|
|
|
|
|
|
for(; i < length; ++i) {
|
|
thumbs[i].el.stopAnimation();
|
|
}
|
|
|
|
if (owner.vertical) {
|
|
inputEl.setHeight(height);
|
|
innerEl.setHeight(Ext.isNumber(height) ? height - inputEl.getPadding('t') - endEl.getPadding('b') : height);
|
|
}
|
|
else {
|
|
inputEl.setWidth(width);
|
|
innerEl.setWidth(Ext.isNumber(width) ? width - inputEl.getPadding('l') - endEl.getPadding('r') : width);
|
|
}
|
|
owner.syncThumbs();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.container.Absolute', {
|
|
|
|
|
|
|
|
alias: 'layout.absolute',
|
|
extend: 'Ext.layout.container.Anchor',
|
|
alternateClassName: 'Ext.layout.AbsoluteLayout',
|
|
|
|
|
|
|
|
itemCls: Ext.baseCSSPrefix + 'abs-layout-item',
|
|
|
|
type: 'absolute',
|
|
|
|
onLayout: function() {
|
|
var me = this,
|
|
target = me.getTarget(),
|
|
targetIsBody = target.dom === document.body;
|
|
|
|
|
|
if (!targetIsBody) {
|
|
target.position();
|
|
}
|
|
me.paddingLeft = target.getPadding('l');
|
|
me.paddingTop = target.getPadding('t');
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
adjustWidthAnchor: function(value, comp) {
|
|
|
|
return value ? value - comp.getPosition(true)[0] : value;
|
|
},
|
|
|
|
|
|
adjustHeightAnchor: function(value, comp) {
|
|
|
|
return value ? value - comp.getPosition(true)[1] : value;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.layout.container.Accordion', {
|
|
extend: 'Ext.layout.container.VBox',
|
|
alias: ['layout.accordion'],
|
|
alternateClassName: 'Ext.layout.AccordionLayout',
|
|
|
|
itemCls: Ext.baseCSSPrefix + 'box-item ' + Ext.baseCSSPrefix + 'accordion-item',
|
|
|
|
align: 'stretch',
|
|
|
|
|
|
fill : true,
|
|
|
|
|
|
autoWidth : true,
|
|
|
|
|
|
titleCollapse : true,
|
|
|
|
|
|
hideCollapseTool : false,
|
|
|
|
|
|
collapseFirst : false,
|
|
|
|
|
|
animate : true,
|
|
|
|
activeOnTop : false,
|
|
|
|
multi: false,
|
|
|
|
constructor: function() {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
me.initialAnimate = me.animate;
|
|
me.animate = false;
|
|
|
|
|
|
if (me.fill === false) {
|
|
me.itemCls = Ext.baseCSSPrefix + 'accordion-item';
|
|
}
|
|
},
|
|
|
|
|
|
|
|
beforeLayout: function() {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
if (me.fill) {
|
|
if (!(me.owner.el.dom.style.height || me.getLayoutTargetSize().height)) {
|
|
return false;
|
|
}
|
|
} else {
|
|
me.owner.componentLayout.monitorChildren = false;
|
|
me.autoSize = true;
|
|
me.owner.setAutoScroll(true);
|
|
}
|
|
},
|
|
|
|
renderItems : function(items, target) {
|
|
var me = this,
|
|
ln = items.length,
|
|
i = 0,
|
|
comp,
|
|
targetSize = me.getLayoutTargetSize(),
|
|
renderedPanels = [];
|
|
|
|
for (; i < ln; i++) {
|
|
comp = items[i];
|
|
if (!comp.rendered) {
|
|
renderedPanels.push(comp);
|
|
|
|
|
|
if (me.collapseFirst) {
|
|
comp.collapseFirst = me.collapseFirst;
|
|
}
|
|
if (me.hideCollapseTool) {
|
|
comp.hideCollapseTool = me.hideCollapseTool;
|
|
comp.titleCollapse = true;
|
|
}
|
|
else if (me.titleCollapse) {
|
|
comp.titleCollapse = me.titleCollapse;
|
|
}
|
|
|
|
delete comp.hideHeader;
|
|
comp.collapsible = true;
|
|
comp.title = comp.title || ' ';
|
|
|
|
|
|
comp.width = targetSize.width;
|
|
if (me.fill) {
|
|
delete comp.height;
|
|
delete comp.flex;
|
|
|
|
|
|
if (me.expandedItem !== undefined) {
|
|
comp.collapsed = true;
|
|
}
|
|
|
|
else if (comp.hasOwnProperty('collapsed') && comp.collapsed === false) {
|
|
comp.flex = 1;
|
|
me.expandedItem = i;
|
|
} else {
|
|
comp.collapsed = true;
|
|
}
|
|
|
|
me.owner.mon(comp, {
|
|
show: me.onComponentShow,
|
|
beforeexpand: me.onComponentExpand,
|
|
beforecollapse: me.onComponentCollapse,
|
|
scope: me
|
|
});
|
|
} else {
|
|
delete comp.flex;
|
|
comp.animCollapse = me.initialAnimate;
|
|
comp.autoHeight = true;
|
|
comp.autoScroll = false;
|
|
}
|
|
comp.border = comp.collapsed;
|
|
}
|
|
}
|
|
|
|
|
|
if (ln && me.expandedItem === undefined) {
|
|
me.expandedItem = 0;
|
|
comp = items[0];
|
|
comp.collapsed = comp.border = false;
|
|
if (me.fill) {
|
|
comp.flex = 1;
|
|
}
|
|
}
|
|
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
ln = renderedPanels.length;
|
|
for (i = 0; i < ln; i++) {
|
|
comp = renderedPanels[i];
|
|
|
|
|
|
delete comp.width;
|
|
|
|
comp.header.addCls(Ext.baseCSSPrefix + 'accordion-hd');
|
|
comp.body.addCls(Ext.baseCSSPrefix + 'accordion-body');
|
|
}
|
|
},
|
|
|
|
onLayout: function() {
|
|
var me = this;
|
|
|
|
|
|
if (me.fill) {
|
|
me.callParent(arguments);
|
|
} else {
|
|
var targetSize = me.getLayoutTargetSize(),
|
|
items = me.getVisibleItems(),
|
|
len = items.length,
|
|
i = 0, comp;
|
|
|
|
for (; i < len; i++) {
|
|
comp = items[i];
|
|
if (comp.collapsed) {
|
|
items[i].setWidth(targetSize.width);
|
|
} else {
|
|
items[i].setSize(null, null);
|
|
}
|
|
}
|
|
}
|
|
me.updatePanelClasses();
|
|
|
|
return me;
|
|
},
|
|
|
|
updatePanelClasses: function() {
|
|
var children = this.getLayoutItems(),
|
|
ln = children.length,
|
|
siblingCollapsed = true,
|
|
i, child;
|
|
|
|
for (i = 0; i < ln; i++) {
|
|
child = children[i];
|
|
|
|
|
|
|
|
if (Ext.isWindows) {
|
|
child.el.dom.scrollTop = 0;
|
|
}
|
|
|
|
if (siblingCollapsed) {
|
|
child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
|
|
}
|
|
else {
|
|
child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-sibling-expanded');
|
|
}
|
|
|
|
if (i + 1 == ln && child.collapsed) {
|
|
child.header.addCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
|
|
}
|
|
else {
|
|
child.header.removeCls(Ext.baseCSSPrefix + 'accordion-hd-last-collapsed');
|
|
}
|
|
siblingCollapsed = child.collapsed;
|
|
}
|
|
},
|
|
|
|
animCallback: function(){
|
|
Ext.Array.forEach(this.toCollapse, function(comp){
|
|
comp.fireEvent('collapse', comp);
|
|
});
|
|
|
|
Ext.Array.forEach(this.toExpand, function(comp){
|
|
comp.fireEvent('expand', comp);
|
|
});
|
|
},
|
|
|
|
setupEvents: function(){
|
|
this.toCollapse = [];
|
|
this.toExpand = [];
|
|
},
|
|
|
|
|
|
|
|
|
|
onComponentExpand: function(toExpand) {
|
|
var me = this,
|
|
it = me.owner.items.items,
|
|
len = it.length,
|
|
i = 0,
|
|
comp;
|
|
|
|
me.setupEvents();
|
|
for (; i < len; i++) {
|
|
comp = it[i];
|
|
if (comp === toExpand && comp.collapsed) {
|
|
me.setExpanded(comp);
|
|
} else if (!me.multi && (comp.rendered && comp.header.rendered && comp !== toExpand && !comp.collapsed)) {
|
|
me.setCollapsed(comp);
|
|
}
|
|
}
|
|
|
|
me.animate = me.initialAnimate;
|
|
if (me.activeOnTop) {
|
|
|
|
me.owner.insert(0, toExpand);
|
|
} else {
|
|
me.layout();
|
|
}
|
|
me.animate = false;
|
|
return false;
|
|
},
|
|
|
|
onComponentCollapse: function(comp) {
|
|
var me = this,
|
|
toExpand = comp.next() || comp.prev(),
|
|
expanded = me.multi ? me.owner.query('>panel:not([collapsed])') : [];
|
|
|
|
me.setupEvents();
|
|
|
|
|
|
if (me.multi) {
|
|
me.setCollapsed(comp);
|
|
|
|
|
|
|
|
if (expanded.length === 1 && expanded[0] === comp) {
|
|
me.setExpanded(toExpand);
|
|
}
|
|
|
|
me.animate = me.initialAnimate;
|
|
me.layout();
|
|
me.animate = false;
|
|
}
|
|
|
|
else if (toExpand) {
|
|
me.onComponentExpand(toExpand);
|
|
}
|
|
return false;
|
|
},
|
|
|
|
onComponentShow: function(comp) {
|
|
|
|
this.onComponentExpand(comp);
|
|
},
|
|
|
|
setCollapsed: function(comp) {
|
|
var otherDocks = comp.getDockedItems(),
|
|
dockItem,
|
|
len = otherDocks.length,
|
|
i = 0;
|
|
|
|
|
|
comp.hiddenDocked = [];
|
|
for (; i < len; i++) {
|
|
dockItem = otherDocks[i];
|
|
if ((dockItem !== comp.header) && !dockItem.hidden) {
|
|
dockItem.hidden = true;
|
|
comp.hiddenDocked.push(dockItem);
|
|
}
|
|
}
|
|
comp.addCls(comp.collapsedCls);
|
|
comp.header.addCls(comp.collapsedHeaderCls);
|
|
comp.height = comp.header.getHeight();
|
|
comp.el.setHeight(comp.height);
|
|
comp.collapsed = true;
|
|
delete comp.flex;
|
|
if (this.initialAnimate) {
|
|
this.toCollapse.push(comp);
|
|
} else {
|
|
comp.fireEvent('collapse', comp);
|
|
}
|
|
if (comp.collapseTool) {
|
|
comp.collapseTool.setType('expand-' + comp.getOppositeDirection(comp.collapseDirection));
|
|
}
|
|
},
|
|
|
|
setExpanded: function(comp) {
|
|
var otherDocks = comp.hiddenDocked,
|
|
len = otherDocks ? otherDocks.length : 0,
|
|
i = 0;
|
|
|
|
|
|
for (; i < len; i++) {
|
|
otherDocks[i].show();
|
|
}
|
|
|
|
|
|
if (!comp.body.isVisible()) {
|
|
comp.body.show();
|
|
}
|
|
delete comp.collapsed;
|
|
delete comp.height;
|
|
delete comp.componentLayout.lastComponentSize;
|
|
comp.suspendLayout = false;
|
|
comp.flex = 1;
|
|
comp.removeCls(comp.collapsedCls);
|
|
comp.header.removeCls(comp.collapsedHeaderCls);
|
|
if (this.initialAnimate) {
|
|
this.toExpand.push(comp);
|
|
} else {
|
|
comp.fireEvent('expand', comp);
|
|
}
|
|
if (comp.collapseTool) {
|
|
comp.collapseTool.setType('collapse-' + comp.collapseDirection);
|
|
}
|
|
comp.setAutoScroll(comp.initialConfig.autoScroll);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.resizer.Splitter', {
|
|
extend: 'Ext.Component',
|
|
requires: ['Ext.XTemplate'],
|
|
uses: ['Ext.resizer.SplitterTracker'],
|
|
alias: 'widget.splitter',
|
|
|
|
renderTpl: [
|
|
'<tpl if="collapsible===true">',
|
|
'<div id="{id}-collapseEl" class="', Ext.baseCSSPrefix, 'collapse-el ',
|
|
Ext.baseCSSPrefix, 'layout-split-{collapseDir}"> </div>',
|
|
'</tpl>'
|
|
],
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'splitter',
|
|
collapsedClsInternal: Ext.baseCSSPrefix + 'splitter-collapsed',
|
|
|
|
|
|
collapsible: false,
|
|
|
|
|
|
|
|
|
|
collapseOnDblClick: true,
|
|
|
|
|
|
defaultSplitMin: 40,
|
|
|
|
|
|
defaultSplitMax: 1000,
|
|
|
|
|
|
|
|
width: 5,
|
|
height: 5,
|
|
|
|
|
|
collapseTarget: 'next',
|
|
|
|
|
|
|
|
onRender: function() {
|
|
var me = this,
|
|
target = me.getCollapseTarget(),
|
|
collapseDir = me.getCollapseDirection();
|
|
|
|
Ext.applyIf(me.renderData, {
|
|
collapseDir: collapseDir,
|
|
collapsible: me.collapsible || target.collapsible
|
|
});
|
|
|
|
me.addChildEls('collapseEl');
|
|
|
|
this.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(target, 'collapse', me.onTargetCollapse, me);
|
|
me.mon(target, 'expand', me.onTargetExpand, me);
|
|
|
|
me.el.addCls(me.baseCls + '-' + me.orientation);
|
|
me.el.unselectable();
|
|
|
|
me.tracker = Ext.create('Ext.resizer.SplitterTracker', {
|
|
el: me.el
|
|
});
|
|
|
|
|
|
me.relayEvents(me.tracker, [ 'beforedragstart', 'dragstart', 'dragend' ]);
|
|
},
|
|
|
|
getCollapseDirection: function() {
|
|
var me = this,
|
|
idx,
|
|
type = me.ownerCt.layout.type;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (me.collapseTarget.isComponent) {
|
|
idx = Number(me.ownerCt.items.indexOf(me.collapseTarget) == me.ownerCt.items.indexOf(me) - 1) << 1 | Number(type == 'hbox');
|
|
} else {
|
|
idx = Number(me.collapseTarget == 'prev') << 1 | Number(type == 'hbox');
|
|
}
|
|
|
|
|
|
me.orientation = ['horizontal', 'vertical'][idx & 1];
|
|
return ['bottom', 'right', 'top', 'left'][idx];
|
|
},
|
|
|
|
getCollapseTarget: function() {
|
|
var me = this;
|
|
|
|
return me.collapseTarget.isComponent ? me.collapseTarget : me.collapseTarget == 'prev' ? me.previousSibling() : me.nextSibling();
|
|
},
|
|
|
|
onTargetCollapse: function(target) {
|
|
this.el.addCls([this.collapsedClsInternal, this.collapsedCls]);
|
|
},
|
|
|
|
onTargetExpand: function(target) {
|
|
this.el.removeCls([this.collapsedClsInternal, this.collapsedCls]);
|
|
},
|
|
|
|
toggleTargetCmp: function(e, t) {
|
|
var cmp = this.getCollapseTarget();
|
|
|
|
if (cmp.isVisible()) {
|
|
|
|
if (cmp.collapsed) {
|
|
cmp.expand(cmp.animCollapse);
|
|
|
|
} else {
|
|
cmp.collapse(this.renderData.collapseDir, cmp.animCollapse);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
setSize: function() {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
if (Ext.isIE) {
|
|
me.el.repaint();
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.container.Border', {
|
|
|
|
alias: ['layout.border'],
|
|
extend: 'Ext.layout.container.Container',
|
|
requires: ['Ext.resizer.Splitter', 'Ext.container.Container', 'Ext.fx.Anim'],
|
|
alternateClassName: 'Ext.layout.BorderLayout',
|
|
|
|
targetCls: Ext.baseCSSPrefix + 'border-layout-ct',
|
|
|
|
itemCls: Ext.baseCSSPrefix + 'border-item',
|
|
|
|
bindToOwnerCtContainer: true,
|
|
|
|
percentageRe: /(\d+)%/,
|
|
|
|
slideDirection: {
|
|
north: 't',
|
|
south: 'b',
|
|
west: 'l',
|
|
east: 'r'
|
|
},
|
|
|
|
constructor: function(config) {
|
|
this.initialConfig = config;
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
onLayout: function() {
|
|
var me = this;
|
|
if (!me.borderLayoutInitialized) {
|
|
me.initializeBorderLayout();
|
|
}
|
|
|
|
|
|
me.fixHeightConstraints();
|
|
me.shadowLayout.onLayout();
|
|
if (me.embeddedContainer) {
|
|
me.embeddedContainer.layout.onLayout();
|
|
}
|
|
|
|
|
|
|
|
if (!me.initialCollapsedComplete) {
|
|
Ext.iterate(me.regions, function(name, region){
|
|
if (region.borderCollapse) {
|
|
me.onBeforeRegionCollapse(region, region.collapseDirection, false, 0);
|
|
}
|
|
});
|
|
me.initialCollapsedComplete = true;
|
|
}
|
|
},
|
|
|
|
isValidParent : function(item, target, position) {
|
|
if (!this.borderLayoutInitialized) {
|
|
this.initializeBorderLayout();
|
|
}
|
|
|
|
|
|
return this.shadowLayout.isValidParent(item, target, position);
|
|
},
|
|
|
|
beforeLayout: function() {
|
|
if (!this.borderLayoutInitialized) {
|
|
this.initializeBorderLayout();
|
|
}
|
|
|
|
|
|
this.shadowLayout.beforeLayout();
|
|
|
|
|
|
},
|
|
|
|
renderItems: function(items, target) {
|
|
},
|
|
|
|
renderItem: function(item) {
|
|
},
|
|
|
|
renderChildren: function() {
|
|
if (!this.borderLayoutInitialized) {
|
|
this.initializeBorderLayout();
|
|
}
|
|
|
|
this.shadowLayout.renderChildren();
|
|
},
|
|
|
|
|
|
getVisibleItems: function() {
|
|
return Ext.ComponentQuery.query(':not([slideOutAnim])', this.callParent(arguments));
|
|
},
|
|
|
|
initializeBorderLayout: function() {
|
|
var me = this,
|
|
i = 0,
|
|
items = me.getLayoutItems(),
|
|
ln = items.length,
|
|
regions = (me.regions = {}),
|
|
vBoxItems = [],
|
|
hBoxItems = [],
|
|
horizontalFlex = 0,
|
|
verticalFlex = 0,
|
|
comp, percentage;
|
|
|
|
|
|
me.splitters = {};
|
|
|
|
|
|
for (; i < ln; i++) {
|
|
comp = items[i];
|
|
regions[comp.region] = comp;
|
|
|
|
|
|
if (comp.region != 'center' && comp.collapsible && comp.collapseMode != 'header') {
|
|
|
|
|
|
comp.borderCollapse = comp.collapsed;
|
|
comp.collapsed = false;
|
|
|
|
comp.on({
|
|
beforecollapse: me.onBeforeRegionCollapse,
|
|
beforeexpand: me.onBeforeRegionExpand,
|
|
destroy: me.onRegionDestroy,
|
|
scope: me
|
|
});
|
|
me.setupState(comp);
|
|
}
|
|
}
|
|
comp = regions.center;
|
|
if (!comp.flex) {
|
|
comp.flex = 1;
|
|
}
|
|
delete comp.width;
|
|
comp.maintainFlex = true;
|
|
|
|
|
|
comp = regions.west;
|
|
if (comp) {
|
|
comp.collapseDirection = Ext.Component.DIRECTION_LEFT;
|
|
hBoxItems.push(comp);
|
|
if (comp.split) {
|
|
hBoxItems.push(me.splitters.west = me.createSplitter(comp));
|
|
}
|
|
percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
|
|
if (percentage) {
|
|
horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
|
|
delete comp.width;
|
|
}
|
|
}
|
|
comp = regions.north;
|
|
if (comp) {
|
|
comp.collapseDirection = Ext.Component.DIRECTION_TOP;
|
|
vBoxItems.push(comp);
|
|
if (comp.split) {
|
|
vBoxItems.push(me.splitters.north = me.createSplitter(comp));
|
|
}
|
|
percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
|
|
if (percentage) {
|
|
verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
|
|
delete comp.height;
|
|
}
|
|
}
|
|
|
|
|
|
if (regions.north || regions.south) {
|
|
if (regions.east || regions.west) {
|
|
|
|
|
|
vBoxItems.push(me.embeddedContainer = Ext.create('Ext.container.Container', {
|
|
xtype: 'container',
|
|
region: 'center',
|
|
id: me.owner.id + '-embedded-center',
|
|
cls: Ext.baseCSSPrefix + 'border-item',
|
|
flex: regions.center.flex,
|
|
maintainFlex: true,
|
|
layout: {
|
|
type: 'hbox',
|
|
align: 'stretch',
|
|
getVisibleItems: me.getVisibleItems
|
|
}
|
|
}));
|
|
hBoxItems.push(regions.center);
|
|
}
|
|
|
|
else {
|
|
vBoxItems.push(regions.center);
|
|
}
|
|
}
|
|
|
|
else {
|
|
hBoxItems.push(regions.center);
|
|
}
|
|
|
|
|
|
comp = regions.south;
|
|
if (comp) {
|
|
comp.collapseDirection = Ext.Component.DIRECTION_BOTTOM;
|
|
if (comp.split) {
|
|
vBoxItems.push(me.splitters.south = me.createSplitter(comp));
|
|
}
|
|
percentage = Ext.isString(comp.height) && comp.height.match(me.percentageRe);
|
|
if (percentage) {
|
|
verticalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
|
|
delete comp.height;
|
|
}
|
|
vBoxItems.push(comp);
|
|
}
|
|
comp = regions.east;
|
|
if (comp) {
|
|
comp.collapseDirection = Ext.Component.DIRECTION_RIGHT;
|
|
if (comp.split) {
|
|
hBoxItems.push(me.splitters.east = me.createSplitter(comp));
|
|
}
|
|
percentage = Ext.isString(comp.width) && comp.width.match(me.percentageRe);
|
|
if (percentage) {
|
|
horizontalFlex += (comp.flex = parseInt(percentage[1], 10) / 100);
|
|
delete comp.width;
|
|
}
|
|
hBoxItems.push(comp);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (regions.north || regions.south) {
|
|
|
|
me.shadowContainer = Ext.create('Ext.container.Container', {
|
|
ownerCt: me.owner,
|
|
el: me.getTarget(),
|
|
layout: Ext.applyIf({
|
|
type: 'vbox',
|
|
align: 'stretch',
|
|
getVisibleItems: me.getVisibleItems
|
|
}, me.initialConfig)
|
|
});
|
|
me.createItems(me.shadowContainer, vBoxItems);
|
|
|
|
|
|
if (me.splitters.north) {
|
|
me.splitters.north.ownerCt = me.shadowContainer;
|
|
}
|
|
if (me.splitters.south) {
|
|
me.splitters.south.ownerCt = me.shadowContainer;
|
|
}
|
|
|
|
|
|
if (me.embeddedContainer) {
|
|
me.embeddedContainer.ownerCt = me.shadowContainer;
|
|
me.createItems(me.embeddedContainer, hBoxItems);
|
|
|
|
|
|
if (me.splitters.east) {
|
|
me.splitters.east.ownerCt = me.embeddedContainer;
|
|
}
|
|
if (me.splitters.west) {
|
|
me.splitters.west.ownerCt = me.embeddedContainer;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ext.each([me.splitters.north, me.splitters.south], function (splitter) {
|
|
if (splitter) {
|
|
splitter.on('beforedragstart', me.fixHeightConstraints, me);
|
|
}
|
|
});
|
|
|
|
|
|
if (horizontalFlex) {
|
|
regions.center.flex -= horizontalFlex;
|
|
}
|
|
|
|
if (verticalFlex) {
|
|
me.embeddedContainer.flex -= verticalFlex;
|
|
}
|
|
} else {
|
|
|
|
if (verticalFlex) {
|
|
regions.center.flex -= verticalFlex;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
else {
|
|
me.shadowContainer = Ext.create('Ext.container.Container', {
|
|
ownerCt: me.owner,
|
|
el: me.getTarget(),
|
|
layout: Ext.applyIf({
|
|
type: (hBoxItems.length == 1) ? 'fit' : 'hbox',
|
|
align: 'stretch'
|
|
}, me.initialConfig)
|
|
});
|
|
me.createItems(me.shadowContainer, hBoxItems);
|
|
|
|
|
|
if (me.splitters.east) {
|
|
me.splitters.east.ownerCt = me.shadowContainer;
|
|
}
|
|
if (me.splitters.west) {
|
|
me.splitters.west.ownerCt = me.shadowContainer;
|
|
}
|
|
|
|
|
|
if (horizontalFlex) {
|
|
regions.center.flex -= verticalFlex;
|
|
}
|
|
}
|
|
|
|
|
|
for (i = 0, items = me.shadowContainer.items.items, ln = items.length; i < ln; i++) {
|
|
items[i].shadowOwnerCt = me.shadowContainer;
|
|
}
|
|
if (me.embeddedContainer) {
|
|
for (i = 0, items = me.embeddedContainer.items.items, ln = items.length; i < ln; i++) {
|
|
items[i].shadowOwnerCt = me.embeddedContainer;
|
|
}
|
|
}
|
|
|
|
|
|
me.shadowLayout = me.shadowContainer.getLayout();
|
|
|
|
me.borderLayoutInitialized = true;
|
|
},
|
|
|
|
setupState: function(comp){
|
|
var getState = comp.getState;
|
|
comp.getState = function(){
|
|
|
|
var state = getState.call(comp) || {},
|
|
region = comp.region;
|
|
|
|
state.collapsed = !!comp.collapsed;
|
|
if (region == 'west' || region == 'east') {
|
|
state.width = comp.getWidth();
|
|
} else {
|
|
state.height = comp.getHeight();
|
|
}
|
|
return state;
|
|
};
|
|
comp.addStateEvents(['collapse', 'expand', 'resize']);
|
|
},
|
|
|
|
|
|
createItems: function(container, items){
|
|
|
|
|
|
delete container.items;
|
|
container.initItems();
|
|
container.items.addAll(items);
|
|
},
|
|
|
|
|
|
|
|
createSplitter: function(comp) {
|
|
var me = this,
|
|
interceptCollapse = (comp.collapseMode != 'header'),
|
|
resizer;
|
|
|
|
resizer = Ext.create('Ext.resizer.Splitter', {
|
|
hidden: !!comp.hidden,
|
|
collapseTarget: comp,
|
|
performCollapse: !interceptCollapse,
|
|
listeners: interceptCollapse ? {
|
|
click: {
|
|
fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
|
|
element: 'collapseEl'
|
|
}
|
|
} : null
|
|
});
|
|
|
|
|
|
if (comp.collapseMode == 'mini') {
|
|
comp.placeholder = resizer;
|
|
resizer.collapsedCls = comp.collapsedCls;
|
|
}
|
|
|
|
|
|
comp.on({
|
|
hide: me.onRegionVisibilityChange,
|
|
show: me.onRegionVisibilityChange,
|
|
scope: me
|
|
});
|
|
return resizer;
|
|
},
|
|
|
|
|
|
|
|
fixHeightConstraints: function () {
|
|
var me = this,
|
|
ct = me.embeddedContainer,
|
|
maxHeight = 1e99, minHeight = -1;
|
|
|
|
if (!ct) {
|
|
return;
|
|
}
|
|
|
|
ct.items.each(function (item) {
|
|
if (Ext.isNumber(item.maxHeight)) {
|
|
maxHeight = Math.max(maxHeight, item.maxHeight);
|
|
}
|
|
if (Ext.isNumber(item.minHeight)) {
|
|
minHeight = Math.max(minHeight, item.minHeight);
|
|
}
|
|
});
|
|
|
|
ct.maxHeight = maxHeight;
|
|
ct.minHeight = minHeight;
|
|
},
|
|
|
|
|
|
onRegionVisibilityChange: function(comp){
|
|
this.splitters[comp.region][comp.hidden ? 'hide' : 'show']();
|
|
this.layout();
|
|
},
|
|
|
|
|
|
|
|
|
|
onSplitterCollapseClick: function(comp) {
|
|
if (comp.collapsed) {
|
|
this.onPlaceHolderToolClick(null, null, null, {client: comp});
|
|
} else {
|
|
comp.collapse();
|
|
}
|
|
},
|
|
|
|
|
|
getPlaceholder: function(comp) {
|
|
var me = this,
|
|
placeholder = comp.placeholder,
|
|
shadowContainer = comp.shadowOwnerCt,
|
|
shadowLayout = shadowContainer.layout,
|
|
oppositeDirection = Ext.panel.Panel.prototype.getOppositeDirection(comp.collapseDirection),
|
|
horiz = (comp.region == 'north' || comp.region == 'south');
|
|
|
|
|
|
if (comp.collapseMode == 'header') {
|
|
return;
|
|
}
|
|
|
|
|
|
if (!placeholder) {
|
|
if (comp.collapseMode == 'mini') {
|
|
placeholder = Ext.create('Ext.resizer.Splitter', {
|
|
id: 'collapse-placeholder-' + comp.id,
|
|
collapseTarget: comp,
|
|
performCollapse: false,
|
|
listeners: {
|
|
click: {
|
|
fn: Ext.Function.bind(me.onSplitterCollapseClick, me, [comp]),
|
|
element: 'collapseEl'
|
|
}
|
|
}
|
|
});
|
|
placeholder.addCls(placeholder.collapsedCls);
|
|
} else {
|
|
placeholder = {
|
|
id: 'collapse-placeholder-' + comp.id,
|
|
margins: comp.initialConfig.margins || Ext.getClass(comp).prototype.margins,
|
|
xtype: 'header',
|
|
orientation: horiz ? 'horizontal' : 'vertical',
|
|
title: comp.title,
|
|
textCls: comp.headerTextCls,
|
|
iconCls: comp.iconCls,
|
|
baseCls: comp.baseCls + '-header',
|
|
ui: comp.ui,
|
|
indicateDrag: comp.draggable,
|
|
cls: Ext.baseCSSPrefix + 'region-collapsed-placeholder ' + Ext.baseCSSPrefix + 'region-collapsed-' + comp.collapseDirection + '-placeholder ' + comp.collapsedCls,
|
|
listeners: comp.floatable ? {
|
|
click: {
|
|
fn: function(e) {
|
|
me.floatCollapsedPanel(e, comp);
|
|
},
|
|
element: 'el'
|
|
}
|
|
} : null
|
|
};
|
|
|
|
if ((Ext.isIE6 || Ext.isIE7 || (Ext.isIEQuirks)) && !horiz) {
|
|
placeholder.width = 25;
|
|
}
|
|
if (!comp.hideCollapseTool) {
|
|
placeholder[horiz ? 'tools' : 'items'] = [{
|
|
xtype: 'tool',
|
|
client: comp,
|
|
type: 'expand-' + oppositeDirection,
|
|
handler: me.onPlaceHolderToolClick,
|
|
scope: me
|
|
}];
|
|
}
|
|
}
|
|
placeholder = me.owner.createComponent(placeholder);
|
|
if (comp.isXType('panel')) {
|
|
comp.on({
|
|
titlechange: me.onRegionTitleChange,
|
|
iconchange: me.onRegionIconChange,
|
|
scope: me
|
|
});
|
|
}
|
|
}
|
|
|
|
|
|
comp.placeholder = placeholder;
|
|
placeholder.comp = comp;
|
|
|
|
return placeholder;
|
|
},
|
|
|
|
|
|
onRegionTitleChange: function(comp, newTitle) {
|
|
comp.placeholder.setTitle(newTitle);
|
|
},
|
|
|
|
|
|
onRegionIconChange: function(comp, newIconCls) {
|
|
comp.placeholder.setIconCls(newIconCls);
|
|
},
|
|
|
|
|
|
calculateChildBox: function(comp) {
|
|
var me = this;
|
|
if (me.shadowContainer.items.contains(comp)) {
|
|
return me.shadowContainer.layout.calculateChildBox(comp);
|
|
}
|
|
else if (me.embeddedContainer && me.embeddedContainer.items.contains(comp)) {
|
|
return me.embeddedContainer.layout.calculateChildBox(comp);
|
|
}
|
|
},
|
|
|
|
|
|
onBeforeRegionCollapse: function(comp, direction, animate) {
|
|
if (comp.collapsedChangingLayout) {
|
|
return false;
|
|
}
|
|
comp.collapsedChangingLayout = true;
|
|
var me = this,
|
|
compEl = comp.el,
|
|
width,
|
|
miniCollapse = comp.collapseMode == 'mini',
|
|
shadowContainer = comp.shadowOwnerCt,
|
|
shadowLayout = shadowContainer.layout,
|
|
placeholder = comp.placeholder,
|
|
sl = me.owner.suspendLayout,
|
|
scsl = shadowContainer.suspendLayout,
|
|
isNorthOrWest = (comp.region == 'north' || comp.region == 'west');
|
|
|
|
|
|
me.owner.suspendLayout = true;
|
|
shadowContainer.suspendLayout = true;
|
|
|
|
|
|
shadowLayout.layoutBusy = true;
|
|
if (shadowContainer.componentLayout) {
|
|
shadowContainer.componentLayout.layoutBusy = true;
|
|
}
|
|
me.shadowContainer.layout.layoutBusy = true;
|
|
me.layoutBusy = true;
|
|
me.owner.componentLayout.layoutBusy = true;
|
|
|
|
|
|
if (!placeholder) {
|
|
placeholder = me.getPlaceholder(comp);
|
|
}
|
|
|
|
|
|
if (placeholder.shadowOwnerCt === shadowContainer) {
|
|
placeholder.show();
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
shadowContainer.insert(shadowContainer.items.indexOf(comp) + (isNorthOrWest ? 0 : 1), placeholder);
|
|
placeholder.shadowOwnerCt = shadowContainer;
|
|
placeholder.ownerCt = me.owner;
|
|
}
|
|
|
|
|
|
|
|
|
|
comp.hidden = true;
|
|
|
|
if (!placeholder.rendered) {
|
|
shadowLayout.renderItem(placeholder, shadowLayout.innerCt);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (comp.region == 'north' || comp.region == 'south') {
|
|
placeholder.setCalculatedSize(comp.getWidth());
|
|
} else {
|
|
placeholder.setCalculatedSize(undefined, comp.getHeight());
|
|
}
|
|
}
|
|
|
|
|
|
function afterCollapse() {
|
|
|
|
me.owner.suspendLayout = sl;
|
|
shadowContainer.suspendLayout = scsl;
|
|
delete shadowLayout.layoutBusy;
|
|
if (shadowContainer.componentLayout) {
|
|
delete shadowContainer.componentLayout.layoutBusy;
|
|
}
|
|
delete me.shadowContainer.layout.layoutBusy;
|
|
delete me.layoutBusy;
|
|
delete me.owner.componentLayout.layoutBusy;
|
|
delete comp.collapsedChangingLayout;
|
|
|
|
|
|
comp.collapsed = true;
|
|
comp.fireEvent('collapse', comp);
|
|
}
|
|
|
|
|
|
if (comp.animCollapse && me.initialCollapsedComplete) {
|
|
shadowLayout.layout();
|
|
compEl.dom.style.zIndex = 100;
|
|
|
|
|
|
if (!miniCollapse) {
|
|
placeholder.el.hide();
|
|
}
|
|
compEl.slideOut(me.slideDirection[comp.region], {
|
|
duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
|
|
listeners: {
|
|
afteranimate: function() {
|
|
compEl.show().setLeftTop(-10000, -10000);
|
|
compEl.dom.style.zIndex = '';
|
|
|
|
|
|
if (!miniCollapse) {
|
|
placeholder.el.slideIn(me.slideDirection[comp.region], {
|
|
easing: 'linear',
|
|
duration: 100
|
|
});
|
|
}
|
|
afterCollapse();
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
compEl.setLeftTop(-10000, -10000);
|
|
shadowLayout.layout();
|
|
afterCollapse();
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
|
|
onBeforeRegionExpand: function(comp, animate) {
|
|
|
|
this.onPlaceHolderToolClick(null, null, null, {client: comp, shouldFireBeforeexpand: false});
|
|
return false;
|
|
},
|
|
|
|
|
|
onPlaceHolderToolClick: function(e, target, owner, tool) {
|
|
var me = this,
|
|
comp = tool.client,
|
|
|
|
|
|
hidePlaceholder = (comp.collapseMode != 'mini') || !comp.split,
|
|
compEl = comp.el,
|
|
toCompBox,
|
|
placeholder = comp.placeholder,
|
|
placeholderEl = placeholder.el,
|
|
shadowContainer = comp.shadowOwnerCt,
|
|
shadowLayout = shadowContainer.layout,
|
|
curSize,
|
|
sl = me.owner.suspendLayout,
|
|
scsl = shadowContainer.suspendLayout,
|
|
isFloating;
|
|
|
|
if (comp.collapsedChangingLayout) {
|
|
return false;
|
|
}
|
|
if (tool.shouldFireBeforeexpand !== false && comp.fireEvent('beforeexpand', comp, true) === false) {
|
|
return false;
|
|
}
|
|
comp.collapsedChangingLayout = true;
|
|
|
|
|
|
|
|
if (comp.getActiveAnimation()) {
|
|
comp.stopAnimation();
|
|
}
|
|
|
|
|
|
|
|
|
|
if (comp.slideOutAnim) {
|
|
|
|
compEl.un(comp.panelMouseMon);
|
|
placeholderEl.un(comp.placeholderMouseMon);
|
|
|
|
delete comp.slideOutAnim;
|
|
delete comp.panelMouseMon;
|
|
delete comp.placeholderMouseMon;
|
|
|
|
|
|
isFloating = true;
|
|
}
|
|
|
|
|
|
me.owner.suspendLayout = true;
|
|
shadowContainer.suspendLayout = true;
|
|
|
|
|
|
shadowLayout.layoutBusy = true;
|
|
if (shadowContainer.componentLayout) {
|
|
shadowContainer.componentLayout.layoutBusy = true;
|
|
}
|
|
me.shadowContainer.layout.layoutBusy = true;
|
|
me.layoutBusy = true;
|
|
me.owner.componentLayout.layoutBusy = true;
|
|
|
|
|
|
|
|
comp.hidden = false;
|
|
comp.collapsed = false;
|
|
if (hidePlaceholder) {
|
|
placeholder.hidden = true;
|
|
}
|
|
toCompBox = shadowLayout.calculateChildBox(comp);
|
|
|
|
|
|
if (comp.collapseTool) {
|
|
comp.collapseTool.show();
|
|
}
|
|
|
|
|
|
if (comp.animCollapse && !isFloating) {
|
|
compEl.setStyle('visibility', 'hidden');
|
|
}
|
|
compEl.setLeftTop(toCompBox.left, toCompBox.top);
|
|
|
|
|
|
|
|
curSize = comp.getSize();
|
|
if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
|
|
me.setItemSize(comp, toCompBox.width, toCompBox.height);
|
|
}
|
|
|
|
|
|
function afterExpand() {
|
|
|
|
me.owner.suspendLayout = sl;
|
|
shadowContainer.suspendLayout = scsl;
|
|
delete shadowLayout.layoutBusy;
|
|
if (shadowContainer.componentLayout) {
|
|
delete shadowContainer.componentLayout.layoutBusy;
|
|
}
|
|
delete me.shadowContainer.layout.layoutBusy;
|
|
delete me.layoutBusy;
|
|
delete me.owner.componentLayout.layoutBusy;
|
|
delete comp.collapsedChangingLayout;
|
|
|
|
|
|
comp.removeCls(Ext.baseCSSPrefix + 'border-region-slide-in');
|
|
|
|
|
|
comp.fireEvent('expand', comp);
|
|
}
|
|
|
|
|
|
if (hidePlaceholder) {
|
|
placeholder.el.hide();
|
|
}
|
|
|
|
|
|
|
|
if (comp.animCollapse && !isFloating) {
|
|
compEl.dom.style.zIndex = 100;
|
|
compEl.slideIn(me.slideDirection[comp.region], {
|
|
duration: Ext.Number.from(comp.animCollapse, Ext.fx.Anim.prototype.duration),
|
|
listeners: {
|
|
afteranimate: function() {
|
|
compEl.dom.style.zIndex = '';
|
|
comp.hidden = false;
|
|
shadowLayout.onLayout();
|
|
afterExpand();
|
|
}
|
|
}
|
|
});
|
|
} else {
|
|
shadowLayout.onLayout();
|
|
afterExpand();
|
|
}
|
|
},
|
|
|
|
floatCollapsedPanel: function(e, comp) {
|
|
|
|
if (comp.floatable === false) {
|
|
return;
|
|
}
|
|
|
|
var me = this,
|
|
compEl = comp.el,
|
|
placeholder = comp.placeholder,
|
|
placeholderEl = placeholder.el,
|
|
shadowContainer = comp.shadowOwnerCt,
|
|
shadowLayout = shadowContainer.layout,
|
|
placeholderBox = shadowLayout.getChildBox(placeholder),
|
|
scsl = shadowContainer.suspendLayout,
|
|
curSize, toCompBox, compAnim;
|
|
|
|
|
|
if (e.getTarget('.' + Ext.baseCSSPrefix + 'tool')) {
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
if (compEl.getActiveAnimation()) {
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
if (comp.slideOutAnim) {
|
|
me.slideOutFloatedComponent(comp);
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
function onMouseLeaveFloated(e) {
|
|
var slideRegion = compEl.getRegion().union(placeholderEl.getRegion()).adjust(1, -1, -1, 1);
|
|
|
|
|
|
if (!slideRegion.contains(e.getPoint())) {
|
|
me.slideOutFloatedComponent(comp);
|
|
}
|
|
}
|
|
|
|
|
|
comp.placeholderMouseMon = placeholderEl.monitorMouseLeave(500, onMouseLeaveFloated);
|
|
|
|
|
|
shadowContainer.suspendLayout = true;
|
|
|
|
|
|
me.layoutBusy = true;
|
|
me.owner.componentLayout.layoutBusy = true;
|
|
|
|
|
|
|
|
if (comp.collapseTool) {
|
|
comp.collapseTool.hide();
|
|
}
|
|
|
|
|
|
comp.hidden = false;
|
|
comp.collapsed = false;
|
|
placeholder.hidden = true;
|
|
|
|
|
|
toCompBox = shadowLayout.calculateChildBox(comp);
|
|
placeholder.hidden = false;
|
|
|
|
|
|
if (comp.region == 'north' || comp.region == 'west') {
|
|
toCompBox[shadowLayout.parallelBefore] += placeholderBox[shadowLayout.parallelPrefix] - 1;
|
|
} else {
|
|
toCompBox[shadowLayout.parallelBefore] -= (placeholderBox[shadowLayout.parallelPrefix] - 1);
|
|
}
|
|
compEl.setStyle('visibility', 'hidden');
|
|
compEl.setLeftTop(toCompBox.left, toCompBox.top);
|
|
|
|
|
|
|
|
curSize = comp.getSize();
|
|
if (curSize.height != toCompBox.height || curSize.width != toCompBox.width) {
|
|
me.setItemSize(comp, toCompBox.width, toCompBox.height);
|
|
}
|
|
|
|
|
|
compAnim = {
|
|
listeners: {
|
|
afteranimate: function() {
|
|
shadowContainer.suspendLayout = scsl;
|
|
delete me.layoutBusy;
|
|
delete me.owner.componentLayout.layoutBusy;
|
|
|
|
|
|
compAnim.listeners = {
|
|
afterAnimate: function() {
|
|
compEl.show().removeCls(Ext.baseCSSPrefix + 'border-region-slide-in').setLeftTop(-10000, -10000);
|
|
|
|
|
|
comp.hidden = true;
|
|
comp.collapsed = true;
|
|
delete comp.slideOutAnim;
|
|
delete comp.panelMouseMon;
|
|
delete comp.placeholderMouseMon;
|
|
}
|
|
};
|
|
comp.slideOutAnim = compAnim;
|
|
}
|
|
},
|
|
duration: 500
|
|
};
|
|
|
|
|
|
compEl.addCls(Ext.baseCSSPrefix + 'border-region-slide-in');
|
|
|
|
|
|
compEl.slideIn(me.slideDirection[comp.region], compAnim);
|
|
|
|
|
|
comp.panelMouseMon = compEl.monitorMouseLeave(500, onMouseLeaveFloated);
|
|
|
|
},
|
|
|
|
slideOutFloatedComponent: function(comp) {
|
|
var compEl = comp.el,
|
|
slideOutAnim;
|
|
|
|
|
|
compEl.un(comp.panelMouseMon);
|
|
comp.placeholder.el.un(comp.placeholderMouseMon);
|
|
|
|
|
|
compEl.slideOut(this.slideDirection[comp.region], comp.slideOutAnim);
|
|
|
|
delete comp.slideOutAnim;
|
|
delete comp.panelMouseMon;
|
|
delete comp.placeholderMouseMon;
|
|
},
|
|
|
|
|
|
onRegionDestroy: function(comp) {
|
|
var placeholder = comp.placeholder;
|
|
if (placeholder) {
|
|
delete placeholder.ownerCt;
|
|
placeholder.destroy();
|
|
}
|
|
},
|
|
|
|
|
|
onDestroy: function() {
|
|
var me = this,
|
|
shadowContainer = me.shadowContainer,
|
|
embeddedContainer = me.embeddedContainer;
|
|
|
|
if (shadowContainer) {
|
|
delete shadowContainer.ownerCt;
|
|
Ext.destroy(shadowContainer);
|
|
}
|
|
|
|
if (embeddedContainer) {
|
|
delete embeddedContainer.ownerCt;
|
|
Ext.destroy(embeddedContainer);
|
|
}
|
|
delete me.regions;
|
|
delete me.splitters;
|
|
delete me.shadowContainer;
|
|
delete me.embeddedContainer;
|
|
me.callParent(arguments);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.layout.container.Card', {
|
|
|
|
|
|
|
|
alias: ['layout.card'],
|
|
alternateClassName: 'Ext.layout.CardLayout',
|
|
|
|
extend: 'Ext.layout.container.AbstractCard',
|
|
|
|
|
|
|
|
|
|
setActiveItem: function(newCard) {
|
|
var me = this,
|
|
owner = me.owner,
|
|
oldCard = me.activeItem,
|
|
newIndex;
|
|
|
|
newCard = me.parseActiveItem(newCard);
|
|
newIndex = owner.items.indexOf(newCard);
|
|
|
|
|
|
if (newIndex == -1) {
|
|
newIndex = owner.items.items.length;
|
|
owner.add(newCard);
|
|
}
|
|
|
|
|
|
if (newCard && oldCard != newCard) {
|
|
|
|
if (!newCard.rendered) {
|
|
me.renderItem(newCard, me.getRenderTarget(), owner.items.length);
|
|
me.configureItem(newCard, 0);
|
|
}
|
|
|
|
me.activeItem = newCard;
|
|
|
|
|
|
if (newCard.fireEvent('beforeactivate', newCard, oldCard) === false) {
|
|
return false;
|
|
}
|
|
if (oldCard && oldCard.fireEvent('beforedeactivate', oldCard, newCard) === false) {
|
|
return false;
|
|
}
|
|
|
|
|
|
if (me.sizeAllCards) {
|
|
|
|
me.onLayout();
|
|
}
|
|
else {
|
|
me.setItemBox(newCard, me.getTargetBox());
|
|
}
|
|
|
|
me.owner.suspendLayout = true;
|
|
|
|
if (oldCard) {
|
|
if (me.hideInactive) {
|
|
oldCard.hide();
|
|
}
|
|
oldCard.fireEvent('deactivate', oldCard, newCard);
|
|
}
|
|
|
|
|
|
me.owner.suspendLayout = false;
|
|
if (newCard.hidden) {
|
|
newCard.show();
|
|
} else {
|
|
me.onLayout();
|
|
}
|
|
|
|
newCard.fireEvent('activate', newCard, oldCard);
|
|
|
|
return newCard;
|
|
}
|
|
return false;
|
|
},
|
|
|
|
configureItem: function(item) {
|
|
|
|
|
|
item.layoutManagedHeight = 0;
|
|
item.layoutManagedWidth = 0;
|
|
|
|
this.callParent(arguments);
|
|
}});
|
|
|
|
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',
|
|
|
|
scrollOffset: 0,
|
|
|
|
bindToOwnerCtComponent: false,
|
|
|
|
getRenderTarget : function() {
|
|
if (!this.innerCt) {
|
|
|
|
|
|
|
|
this.innerCt = this.getTarget().createChild({
|
|
cls: Ext.baseCSSPrefix + 'column-inner'
|
|
});
|
|
|
|
|
|
|
|
|
|
this.clearEl = this.innerCt.createChild({
|
|
cls: Ext.baseCSSPrefix + 'clear',
|
|
role: 'presentation'
|
|
});
|
|
}
|
|
return this.innerCt;
|
|
},
|
|
|
|
|
|
onLayout : function() {
|
|
var me = this,
|
|
target = me.getTarget(),
|
|
items = me.getLayoutItems(),
|
|
len = items.length,
|
|
item,
|
|
i,
|
|
parallelMargins = [],
|
|
itemParallelMargins,
|
|
size,
|
|
availableWidth,
|
|
columnWidth;
|
|
|
|
size = me.getLayoutTargetSize();
|
|
if (size.width < len * 10) {
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
if (me.adjustmentPass) {
|
|
if (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) {
|
|
size.width = me.adjustedWidth;
|
|
}
|
|
} else {
|
|
i = target.getStyle('overflow');
|
|
if (i && i != 'hidden') {
|
|
me.autoScroll = true;
|
|
if (!(Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks)) {
|
|
target.setStyle('overflow', 'hidden');
|
|
size = me.getLayoutTargetSize();
|
|
}
|
|
}
|
|
}
|
|
|
|
availableWidth = size.width - me.scrollOffset;
|
|
me.innerCt.setWidth(availableWidth);
|
|
|
|
|
|
|
|
for (i = 0; i < len; i++) {
|
|
item = items[i];
|
|
itemParallelMargins = parallelMargins[i] = item.getEl().getMargin('lr');
|
|
if (!item.columnWidth) {
|
|
availableWidth -= (item.getWidth() + itemParallelMargins);
|
|
}
|
|
}
|
|
|
|
availableWidth = availableWidth < 0 ? 0 : availableWidth;
|
|
for (i = 0; i < len; i++) {
|
|
item = items[i];
|
|
if (item.columnWidth) {
|
|
columnWidth = Math.floor(item.columnWidth * availableWidth) - parallelMargins[i];
|
|
me.setItemSize(item, columnWidth, item.height);
|
|
} else {
|
|
me.layoutItem(item);
|
|
}
|
|
}
|
|
|
|
|
|
if (!me.adjustmentPass && me.autoScroll) {
|
|
|
|
|
|
target.setStyle('overflow', 'auto');
|
|
me.adjustmentPass = (target.dom.scrollHeight > size.height);
|
|
if (Ext.isIE6 || Ext.isIE7 || Ext.isIEQuirks) {
|
|
me.adjustedWidth = size.width - Ext.getScrollBarWidth();
|
|
} else {
|
|
target.setStyle('overflow', 'auto');
|
|
}
|
|
|
|
|
|
if (me.adjustmentPass) {
|
|
me.onLayout();
|
|
}
|
|
}
|
|
delete me.adjustmentPass;
|
|
},
|
|
|
|
configureItem: function(item) {
|
|
this.callParent(arguments);
|
|
|
|
if (item.columnWidth) {
|
|
item.layoutManagedWidth = 1;
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.layout.container.Table', {
|
|
|
|
|
|
|
|
alias: ['layout.table'],
|
|
extend: 'Ext.layout.container.Auto',
|
|
alternateClassName: 'Ext.layout.TableLayout',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
monitorResize:false,
|
|
|
|
type: 'table',
|
|
|
|
|
|
|
|
autoSize: true,
|
|
|
|
clearEl: true,
|
|
|
|
targetCls: Ext.baseCSSPrefix + 'table-layout-ct',
|
|
tableCls: Ext.baseCSSPrefix + 'table-layout',
|
|
cellCls: Ext.baseCSSPrefix + 'table-layout-cell',
|
|
|
|
|
|
tableAttrs:null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
renderItems: function(items) {
|
|
var tbody = this.getTable().tBodies[0],
|
|
rows = tbody.rows,
|
|
i = 0,
|
|
len = items.length,
|
|
cells, curCell, rowIdx, cellIdx, item, trEl, tdEl, itemCt;
|
|
|
|
|
|
cells = this.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 (this.trAttrs) {
|
|
trEl.set(this.trAttrs);
|
|
}
|
|
}
|
|
|
|
|
|
itemCt = tdEl = Ext.get(trEl.cells[cellIdx] || trEl.insertCell(cellIdx));
|
|
if (this.needsDivWrap()) {
|
|
itemCt = tdEl.first() || tdEl.createChild({tag: 'div'});
|
|
itemCt.setWidth(null);
|
|
}
|
|
|
|
|
|
if (!item.rendered) {
|
|
this.renderItem(item, itemCt, 0);
|
|
}
|
|
else if (!this.isValidParent(item, itemCt, 0)) {
|
|
this.moveItem(item, itemCt, 0);
|
|
}
|
|
|
|
|
|
if (this.tdAttrs) {
|
|
tdEl.set(this.tdAttrs);
|
|
}
|
|
tdEl.set({
|
|
colSpan: item.colspan || 1,
|
|
rowSpan: item.rowspan || 1,
|
|
id: item.cellId || '',
|
|
cls: this.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);
|
|
}
|
|
},
|
|
|
|
afterLayout: function() {
|
|
this.callParent();
|
|
|
|
if (this.needsDivWrap()) {
|
|
|
|
Ext.Array.forEach(this.getLayoutItems(), function(item) {
|
|
Ext.fly(item.el.dom.parentNode).setWidth(item.getWidth());
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
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;
|
|
},
|
|
|
|
|
|
getTable: function() {
|
|
var table = this.table;
|
|
if (!table) {
|
|
table = this.table = this.getTarget().createChild(
|
|
Ext.apply({
|
|
tag: 'table',
|
|
role: 'presentation',
|
|
cls: this.tableCls,
|
|
cellspacing: 0,
|
|
cn: {tag: 'tbody'}
|
|
}, this.tableAttrs),
|
|
null, true
|
|
);
|
|
}
|
|
return table;
|
|
},
|
|
|
|
|
|
needsDivWrap: function() {
|
|
return Ext.isOpera10_5;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.menu.Item', {
|
|
extend: 'Ext.Component',
|
|
alias: 'widget.menuitem',
|
|
alternateClassName: 'Ext.menu.TextItem',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
activeCls: Ext.baseCSSPrefix + 'menu-item-active',
|
|
|
|
|
|
ariaRole: 'menuitem',
|
|
|
|
|
|
canActivate: true,
|
|
|
|
|
|
clickHideDelay: 1,
|
|
|
|
|
|
destroyMenu: true,
|
|
|
|
|
|
disabledCls: Ext.baseCSSPrefix + 'menu-item-disabled',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hideOnClick: true,
|
|
|
|
|
|
|
|
|
|
|
|
isMenuItem: true,
|
|
|
|
|
|
|
|
|
|
menuAlign: 'tl-tr?',
|
|
|
|
|
|
menuExpandDelay: 200,
|
|
|
|
|
|
menuHideDelay: 200,
|
|
|
|
|
|
|
|
renderTpl: [
|
|
'<tpl if="plain">',
|
|
'{text}',
|
|
'</tpl>',
|
|
'<tpl if="!plain">',
|
|
'<a id="{id}-itemEl" class="' + Ext.baseCSSPrefix + 'menu-item-link" href="{href}" <tpl if="hrefTarget">target="{hrefTarget}"</tpl> hidefocus="true" unselectable="on">',
|
|
'<img id="{id}-iconEl" src="{icon}" class="' + Ext.baseCSSPrefix + 'menu-item-icon {iconCls}" />',
|
|
'<span id="{id}-textEl" class="' + Ext.baseCSSPrefix + 'menu-item-text" <tpl if="menu">style="margin-right: 17px;"</tpl> >{text}</span>',
|
|
'<tpl if="menu">',
|
|
'<img id="{id}-arrowEl" src="{blank}" class="' + Ext.baseCSSPrefix + 'menu-item-arrow" />',
|
|
'</tpl>',
|
|
'</a>',
|
|
'</tpl>'
|
|
],
|
|
|
|
maskOnDisable: false,
|
|
|
|
|
|
|
|
activate: function() {
|
|
var me = this;
|
|
|
|
if (!me.activated && me.canActivate && me.rendered && !me.isDisabled() && me.isVisible()) {
|
|
me.el.addCls(me.activeCls);
|
|
me.focus();
|
|
me.activated = true;
|
|
me.fireEvent('activate', me);
|
|
}
|
|
},
|
|
|
|
blur: function() {
|
|
this.$focused = false;
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
deactivate: function() {
|
|
var me = this;
|
|
|
|
if (me.activated) {
|
|
me.el.removeCls(me.activeCls);
|
|
me.blur();
|
|
me.hideMenu();
|
|
me.activated = false;
|
|
me.fireEvent('deactivate', me);
|
|
}
|
|
},
|
|
|
|
deferExpandMenu: function() {
|
|
var me = this;
|
|
|
|
if (!me.menu.rendered || !me.menu.isVisible()) {
|
|
me.parentMenu.activeChild = me.menu;
|
|
me.menu.parentItem = me;
|
|
me.menu.parentMenu = me.menu.ownerCt = me.parentMenu;
|
|
me.menu.showBy(me, me.menuAlign);
|
|
}
|
|
},
|
|
|
|
deferHideMenu: function() {
|
|
if (this.menu.isVisible()) {
|
|
this.menu.hide();
|
|
}
|
|
},
|
|
|
|
deferHideParentMenus: function() {
|
|
Ext.menu.Manager.hideAll();
|
|
},
|
|
|
|
expandMenu: function(delay) {
|
|
var me = this;
|
|
|
|
if (me.menu) {
|
|
clearTimeout(me.hideMenuTimer);
|
|
if (delay === 0) {
|
|
me.deferExpandMenu();
|
|
} else {
|
|
me.expandMenuTimer = Ext.defer(me.deferExpandMenu, Ext.isNumber(delay) ? delay : me.menuExpandDelay, me);
|
|
}
|
|
}
|
|
},
|
|
|
|
focus: function() {
|
|
this.$focused = true;
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
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'];
|
|
|
|
me.addEvents(
|
|
|
|
'activate',
|
|
|
|
|
|
'click',
|
|
|
|
|
|
'deactivate'
|
|
);
|
|
|
|
if (me.plain) {
|
|
cls.push(prefix + 'menu-item-plain');
|
|
}
|
|
|
|
if (me.cls) {
|
|
cls.push(me.cls);
|
|
}
|
|
|
|
me.cls = cls.join(' ');
|
|
|
|
if (me.menu) {
|
|
me.menu = Ext.menu.Manager.get(me.menu);
|
|
}
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
onClick: function(e) {
|
|
var me = this;
|
|
|
|
if (!me.href) {
|
|
e.stopEvent();
|
|
}
|
|
|
|
if (me.disabled) {
|
|
return;
|
|
}
|
|
|
|
if (me.hideOnClick) {
|
|
me.deferHideParentMenusTimer = Ext.defer(me.deferHideParentMenus, me.clickHideDelay, me);
|
|
}
|
|
|
|
Ext.callback(me.handler, me.scope || me, [me, e]);
|
|
me.fireEvent('click', me, e);
|
|
|
|
if (!me.hideOnClick) {
|
|
me.focus();
|
|
}
|
|
},
|
|
|
|
onDestroy: function() {
|
|
var me = this;
|
|
|
|
clearTimeout(me.expandMenuTimer);
|
|
clearTimeout(me.hideMenuTimer);
|
|
clearTimeout(me.deferHideParentMenusTimer);
|
|
|
|
if (me.menu) {
|
|
delete me.menu.parentItem;
|
|
delete me.menu.parentMenu;
|
|
delete me.menu.ownerCt;
|
|
if (me.destroyMenu !== false) {
|
|
me.menu.destroy();
|
|
}
|
|
}
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
onRender: function(ct, pos) {
|
|
var me = this,
|
|
blank = Ext.BLANK_IMAGE_URL;
|
|
|
|
Ext.applyIf(me.renderData, {
|
|
href: me.href || '#',
|
|
hrefTarget: me.hrefTarget,
|
|
icon: me.icon || blank,
|
|
iconCls: me.iconCls + (me.checkChangeDisabled ? ' ' + me.disabledCls : ''),
|
|
menu: Ext.isDefined(me.menu),
|
|
plain: me.plain,
|
|
text: me.text,
|
|
blank: blank
|
|
});
|
|
|
|
me.addChildEls('itemEl', 'iconEl', 'textEl', 'arrowEl');
|
|
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
setHandler: function(fn, scope) {
|
|
this.handler = fn || null;
|
|
this.scope = scope;
|
|
},
|
|
|
|
|
|
setIconCls: function(iconCls) {
|
|
var me = this;
|
|
|
|
if (me.iconEl) {
|
|
if (me.iconCls) {
|
|
me.iconEl.removeCls(me.iconCls);
|
|
}
|
|
|
|
if (iconCls) {
|
|
me.iconEl.addCls(iconCls);
|
|
}
|
|
}
|
|
|
|
me.iconCls = iconCls;
|
|
},
|
|
|
|
|
|
setText: function(text) {
|
|
var me = this,
|
|
el = me.textEl || me.el;
|
|
|
|
me.text = text;
|
|
|
|
if (me.rendered) {
|
|
el.update(text || '');
|
|
|
|
me.ownerCt.redoComponentLayout();
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
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,
|
|
|
|
afterRender: function() {
|
|
var me = this;
|
|
this.callParent();
|
|
me.checked = !me.checked;
|
|
me.setChecked(!me.checked, true);
|
|
},
|
|
|
|
initComponent: function() {
|
|
var me = this;
|
|
me.addEvents(
|
|
|
|
'beforecheckchange',
|
|
|
|
|
|
'checkchange'
|
|
);
|
|
|
|
me.callParent(arguments);
|
|
|
|
Ext.menu.Manager.registerCheckable(me);
|
|
|
|
if (me.group) {
|
|
if (!me.iconCls) {
|
|
me.iconCls = me.groupCls;
|
|
}
|
|
if (me.initialConfig.hideOnClick !== false) {
|
|
me.hideOnClick = true;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
disableCheckChange: function() {
|
|
var me = this;
|
|
|
|
if (me.iconEl) {
|
|
me.iconEl.addCls(me.disabledCls);
|
|
}
|
|
me.checkChangeDisabled = true;
|
|
},
|
|
|
|
|
|
enableCheckChange: function() {
|
|
var me = this;
|
|
|
|
me.iconEl.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;
|
|
if (me.checked !== checked && (suppressEvents || me.fireEvent('beforecheckchange', me, checked) !== false)) {
|
|
if (me.el) {
|
|
me.el[checked ? 'addCls' : 'removeCls'](me.checkedCls)[!checked ? 'addCls' : 'removeCls'](me.uncheckedCls);
|
|
}
|
|
me.checked = checked;
|
|
Ext.menu.Manager.onCheckChange(me, checked);
|
|
if (!suppressEvents) {
|
|
Ext.callback(me.checkHandler, me.scope, [me, checked]);
|
|
me.fireEvent('checkchange', me, checked);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.menu.KeyNav', {
|
|
extend: 'Ext.util.KeyNav',
|
|
|
|
requires: ['Ext.FocusManager'],
|
|
|
|
constructor: function(menu) {
|
|
var me = this;
|
|
|
|
me.menu = menu;
|
|
me.callParent([menu.el, {
|
|
down: me.down,
|
|
enter: me.enter,
|
|
esc: me.escape,
|
|
left: me.left,
|
|
right: me.right,
|
|
space: me.enter,
|
|
tab: me.tab,
|
|
up: me.up
|
|
}]);
|
|
},
|
|
|
|
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;
|
|
|
|
while (idx != startIdx) {
|
|
if (idx < 0) {
|
|
idx = items.length - 1;
|
|
} else if (idx >= items.length) {
|
|
idx = 0;
|
|
}
|
|
|
|
var item = items.getAt(idx);
|
|
if (menu.canActivateItem(item)) {
|
|
menu.setActiveItem(item);
|
|
break;
|
|
}
|
|
idx += step;
|
|
}
|
|
},
|
|
|
|
isWhitelisted: function(item) {
|
|
return Ext.FocusManager.isWhitelisted(item);
|
|
},
|
|
|
|
left: function(e) {
|
|
var menu = this.menu,
|
|
fi = menu.focusedItem,
|
|
ai = menu.activeItem;
|
|
|
|
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);
|
|
Ext.defer(function() {
|
|
am.setActiveItem(am.items.getAt(0));
|
|
}, 25);
|
|
}
|
|
}
|
|
},
|
|
|
|
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: ' ',
|
|
|
|
onRender: function(ct, pos) {
|
|
var me = this,
|
|
sepCls = me.separatorCls;
|
|
|
|
me.cls += ' ' + sepCls;
|
|
|
|
me.callParent(arguments);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.menu.Menu', {
|
|
extend: 'Ext.panel.Panel',
|
|
alias: 'widget.menu',
|
|
requires: [
|
|
'Ext.layout.container.Fit',
|
|
'Ext.layout.container.VBox',
|
|
'Ext.menu.CheckItem',
|
|
'Ext.menu.Item',
|
|
'Ext.menu.KeyNav',
|
|
'Ext.menu.Manager',
|
|
'Ext.menu.Separator'
|
|
],
|
|
|
|
|
|
|
|
|
|
allowOtherMenus: false,
|
|
|
|
|
|
ariaRole: 'menu',
|
|
|
|
|
|
|
|
|
|
defaultAlign: 'tl-bl?',
|
|
|
|
|
|
floating: true,
|
|
|
|
|
|
constrain: true,
|
|
|
|
|
|
hidden: true,
|
|
|
|
hideMode: 'visibility',
|
|
|
|
|
|
ignoreParentClicks: false,
|
|
|
|
isMenu: true,
|
|
|
|
|
|
|
|
|
|
showSeparator : true,
|
|
|
|
|
|
minWidth: 120,
|
|
|
|
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
prefix = Ext.baseCSSPrefix,
|
|
cls = [prefix + 'menu'],
|
|
bodyCls = me.bodyCls ? [me.bodyCls] : [];
|
|
|
|
me.addEvents(
|
|
|
|
'click',
|
|
|
|
|
|
'mouseenter',
|
|
|
|
|
|
'mouseleave',
|
|
|
|
|
|
'mouseover'
|
|
);
|
|
|
|
Ext.menu.Manager.register(me);
|
|
|
|
|
|
if (me.plain) {
|
|
cls.push(prefix + 'menu-plain');
|
|
}
|
|
me.cls = cls.join(' ');
|
|
|
|
|
|
bodyCls.unshift(prefix + 'menu-body');
|
|
me.bodyCls = bodyCls.join(' ');
|
|
|
|
|
|
|
|
|
|
|
|
me.layout = {
|
|
type: 'vbox',
|
|
align: 'stretchmax',
|
|
autoSize: true,
|
|
clearInnerCtOnLayout: true,
|
|
overflowHandler: 'Scroller'
|
|
};
|
|
|
|
|
|
if (me.floating === false && me.initialConfig.hidden !== true) {
|
|
me.hidden = false;
|
|
}
|
|
|
|
me.callParent(arguments);
|
|
|
|
me.on('beforeshow', function() {
|
|
var hasItems = !!me.items.length;
|
|
|
|
|
|
|
|
if (hasItems && me.rendered) {
|
|
me.el.setStyle('visibility', null);
|
|
}
|
|
return hasItems;
|
|
});
|
|
},
|
|
|
|
afterRender: function(ct) {
|
|
var me = this,
|
|
prefix = Ext.baseCSSPrefix,
|
|
space = ' ';
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
if (me.showSeparator) {
|
|
me.iconSepEl = me.layout.getRenderTarget().insertFirst({
|
|
cls: prefix + 'menu-icon-separator',
|
|
html: space
|
|
});
|
|
}
|
|
|
|
me.focusEl = me.el.createChild({
|
|
cls: prefix + 'menu-focus',
|
|
tabIndex: '-1',
|
|
html: space
|
|
});
|
|
|
|
me.mon(me.el, {
|
|
click: me.onClick,
|
|
mouseover: me.onMouseOver,
|
|
scope: me
|
|
});
|
|
me.mouseMonitor = me.el.monitorMouseLeave(100, me.onMouseLeave, me);
|
|
|
|
if (me.showSeparator && ((!Ext.isStrict && Ext.isIE) || Ext.isIE6)) {
|
|
me.iconSepEl.setHeight(me.el.getHeight());
|
|
}
|
|
|
|
me.keyNav = Ext.create('Ext.menu.KeyNav', me);
|
|
},
|
|
|
|
afterLayout: function() {
|
|
var me = this;
|
|
me.callParent(arguments);
|
|
|
|
|
|
|
|
|
|
|
|
if ((!Ext.isStrict && Ext.isIE) || Ext.isIE6) {
|
|
var innerCt = me.layout.getRenderTarget(),
|
|
innerCtWidth = 0,
|
|
dis = me.dockedItems,
|
|
l = dis.length,
|
|
i = 0,
|
|
di, clone, newWidth;
|
|
|
|
innerCtWidth = innerCt.getWidth();
|
|
|
|
newWidth = innerCtWidth + me.body.getBorderWidth('lr') + me.body.getPadding('lr');
|
|
|
|
|
|
me.body.setWidth(newWidth);
|
|
|
|
|
|
for (; i < l, di = dis.getAt(i); i++) {
|
|
if (di.dock == 'left' || di.dock == 'right') {
|
|
newWidth += di.getWidth();
|
|
}
|
|
}
|
|
me.el.setWidth(newWidth);
|
|
}
|
|
},
|
|
|
|
getBubbleTarget: function(){
|
|
return this.parentMenu || this.callParent();
|
|
},
|
|
|
|
|
|
canActivateItem: function(item) {
|
|
return item && !item.isDisabled() && item.isVisible() && (item.canActivate || item.getXTypes().indexOf('menuitem') < 0);
|
|
},
|
|
|
|
|
|
deactivateActiveItem: function() {
|
|
var me = this;
|
|
|
|
if (me.activeItem) {
|
|
me.activeItem.deactivate();
|
|
if (!me.activeItem.activated) {
|
|
delete me.activeItem;
|
|
}
|
|
}
|
|
|
|
|
|
if (me.focusedItem && !me.filtered) {
|
|
me.focusedItem.blur();
|
|
if (!me.focusedItem.$focused) {
|
|
delete me.focusedItem;
|
|
}
|
|
}
|
|
},
|
|
|
|
clearStretch: function () {
|
|
|
|
|
|
if (this.rendered) {
|
|
this.items.each(function (item) {
|
|
|
|
if (item.componentLayout) {
|
|
delete item.componentLayout.lastComponentSize;
|
|
}
|
|
if (item.el) {
|
|
item.el.setWidth(null);
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
onAdd: function () {
|
|
var me = this;
|
|
|
|
me.clearStretch();
|
|
me.callParent(arguments);
|
|
|
|
if (Ext.isIE6 || Ext.isIE7) {
|
|
|
|
Ext.Function.defer(me.doComponentLayout, 10, me);
|
|
}
|
|
},
|
|
|
|
onRemove: function () {
|
|
this.clearStretch();
|
|
this.callParent(arguments);
|
|
|
|
},
|
|
|
|
redoComponentLayout: function () {
|
|
if (this.rendered) {
|
|
this.clearStretch();
|
|
this.doComponentLayout();
|
|
}
|
|
},
|
|
|
|
|
|
getFocusEl: function() {
|
|
return this.focusEl;
|
|
},
|
|
|
|
|
|
hide: function() {
|
|
this.deactivateActiveItem();
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
|
|
getItemFromEvent: function(e) {
|
|
return this.getChildByElement(e.getTarget());
|
|
},
|
|
|
|
lookupComponent: function(cmp) {
|
|
var me = this;
|
|
|
|
if (Ext.isString(cmp)) {
|
|
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,
|
|
intercept;
|
|
|
|
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', prefix + 'menu-item-cmp'];
|
|
intercept = Ext.Function.createInterceptor;
|
|
|
|
|
|
cmp.focus = intercept(cmp.focus, function() {
|
|
this.$focused = true;
|
|
}, cmp);
|
|
cmp.blur = intercept(cmp.blur, function() {
|
|
this.$focused = false;
|
|
}, cmp);
|
|
|
|
if (!me.plain && (cmp.indent === true || cmp.iconCls === 'no-icon')) {
|
|
cls.push(prefix + 'menu-item-indent');
|
|
}
|
|
|
|
if (cmp.rendered) {
|
|
cmp.el.addCls(cls);
|
|
} else {
|
|
cmp.cls = (cmp.cls ? cmp.cls : '') + ' ' + cls.join(' ');
|
|
}
|
|
cmp.isMenuItem = true;
|
|
}
|
|
return cmp;
|
|
},
|
|
|
|
|
|
lookupItemFromString: function(cmp) {
|
|
return (cmp == 'separator' || cmp == '-') ?
|
|
Ext.createWidget('menuseparator')
|
|
: Ext.createWidget('menuitem', {
|
|
canActivate: false,
|
|
hideOnClick: false,
|
|
plain: true,
|
|
text: cmp
|
|
});
|
|
},
|
|
|
|
onClick: function(e) {
|
|
var me = this,
|
|
item;
|
|
|
|
if (me.disabled) {
|
|
e.stopEvent();
|
|
return;
|
|
}
|
|
|
|
if ((e.getTarget() == me.focusEl.dom) || e.within(me.layout.getRenderTarget())) {
|
|
item = me.getItemFromEvent(e) || me.activeItem;
|
|
|
|
if (item) {
|
|
if (item.getXTypes().indexOf('menuitem') >= 0) {
|
|
if (!item.menu || !me.ignoreParentClicks) {
|
|
item.onClick(e);
|
|
} else {
|
|
e.stopEvent();
|
|
}
|
|
}
|
|
}
|
|
me.fireEvent('click', me, item, e);
|
|
}
|
|
},
|
|
|
|
onDestroy: function() {
|
|
var me = this;
|
|
|
|
Ext.menu.Manager.unregister(me);
|
|
if (me.rendered) {
|
|
me.el.un(me.mouseMonitor);
|
|
me.keyNav.destroy();
|
|
delete me.keyNav;
|
|
}
|
|
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);
|
|
|
|
if (mouseEnter && me.parentMenu) {
|
|
me.parentMenu.setActiveItem(me.parentItem);
|
|
me.parentMenu.mouseMonitor.mouseenter();
|
|
}
|
|
|
|
if (me.disabled) {
|
|
return;
|
|
}
|
|
|
|
if (item) {
|
|
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 && item != me.focusedItem)) {
|
|
me.deactivateActiveItem();
|
|
if (me.canActivateItem(item)) {
|
|
if (item.activate) {
|
|
item.activate();
|
|
if (item.activated) {
|
|
me.activeItem = item;
|
|
me.focusedItem = item;
|
|
me.focus();
|
|
}
|
|
} else {
|
|
item.focus();
|
|
me.focusedItem = item;
|
|
}
|
|
}
|
|
item.el.scrollIntoView(me.layout.getRenderTarget());
|
|
}
|
|
},
|
|
|
|
|
|
showBy: function(cmp, pos, off) {
|
|
var me = this,
|
|
xy,
|
|
region;
|
|
|
|
if (me.floating && cmp) {
|
|
me.layout.autoSize = true;
|
|
|
|
|
|
me.doAutoRender();
|
|
delete me.needsLayout;
|
|
|
|
|
|
cmp = cmp.el || cmp;
|
|
|
|
|
|
xy = me.el.getAlignToXY(cmp, pos || me.defaultAlign, off);
|
|
if (me.floatParent) {
|
|
region = me.floatParent.getTargetEl().getViewRegion();
|
|
xy[0] -= region.x;
|
|
xy[1] -= region.y;
|
|
}
|
|
me.showAt(xy);
|
|
}
|
|
return me;
|
|
},
|
|
|
|
doConstrain : function() {
|
|
var me = this,
|
|
y = me.el.getY(),
|
|
max, full,
|
|
vector,
|
|
returnY = y, normalY, parentEl, scrollTop, viewHeight;
|
|
|
|
delete me.height;
|
|
me.setSize();
|
|
full = me.getHeight();
|
|
if (me.floating) {
|
|
|
|
parentEl = Ext.fly(me.el.getScopeParent());
|
|
scrollTop = parentEl.getScroll().top;
|
|
viewHeight = parentEl.getViewSize().height;
|
|
|
|
|
|
normalY = y - scrollTop;
|
|
max = me.maxHeight ? me.maxHeight : viewHeight - normalY;
|
|
if (full > viewHeight) {
|
|
max = viewHeight;
|
|
|
|
returnY = y - normalY;
|
|
} else if (max < full) {
|
|
returnY = y - (full - max);
|
|
max = full;
|
|
}
|
|
}else{
|
|
max = me.getHeight();
|
|
}
|
|
|
|
if (me.maxHeight){
|
|
max = Math.min(me.maxHeight, max);
|
|
}
|
|
if (full > max && max > 0){
|
|
me.layout.autoSize = false;
|
|
me.setHeight(max);
|
|
if (me.showSeparator){
|
|
me.iconSepEl.setHeight(me.layout.getRenderTarget().dom.scrollHeight);
|
|
}
|
|
}
|
|
vector = me.getConstrainVector(me.el.getScopeParent());
|
|
if (vector) {
|
|
me.setPosition(me.getPosition()[0] + vector[0]);
|
|
}
|
|
me.el.setY(returnY);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.menu.ColorPicker', {
|
|
extend: 'Ext.menu.Menu',
|
|
|
|
alias: 'widget.colormenu',
|
|
|
|
requires: [
|
|
'Ext.picker.Color'
|
|
],
|
|
|
|
|
|
hideOnClick : true,
|
|
|
|
|
|
pickerId : null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initComponent : function(){
|
|
var me = this,
|
|
cfg = Ext.apply({}, me.initialConfig);
|
|
|
|
|
|
delete cfg.listeners;
|
|
Ext.apply(me, {
|
|
plain: true,
|
|
showSeparator: false,
|
|
items: Ext.applyIf({
|
|
cls: Ext.baseCSSPrefix + 'menu-color-item',
|
|
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',
|
|
|
|
requires: [
|
|
'Ext.picker.Date'
|
|
],
|
|
|
|
|
|
hideOnClick : true,
|
|
|
|
|
|
pickerId : null,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initComponent : function(){
|
|
var me = this;
|
|
|
|
Ext.apply(me, {
|
|
showSeparator: false,
|
|
plain: true,
|
|
border: false,
|
|
bodyPadding: 0,
|
|
items: Ext.applyIf({
|
|
cls: Ext.baseCSSPrefix + 'menu-date-item',
|
|
id: me.pickerId,
|
|
xtype: 'datepicker'
|
|
}, me.initialConfig)
|
|
});
|
|
|
|
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',
|
|
requires: ['Ext.tip.QuickTipManager'],
|
|
alias: 'widget.tool',
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'tool',
|
|
disabledCls: Ext.baseCSSPrefix + 'tool-disabled',
|
|
toolPressedCls: Ext.baseCSSPrefix + 'tool-pressed',
|
|
toolOverCls: Ext.baseCSSPrefix + 'tool-over',
|
|
ariaRole: 'button',
|
|
renderTpl: ['<img id="{id}-toolEl" src="{blank}" class="{baseCls}-{type}" role="presentation"/>'],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tooltipType: 'qtip',
|
|
|
|
|
|
stopEvent: true,
|
|
|
|
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.addChildEls('toolEl');
|
|
|
|
|
|
me.tooltip = me.tooltip || me.qtip;
|
|
me.callParent();
|
|
},
|
|
|
|
|
|
afterRender: function() {
|
|
var me = this,
|
|
attr;
|
|
|
|
me.callParent(arguments);
|
|
if (me.tooltip) {
|
|
if (Ext.isObject(me.tooltip)) {
|
|
Ext.tip.QuickTipManager.register(Ext.apply({
|
|
target: me.id
|
|
}, me.tooltip));
|
|
}
|
|
else {
|
|
attr = me.tooltipType == 'qtip' ? 'data-qtip' : 'title';
|
|
me.toolEl.dom.setAttribute(attr, me.tooltip);
|
|
}
|
|
}
|
|
|
|
me.mon(me.toolEl, {
|
|
click: me.onClick,
|
|
mousedown: me.onMouseDown,
|
|
mouseover: me.onMouseOver,
|
|
mouseout: me.onMouseOut,
|
|
scope: me
|
|
});
|
|
},
|
|
|
|
|
|
setType: function(type) {
|
|
var me = this;
|
|
|
|
me.type = type;
|
|
if (me.rendered) {
|
|
me.toolEl.dom.className = me.baseCls + '-' + type;
|
|
}
|
|
return me;
|
|
},
|
|
|
|
|
|
bindTo: function(component) {
|
|
this.owner = component;
|
|
},
|
|
|
|
|
|
onClick: function(e, target) {
|
|
var me = this,
|
|
owner;
|
|
|
|
if (me.disabled) {
|
|
return false;
|
|
}
|
|
owner = me.owner || me.ownerCt;
|
|
|
|
|
|
me.el.removeCls(me.toolPressedCls);
|
|
me.el.removeCls(me.toolOverCls);
|
|
|
|
if (me.stopEvent !== false) {
|
|
e.stopEvent();
|
|
}
|
|
|
|
Ext.callback(me.handler, me.scope || me, [e, target, owner, me]);
|
|
me.fireEvent('click', me, e);
|
|
return true;
|
|
},
|
|
|
|
|
|
onDestroy: function(){
|
|
if (Ext.isObject(this.tooltip)) {
|
|
Ext.tip.QuickTipManager.unregister(this.id);
|
|
}
|
|
this.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.Handle', {
|
|
extend: 'Ext.Component',
|
|
handleCls: '',
|
|
baseHandleCls: Ext.baseCSSPrefix + 'resizable-handle',
|
|
|
|
|
|
region: '',
|
|
|
|
onRender: function() {
|
|
this.addCls(
|
|
this.baseHandleCls,
|
|
this.baseHandleCls + '-' + this.region,
|
|
this.handleCls
|
|
);
|
|
this.callParent(arguments);
|
|
this.el.unselectable();
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.resizer.Resizer', {
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
uses: ['Ext.resizer.ResizeTracker', 'Ext.Component'],
|
|
|
|
alternateClassName: 'Ext.Resizable',
|
|
|
|
handleCls: Ext.baseCSSPrefix + 'resizable-handle',
|
|
pinnedCls: Ext.baseCSSPrefix + 'resizable-pinned',
|
|
overCls: Ext.baseCSSPrefix + 'resizable-over',
|
|
wrapCls: Ext.baseCSSPrefix + 'resizable-wrap',
|
|
|
|
|
|
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'
|
|
},
|
|
|
|
|
|
|
|
|
|
|
|
constructor: function(config) {
|
|
var me = this,
|
|
target,
|
|
tag,
|
|
handles = me.handles,
|
|
handleCls,
|
|
possibles,
|
|
len,
|
|
i = 0,
|
|
pos;
|
|
|
|
this.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) {
|
|
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 (!this.hasOwnProperty('handles')) {
|
|
this.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;
|
|
if (tag == 'TEXTAREA' || tag == 'IMG') {
|
|
|
|
me.originalTarget = me.target;
|
|
me.target = me.el = me.el.wrap({
|
|
cls: me.wrapCls,
|
|
id: me.el.id + '-rzwrap'
|
|
});
|
|
|
|
|
|
me.el.setPositioning(me.originalTarget.getPositioning());
|
|
me.originalTarget.clearPositioning();
|
|
var box = me.originalTarget.getBox();
|
|
me.el.setBox(box);
|
|
}
|
|
|
|
|
|
|
|
me.el.position();
|
|
if (me.pinned) {
|
|
me.el.addCls(me.pinnedCls);
|
|
}
|
|
|
|
|
|
me.resizeTracker = Ext.create('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, me);
|
|
me.resizeTracker.on('drag', me.onResize, me);
|
|
me.resizeTracker.on('dragend', me.onResizeEnd, me);
|
|
|
|
if (me.handles == 'all') {
|
|
me.handles = 'n s e w ne nw se sw';
|
|
}
|
|
|
|
handles = me.handles = me.handles.split(/ |\s*?[,;]\s*?/);
|
|
possibles = me.possiblePositions;
|
|
len = handles.length;
|
|
handleCls = me.handleCls + ' ' + (this.target.isComponent ? (me.target.baseCls + '-handle ') : '') + me.handleCls + '-';
|
|
|
|
for(; i < len; i++){
|
|
|
|
if (handles[i] && possibles[handles[i]]) {
|
|
pos = possibles[handles[i]];
|
|
|
|
|
|
me[pos] = Ext.create('Ext.Component', {
|
|
owner: this,
|
|
region: pos,
|
|
cls: handleCls + pos,
|
|
renderTo: me.el
|
|
});
|
|
me[pos].el.unselectable();
|
|
if (me.transparent) {
|
|
me[pos].el.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 b = this.target.getBox();
|
|
return this.fireEvent('beforeresize', this, b.width, b.height, e);
|
|
},
|
|
|
|
|
|
onResize: function(tracker, e) {
|
|
var me = this,
|
|
b = me.target.getBox();
|
|
me.forceHandlesHeight();
|
|
return me.fireEvent('resizedrag', me, b.width, b.height, e);
|
|
},
|
|
|
|
|
|
onResizeEnd: function(tracker, e) {
|
|
var me = this,
|
|
b = me.target.getBox();
|
|
me.forceHandlesHeight();
|
|
return me.fireEvent('resize', me, b.width, b.height, e);
|
|
},
|
|
|
|
|
|
resizeTo : function(width, height){
|
|
this.target.setSize(width, height);
|
|
this.fireEvent('resize', this, width, height, null);
|
|
},
|
|
|
|
|
|
getEl : function() {
|
|
return this.el;
|
|
},
|
|
|
|
|
|
getTarget: function() {
|
|
return this.target;
|
|
},
|
|
|
|
destroy: function() {
|
|
var h;
|
|
for (var i = 0, l = this.handles.length; i < l; i++) {
|
|
h = this[this.possiblePositions[this.handles[i]]];
|
|
delete h.owner;
|
|
Ext.destroy(h);
|
|
}
|
|
},
|
|
|
|
|
|
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.resizer.ResizeTracker', {
|
|
extend: 'Ext.dd.DragTracker',
|
|
dynamic: true,
|
|
preserveRatio: false,
|
|
|
|
|
|
constrainTo: null,
|
|
|
|
proxyCls: Ext.baseCSSPrefix + 'resizable-proxy',
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
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) {
|
|
var 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) {
|
|
var 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.el.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,
|
|
renderTo;
|
|
|
|
if (target.isComponent) {
|
|
proxy = target.getProxy().addCls(cls);
|
|
} else {
|
|
renderTo = Ext.getBody();
|
|
if (Ext.scopeResetCSS) {
|
|
renderTo = Ext.getBody().createChild({
|
|
cls: Ext.baseCSSPrefix + 'reset'
|
|
});
|
|
}
|
|
proxy = target.createProxy({
|
|
tag: 'div',
|
|
cls: cls,
|
|
id: target.id + '-rzproxy'
|
|
}, renderTo);
|
|
}
|
|
proxy.removeCls(Ext.baseCSSPrefix + 'proxy-el');
|
|
return proxy;
|
|
},
|
|
|
|
onStart: function(e) {
|
|
|
|
this.activeResizeHandle = Ext.getCmp(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;
|
|
|
|
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;
|
|
}
|
|
|
|
var 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) {
|
|
var newHeight,
|
|
newWidth;
|
|
|
|
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 target = this.getResizeTarget(atEnd);
|
|
if (target.isComponent) {
|
|
if (target.floating) {
|
|
target.setPagePosition(box.x, box.y);
|
|
}
|
|
target.setSize(box.width, box.height);
|
|
} else {
|
|
target.setBox(box);
|
|
|
|
if (this.originalTarget) {
|
|
this.originalTarget.setBox(box);
|
|
}
|
|
}
|
|
},
|
|
|
|
onEnd: function(e) {
|
|
this.updateDimensions(e, true);
|
|
if (this.proxy) {
|
|
this.proxy.hide();
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.resizer.SplitterTracker', {
|
|
extend: 'Ext.dd.DragTracker',
|
|
requires: ['Ext.util.Region'],
|
|
enabled: true,
|
|
|
|
overlayCls: Ext.baseCSSPrefix + 'resizable-overlay',
|
|
|
|
getPrevCmp: function() {
|
|
var splitter = this.getSplitter();
|
|
return splitter.previousSibling();
|
|
},
|
|
|
|
getNextCmp: function() {
|
|
var splitter = this.getSplitter();
|
|
return splitter.nextSibling();
|
|
},
|
|
|
|
|
|
|
|
onBeforeStart: function(e) {
|
|
var me = this,
|
|
prevCmp = me.getPrevCmp(),
|
|
nextCmp = me.getNextCmp(),
|
|
collapseEl = me.getSplitter().collapseEl,
|
|
overlay;
|
|
|
|
if (collapseEl && (e.getTarget() === me.getSplitter().collapseEl.dom)) {
|
|
return false;
|
|
}
|
|
|
|
|
|
if (nextCmp.collapsed || prevCmp.collapsed) {
|
|
return false;
|
|
}
|
|
|
|
overlay = me.overlay = Ext.getBody().createChild({
|
|
cls: me.overlayCls,
|
|
html: ' '
|
|
});
|
|
overlay.unselectable();
|
|
overlay.setSize(Ext.Element.getViewWidth(true), Ext.Element.getViewHeight(true));
|
|
overlay.show();
|
|
|
|
|
|
me.prevBox = prevCmp.getEl().getBox();
|
|
me.nextBox = nextCmp.getEl().getBox();
|
|
me.constrainTo = me.calculateConstrainRegion();
|
|
},
|
|
|
|
|
|
onStart: function(e) {
|
|
var splitter = this.getSplitter();
|
|
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;
|
|
|
|
|
|
if (orient === 'vertical') {
|
|
|
|
|
|
|
|
prevConstrainRegion = Ext.create('Ext.util.Region',
|
|
prevBox.y,
|
|
|
|
|
|
(prevCmp.maxWidth ? prevBox.x + prevCmp.maxWidth : nextBox.right - (nextCmp.minWidth || defaultMin)) + splitWidth,
|
|
prevBox.bottom,
|
|
prevBox.x + (prevCmp.minWidth || defaultMin)
|
|
);
|
|
|
|
nextConstrainRegion = Ext.create('Ext.util.Region',
|
|
nextBox.y,
|
|
nextBox.right - (nextCmp.minWidth || defaultMin),
|
|
nextBox.bottom,
|
|
|
|
|
|
(nextCmp.maxWidth ? nextBox.right - nextCmp.maxWidth : prevBox.x + (prevBox.minWidth || defaultMin)) - splitWidth
|
|
);
|
|
} else {
|
|
|
|
prevConstrainRegion = Ext.create('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 = Ext.create('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) {
|
|
var me = this,
|
|
offset = me.getOffset('dragTarget'),
|
|
splitter = me.getSplitter(),
|
|
orient = splitter.orientation,
|
|
prevCmp = me.getPrevCmp(),
|
|
nextCmp = me.getNextCmp(),
|
|
owner = splitter.ownerCt,
|
|
layout = owner.getLayout();
|
|
|
|
|
|
owner.suspendLayout = true;
|
|
|
|
if (orient === 'vertical') {
|
|
if (prevCmp) {
|
|
if (!prevCmp.maintainFlex) {
|
|
delete prevCmp.flex;
|
|
prevCmp.setSize(me.prevBox.width + offset[0], prevCmp.getHeight());
|
|
}
|
|
}
|
|
if (nextCmp) {
|
|
if (!nextCmp.maintainFlex) {
|
|
delete nextCmp.flex;
|
|
nextCmp.setSize(me.nextBox.width - offset[0], nextCmp.getHeight());
|
|
}
|
|
}
|
|
|
|
} else {
|
|
if (prevCmp) {
|
|
if (!prevCmp.maintainFlex) {
|
|
delete prevCmp.flex;
|
|
prevCmp.setSize(prevCmp.getWidth(), me.prevBox.height + offset[1]);
|
|
}
|
|
}
|
|
if (nextCmp) {
|
|
if (!nextCmp.maintainFlex) {
|
|
delete nextCmp.flex;
|
|
nextCmp.setSize(prevCmp.getWidth(), me.nextBox.height - offset[1]);
|
|
}
|
|
}
|
|
}
|
|
delete owner.suspendLayout;
|
|
layout.onLayout();
|
|
},
|
|
|
|
|
|
|
|
|
|
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();
|
|
},
|
|
|
|
|
|
|
|
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 Ext.getCmp(this.getDragCt().id);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.selection.CellModel', {
|
|
extend: 'Ext.selection.Model',
|
|
alias: 'selection.cellmodel',
|
|
requires: ['Ext.util.KeyNav'],
|
|
|
|
|
|
enableKeyNav: true,
|
|
|
|
|
|
preventWrap: false,
|
|
|
|
constructor: function(){
|
|
this.addEvents(
|
|
|
|
'deselect',
|
|
|
|
|
|
'select'
|
|
);
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
bindComponent: function(view) {
|
|
var me = this;
|
|
me.primaryView = view;
|
|
me.views = me.views || [];
|
|
me.views.push(view);
|
|
me.bind(view.getStore(), true);
|
|
|
|
view.on({
|
|
cellmousedown: me.onMouseDown,
|
|
refresh: me.onViewRefresh,
|
|
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 = Ext.create('Ext.util.KeyNav', view.el, {
|
|
up: me.onKeyUp,
|
|
down: me.onKeyDown,
|
|
right: me.onKeyRight,
|
|
left: me.onKeyLeft,
|
|
tab: me.onKeyTab,
|
|
scope: me
|
|
});
|
|
},
|
|
|
|
getHeaderCt: function() {
|
|
return this.primaryView.headerCt;
|
|
},
|
|
|
|
onKeyUp: function(e, t) {
|
|
this.move('up', e);
|
|
},
|
|
|
|
onKeyDown: function(e, t) {
|
|
this.move('down', e);
|
|
},
|
|
|
|
onKeyLeft: function(e, t) {
|
|
this.move('left', e);
|
|
},
|
|
|
|
onKeyRight: function(e, t) {
|
|
this.move('right', e);
|
|
},
|
|
|
|
move: function(dir, e) {
|
|
var me = this,
|
|
pos = me.primaryView.walkCells(me.getCurrentPosition(), dir, e, me.preventWrap);
|
|
if (pos) {
|
|
me.setCurrentPosition(pos);
|
|
}
|
|
return pos;
|
|
},
|
|
|
|
|
|
getCurrentPosition: function() {
|
|
return this.position;
|
|
},
|
|
|
|
|
|
setCurrentPosition: function(pos) {
|
|
var me = this;
|
|
|
|
if (me.position) {
|
|
me.onCellDeselect(me.position);
|
|
}
|
|
if (pos) {
|
|
me.onCellSelect(pos);
|
|
}
|
|
me.position = pos;
|
|
},
|
|
|
|
|
|
onMouseDown: function(view, cell, cellIndex, record, row, rowIndex, e) {
|
|
this.setCurrentPosition({
|
|
row: rowIndex,
|
|
column: cellIndex
|
|
});
|
|
},
|
|
|
|
|
|
|
|
onCellSelect: function(position) {
|
|
var me = this,
|
|
store = me.view.getStore(),
|
|
record = store.getAt(position.row);
|
|
|
|
me.doSelect(record);
|
|
me.primaryView.onCellSelect(position);
|
|
|
|
me.primaryView.onCellFocus(position);
|
|
me.fireEvent('select', me, record, position.row, position.column);
|
|
},
|
|
|
|
|
|
|
|
onCellDeselect: function(position) {
|
|
var me = this,
|
|
store = me.view.getStore(),
|
|
record = store.getAt(position.row);
|
|
|
|
me.doDeselect(record);
|
|
me.primaryView.onCellDeselect(position);
|
|
me.fireEvent('deselect', me, record, position.row, position.column);
|
|
},
|
|
|
|
onKeyTab: function(e, t) {
|
|
var me = this,
|
|
direction = e.shiftKey ? 'left' : 'right',
|
|
editingPlugin = me.view.editingPlugin,
|
|
position = me.move(direction, e);
|
|
|
|
if (editingPlugin && position && me.wasEditing) {
|
|
editingPlugin.startEditByPosition(position);
|
|
}
|
|
delete me.wasEditing;
|
|
},
|
|
|
|
onEditorTab: function(editingPlugin, e) {
|
|
var me = this,
|
|
direction = e.shiftKey ? 'left' : 'right',
|
|
position = me.move(direction, e);
|
|
|
|
if (position) {
|
|
editingPlugin.startEditByPosition(position);
|
|
me.wasEditing = true;
|
|
}
|
|
},
|
|
|
|
refresh: function() {
|
|
var pos = this.getCurrentPosition();
|
|
if (pos) {
|
|
this.onCellSelect(pos);
|
|
}
|
|
},
|
|
|
|
onViewRefresh: function() {
|
|
var pos = this.getCurrentPosition();
|
|
if (pos) {
|
|
this.onCellDeselect(pos);
|
|
this.setCurrentPosition(null);
|
|
}
|
|
},
|
|
|
|
selectByPosition: function(position) {
|
|
this.setCurrentPosition(position);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.selection.RowModel', {
|
|
extend: 'Ext.selection.Model',
|
|
alias: 'selection.rowmodel',
|
|
requires: ['Ext.util.KeyNav'],
|
|
|
|
|
|
deltaScroll: 5,
|
|
|
|
|
|
enableKeyNav: true,
|
|
|
|
|
|
ignoreRightMouseSelection: true,
|
|
|
|
constructor: function(){
|
|
this.addEvents(
|
|
|
|
'beforedeselect',
|
|
|
|
|
|
'beforeselect',
|
|
|
|
|
|
'deselect',
|
|
|
|
|
|
'select'
|
|
);
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
bindComponent: function(view) {
|
|
var me = this;
|
|
|
|
me.views = me.views || [];
|
|
me.views.push(view);
|
|
me.bind(view.getStore(), true);
|
|
|
|
view.on({
|
|
itemmousedown: me.onRowMouseDown,
|
|
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(view.el, {
|
|
up: me.onKeyUp,
|
|
down: me.onKeyDown,
|
|
right: me.onKeyRight,
|
|
left: me.onKeyLeft,
|
|
pageDown: me.onKeyPageDown,
|
|
pageUp: me.onKeyPageUp,
|
|
home: me.onKeyHome,
|
|
end: me.onKeyEnd,
|
|
scope: me
|
|
});
|
|
view.el.on(Ext.EventManager.getKeyEvent(), me.onKeyPress, me);
|
|
},
|
|
|
|
|
|
|
|
|
|
getRowsVisible: function() {
|
|
var rowsVisible = false,
|
|
view = this.views[0],
|
|
row = view.getNode(0),
|
|
rowHeight, gridViewHeight;
|
|
|
|
if (row) {
|
|
rowHeight = Ext.fly(row).getHeight();
|
|
gridViewHeight = view.el.getHeight();
|
|
rowsVisible = Math.floor(gridViewHeight / rowHeight);
|
|
}
|
|
|
|
return rowsVisible;
|
|
},
|
|
|
|
|
|
onKeyEnd: function(e, t) {
|
|
var me = this,
|
|
last = me.store.getAt(me.store.getCount() - 1);
|
|
|
|
if (last) {
|
|
if (e.shiftKey) {
|
|
me.selectRange(last, me.lastFocused || 0);
|
|
me.setLastFocused(last);
|
|
} else if (e.ctrlKey) {
|
|
me.setLastFocused(last);
|
|
} else {
|
|
me.doSelect(last);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onKeyHome: function(e, t) {
|
|
var me = this,
|
|
first = me.store.getAt(0);
|
|
|
|
if (first) {
|
|
if (e.shiftKey) {
|
|
me.selectRange(first, me.lastFocused || 0);
|
|
me.setLastFocused(first);
|
|
} else if (e.ctrlKey) {
|
|
me.setLastFocused(first);
|
|
} else {
|
|
me.doSelect(first, false);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onKeyPageUp: function(e, t) {
|
|
var me = this,
|
|
rowsVisible = me.getRowsVisible(),
|
|
selIdx,
|
|
prevIdx,
|
|
prevRecord,
|
|
currRec;
|
|
|
|
if (rowsVisible) {
|
|
selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
|
|
prevIdx = selIdx - rowsVisible;
|
|
if (prevIdx < 0) {
|
|
prevIdx = 0;
|
|
}
|
|
prevRecord = me.store.getAt(prevIdx);
|
|
if (e.shiftKey) {
|
|
currRec = me.store.getAt(selIdx);
|
|
me.selectRange(prevRecord, currRec, e.ctrlKey, 'up');
|
|
me.setLastFocused(prevRecord);
|
|
} else if (e.ctrlKey) {
|
|
e.preventDefault();
|
|
me.setLastFocused(prevRecord);
|
|
} else {
|
|
me.doSelect(prevRecord);
|
|
}
|
|
|
|
}
|
|
},
|
|
|
|
|
|
onKeyPageDown: function(e, t) {
|
|
var me = this,
|
|
rowsVisible = me.getRowsVisible(),
|
|
selIdx,
|
|
nextIdx,
|
|
nextRecord,
|
|
currRec;
|
|
|
|
if (rowsVisible) {
|
|
selIdx = me.lastFocused ? me.store.indexOf(me.lastFocused) : 0;
|
|
nextIdx = selIdx + rowsVisible;
|
|
if (nextIdx >= me.store.getCount()) {
|
|
nextIdx = me.store.getCount() - 1;
|
|
}
|
|
nextRecord = me.store.getAt(nextIdx);
|
|
if (e.shiftKey) {
|
|
currRec = me.store.getAt(selIdx);
|
|
me.selectRange(nextRecord, currRec, e.ctrlKey, 'down');
|
|
me.setLastFocused(nextRecord);
|
|
} else if (e.ctrlKey) {
|
|
|
|
|
|
e.preventDefault();
|
|
me.setLastFocused(nextRecord);
|
|
} else {
|
|
me.doSelect(nextRecord);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
|
|
onKeyPress: function(e, t) {
|
|
if (e.getKey() === e.SPACE) {
|
|
e.stopEvent();
|
|
var me = this,
|
|
record = me.lastFocused;
|
|
|
|
if (record) {
|
|
if (me.isSelected(record)) {
|
|
me.doDeselect(record, false);
|
|
} else {
|
|
me.doSelect(record, true);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
|
|
|
|
onKeyUp: function(e, t) {
|
|
var me = this,
|
|
view = me.views[0],
|
|
idx = me.store.indexOf(me.lastFocused),
|
|
record;
|
|
|
|
if (idx > 0) {
|
|
|
|
|
|
record = me.store.getAt(idx - 1);
|
|
if (e.shiftKey && me.lastFocused) {
|
|
if (me.isSelected(me.lastFocused) && me.isSelected(record)) {
|
|
me.doDeselect(me.lastFocused, true);
|
|
me.setLastFocused(record);
|
|
} else if (!me.isSelected(me.lastFocused)) {
|
|
me.doSelect(me.lastFocused, true);
|
|
me.doSelect(record, true);
|
|
} else {
|
|
me.doSelect(record, true);
|
|
}
|
|
} else if (e.ctrlKey) {
|
|
me.setLastFocused(record);
|
|
} else {
|
|
me.doSelect(record);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
onKeyDown: function(e, t) {
|
|
var me = this,
|
|
view = me.views[0],
|
|
idx = me.store.indexOf(me.lastFocused),
|
|
record;
|
|
|
|
|
|
|
|
if (idx + 1 < me.store.getCount()) {
|
|
record = me.store.getAt(idx + 1);
|
|
if (me.selected.getCount() === 0) {
|
|
me.doSelect(record);
|
|
|
|
} else if (e.shiftKey && me.lastFocused) {
|
|
if (me.isSelected(me.lastFocused) && me.isSelected(record)) {
|
|
me.doDeselect(me.lastFocused, true);
|
|
me.setLastFocused(record);
|
|
} else if (!me.isSelected(me.lastFocused)) {
|
|
me.doSelect(me.lastFocused, true);
|
|
me.doSelect(record, true);
|
|
} else {
|
|
me.doSelect(record, true);
|
|
}
|
|
} else if (e.ctrlKey) {
|
|
me.setLastFocused(record);
|
|
} else {
|
|
me.doSelect(record);
|
|
|
|
}
|
|
}
|
|
},
|
|
|
|
scrollByDeltaX: function(delta) {
|
|
var view = this.views[0],
|
|
section = view.up(),
|
|
hScroll = section.horizontalScroller;
|
|
|
|
if (hScroll) {
|
|
hScroll.scrollByDeltaX(delta);
|
|
}
|
|
},
|
|
|
|
onKeyLeft: function(e, t) {
|
|
this.scrollByDeltaX(-this.deltaScroll);
|
|
},
|
|
|
|
onKeyRight: function(e, t) {
|
|
this.scrollByDeltaX(this.deltaScroll);
|
|
},
|
|
|
|
|
|
|
|
onRowMouseDown: function(view, record, item, index, e) {
|
|
view.el.focus();
|
|
if (!this.allowRightMouseSelection(e)) {
|
|
return;
|
|
}
|
|
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,
|
|
store = me.store,
|
|
rowIdx = store.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,
|
|
store = this.store,
|
|
rowIdx,
|
|
i = 0;
|
|
|
|
if (oldFocused) {
|
|
rowIdx = store.indexOf(oldFocused);
|
|
if (rowIdx != -1) {
|
|
for (; i < viewsLn; i++) {
|
|
views[i].onRowFocus(rowIdx, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (newFocused) {
|
|
rowIdx = store.indexOf(newFocused);
|
|
if (rowIdx != -1) {
|
|
for (i = 0; i < viewsLn; i++) {
|
|
views[i].onRowFocus(rowIdx, true, supressFocus);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
onEditorTab: function(editingPlugin, e) {
|
|
var me = this,
|
|
view = me.views[0],
|
|
record = editingPlugin.getActiveRecord(),
|
|
header = editingPlugin.getActiveColumn(),
|
|
position = view.getPosition(record, header),
|
|
direction = e.shiftKey ? 'left' : 'right',
|
|
newPosition = view.walkCells(position, direction, e, this.preventWrap);
|
|
|
|
if (newPosition) {
|
|
editingPlugin.startEditByPosition(newPosition);
|
|
}
|
|
},
|
|
|
|
selectByPosition: function(position) {
|
|
var record = this.store.getAt(position.row);
|
|
this.select(record);
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.selection.CheckboxModel', {
|
|
alias: 'selection.checkboxmodel',
|
|
extend: 'Ext.selection.RowModel',
|
|
|
|
|
|
mode: 'MULTI',
|
|
|
|
|
|
injectCheckbox: 0,
|
|
|
|
|
|
checkOnly: false,
|
|
|
|
headerWidth: 24,
|
|
|
|
|
|
checkerOnCls: Ext.baseCSSPrefix + 'grid-hd-checker-on',
|
|
|
|
bindComponent: function(view) {
|
|
var me = this;
|
|
|
|
me.sortable = false;
|
|
me.callParent(arguments);
|
|
if (!me.hasLockedHeader() || view.headerCt.lockedCt) {
|
|
|
|
view.headerCt.on('headerclick', me.onHeaderClick, me);
|
|
me.addCheckbox(true);
|
|
me.mon(view.ownerCt, 'reconfigure', me.addCheckbox, me);
|
|
}
|
|
},
|
|
|
|
hasLockedHeader: function(){
|
|
var hasLocked = false;
|
|
Ext.each(this.views, function(view){
|
|
if (view.headerCt.lockedCt) {
|
|
hasLocked = true;
|
|
return false;
|
|
}
|
|
});
|
|
return hasLocked;
|
|
},
|
|
|
|
|
|
addCheckbox: function(initial){
|
|
var me = this,
|
|
checkbox = me.injectCheckbox,
|
|
view = me.views[0],
|
|
headerCt = view.headerCt;
|
|
|
|
if (checkbox !== false) {
|
|
if (checkbox == 'first') {
|
|
checkbox = 0;
|
|
} else if (checkbox == 'last') {
|
|
checkbox = headerCt.getColumnCount();
|
|
}
|
|
headerCt.add(checkbox, me.getHeaderConfig());
|
|
}
|
|
|
|
if (initial !== true) {
|
|
view.refresh();
|
|
}
|
|
},
|
|
|
|
|
|
toggleUiHeader: function(isChecked) {
|
|
var view = this.views[0],
|
|
headerCt = view.headerCt,
|
|
checkHd = headerCt.child('gridcolumn[isCheckerHd]');
|
|
|
|
if (checkHd) {
|
|
if (isChecked) {
|
|
checkHd.el.addCls(this.checkerOnCls);
|
|
} else {
|
|
checkHd.el.removeCls(this.checkerOnCls);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onHeaderClick: function(headerCt, header, e) {
|
|
if (header.isCheckerHd) {
|
|
e.stopEvent();
|
|
var isChecked = header.el.hasCls(Ext.baseCSSPrefix + 'grid-hd-checker-on');
|
|
if (isChecked) {
|
|
|
|
this.deselectAll(true);
|
|
} else {
|
|
|
|
this.selectAll(true);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getHeaderConfig: function() {
|
|
var me = this;
|
|
|
|
return {
|
|
isCheckerHd: true,
|
|
text : ' ',
|
|
width: me.headerWidth,
|
|
sortable: false,
|
|
draggable: false,
|
|
resizable: false,
|
|
hideable: false,
|
|
menuDisabled: true,
|
|
dataIndex: '',
|
|
cls: Ext.baseCSSPrefix + 'column-header-checkbox ',
|
|
renderer: Ext.Function.bind(me.renderer, me),
|
|
locked: me.hasLockedHeader()
|
|
};
|
|
},
|
|
|
|
|
|
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
|
|
metaData.tdCls = Ext.baseCSSPrefix + 'grid-cell-special';
|
|
return '<div class="' + Ext.baseCSSPrefix + 'grid-row-checker"> </div>';
|
|
},
|
|
|
|
|
|
onRowMouseDown: function(view, record, item, index, e) {
|
|
view.el.focus();
|
|
var me = this,
|
|
checker = e.getTarget('.' + Ext.baseCSSPrefix + 'grid-row-checker');
|
|
|
|
if (!me.allowRightMouseSelection(e)) {
|
|
return;
|
|
}
|
|
|
|
|
|
if (me.checkOnly && !checker) {
|
|
return;
|
|
}
|
|
|
|
if (checker) {
|
|
var 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);
|
|
|
|
|
|
var hdSelectStatus = this.selected.getCount() === this.store.getCount();
|
|
this.toggleUiHeader(hdSelectStatus);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.selection.TreeModel', {
|
|
extend: 'Ext.selection.RowModel',
|
|
alias: 'selection.treemodel',
|
|
|
|
|
|
|
|
|
|
pruneRemoved: false,
|
|
|
|
onKeyRight: function(e, t) {
|
|
var focused = this.getLastFocused(),
|
|
view = this.view;
|
|
|
|
if (focused) {
|
|
|
|
|
|
|
|
if (focused.isExpanded()) {
|
|
this.onKeyDown(e, t);
|
|
|
|
} else if (!focused.isLeaf()) {
|
|
view.expand(focused);
|
|
}
|
|
}
|
|
},
|
|
|
|
onKeyLeft: function(e, t) {
|
|
var focused = this.getLastFocused(),
|
|
view = this.view,
|
|
viewSm = view.getSelectionModel(),
|
|
parentNode, parentRecord;
|
|
|
|
if (focused) {
|
|
parentNode = focused.parentNode;
|
|
|
|
if (focused.isExpanded()) {
|
|
view.collapse(focused);
|
|
|
|
|
|
} else if (parentNode && !parentNode.isRoot()) {
|
|
|
|
if (e.shiftKey) {
|
|
viewSm.selectRange(parentNode, focused, e.ctrlKey, 'up');
|
|
viewSm.setLastFocused(parentNode);
|
|
|
|
} else if (e.ctrlKey) {
|
|
viewSm.setLastFocused(parentNode);
|
|
|
|
} else {
|
|
viewSm.select(parentNode);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
onKeyPress: function(e, t) {
|
|
var key = e.getKey(),
|
|
selected,
|
|
checked;
|
|
|
|
if (key === e.SPACE || key === e.ENTER) {
|
|
e.stopEvent();
|
|
selected = this.getLastSelected();
|
|
if (selected) {
|
|
this.view.onCheckChange(selected);
|
|
}
|
|
} else {
|
|
this.callParent(arguments);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.slider.Thumb', {
|
|
requires: ['Ext.dd.DragTracker', 'Ext.util.Format'],
|
|
|
|
topZIndex: 10000,
|
|
|
|
|
|
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
|
|
Ext.apply(me, config || {}, {
|
|
cls: Ext.baseCSSPrefix + 'slider-thumb',
|
|
|
|
|
|
constrain: false
|
|
});
|
|
me.callParent([config]);
|
|
|
|
if (me.slider.vertical) {
|
|
Ext.apply(me, Ext.slider.Thumb.Vertical);
|
|
}
|
|
},
|
|
|
|
|
|
render: function() {
|
|
var me = this;
|
|
|
|
me.el = me.slider.innerEl.insertFirst({cls: me.cls});
|
|
if (me.disabled) {
|
|
me.disable();
|
|
}
|
|
me.initEvents();
|
|
},
|
|
|
|
|
|
move: function(v, animate){
|
|
if(!animate){
|
|
this.el.setLeft(v);
|
|
}else{
|
|
Ext.create('Ext.fx.Anim', {
|
|
target: this.el,
|
|
duration: 350,
|
|
to: {
|
|
left: v
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
|
|
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 = Ext.create('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;
|
|
|
|
me.el.addCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
|
|
me.dragging = true;
|
|
me.dragStartValue = me.value;
|
|
|
|
me.slider.fireEvent('dragstart', me.slider, e, me);
|
|
},
|
|
|
|
|
|
onDrag: function(e) {
|
|
var me = this,
|
|
slider = me.slider,
|
|
index = me.index,
|
|
newValue = me.getNewValue(),
|
|
above,
|
|
below;
|
|
|
|
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);
|
|
},
|
|
|
|
getNewValue: function() {
|
|
var slider = this.slider,
|
|
pos = slider.innerEl.translatePoints(this.tracker.getXY());
|
|
|
|
return Ext.util.Format.round(slider.reverseValue(pos.left), slider.decimalPrecision);
|
|
},
|
|
|
|
|
|
onDragEnd: function(e) {
|
|
var me = this,
|
|
slider = me.slider,
|
|
value = me.value;
|
|
|
|
me.el.removeCls(Ext.baseCSSPrefix + 'slider-thumb-drag');
|
|
|
|
me.dragging = false;
|
|
slider.fireEvent('dragend', slider, e);
|
|
|
|
if (me.dragStartValue != value) {
|
|
slider.fireEvent('changecomplete', slider, value, me);
|
|
}
|
|
},
|
|
|
|
destroy: function() {
|
|
Ext.destroy(this.tracker);
|
|
},
|
|
statics: {
|
|
|
|
Vertical: {
|
|
getNewValue: function() {
|
|
var slider = this.slider,
|
|
innerEl = slider.innerEl,
|
|
pos = innerEl.translatePoints(this.tracker.getXY()),
|
|
bottom = innerEl.getHeight() - pos.top;
|
|
|
|
return Ext.util.Format.round(slider.reverseValue(bottom), slider.decimalPrecision);
|
|
},
|
|
move: function(v, animate) {
|
|
if (!animate) {
|
|
this.el.setBottom(v);
|
|
} else {
|
|
Ext.create('Ext.fx.Anim', {
|
|
target: this.el,
|
|
duration: 350,
|
|
to: {
|
|
bottom: v
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.slider.Tip', {
|
|
extend: 'Ext.tip.Tip',
|
|
minWidth: 10,
|
|
alias: 'widget.slidertip',
|
|
offsets : [0, -10],
|
|
|
|
isSliderTip: true,
|
|
|
|
init: function(slider) {
|
|
var me = this;
|
|
|
|
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.doComponentLayout();
|
|
me.el.alignTo(thumb.el, 'b-t?', 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',
|
|
|
|
requires: [
|
|
'Ext.slider.Thumb',
|
|
'Ext.slider.Tip',
|
|
'Ext.Number',
|
|
'Ext.util.Format',
|
|
'Ext.Template',
|
|
'Ext.layout.component.field.Slider'
|
|
],
|
|
|
|
|
|
fieldSubTpl: [
|
|
'<div id="{id}" class="' + Ext.baseCSSPrefix + 'slider {fieldCls} {vertical}" aria-valuemin="{minValue}" aria-valuemax="{maxValue}" aria-valuenow="{value}" aria-valuetext="{value}">',
|
|
'<div id="{cmpId}-endEl" class="' + Ext.baseCSSPrefix + 'slider-end" role="presentation">',
|
|
'<div id="{cmpId}-innerEl" class="' + Ext.baseCSSPrefix + 'slider-inner" role="presentation">',
|
|
'<a id="{cmpId}-focusEl" class="' + Ext.baseCSSPrefix + 'slider-focus" href="#" tabIndex="-1" hidefocus="on" role="presentation"></a>',
|
|
'</div>',
|
|
'</div>',
|
|
'</div>',
|
|
{
|
|
disableFormats: true,
|
|
compiled: true
|
|
}
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
me.thumbs = [];
|
|
|
|
me.keyIncrement = Math.max(me.increment, me.keyIncrement);
|
|
|
|
me.addEvents(
|
|
|
|
'beforechange',
|
|
|
|
|
|
'change',
|
|
|
|
|
|
'changecomplete',
|
|
|
|
|
|
'dragstart',
|
|
|
|
|
|
'drag',
|
|
|
|
|
|
'dragend'
|
|
);
|
|
|
|
if (me.vertical) {
|
|
Ext.apply(me, Ext.slider.Multi.Vertical);
|
|
}
|
|
|
|
me.callParent();
|
|
|
|
|
|
if (me.useTips) {
|
|
tipPlug = me.tipText ? {getText: me.tipText} : {};
|
|
me.plugins = me.plugins || [];
|
|
Ext.each(me.plugins, function(plug){
|
|
if (plug.isSliderTip) {
|
|
hasTip = true;
|
|
return false;
|
|
}
|
|
});
|
|
if (!hasTip) {
|
|
me.plugins.push(Ext.create('Ext.slider.Tip', tipPlug));
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
addThumb: function(value) {
|
|
var me = this,
|
|
thumb = Ext.create('Ext.slider.Thumb', {
|
|
value : value,
|
|
slider : me,
|
|
index : me.thumbs.length,
|
|
constrain: me.constrainThumbs
|
|
});
|
|
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();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
onRender : function() {
|
|
var me = this,
|
|
i = 0,
|
|
thumbs = me.thumbs,
|
|
len = thumbs.length,
|
|
thumb;
|
|
|
|
Ext.applyIf(me.subTplData, {
|
|
vertical: me.vertical ? Ext.baseCSSPrefix + 'slider-vert' : Ext.baseCSSPrefix + 'slider-horz',
|
|
minValue: me.minValue,
|
|
maxValue: me.maxValue,
|
|
value: me.value
|
|
});
|
|
|
|
me.addChildEls('endEl', 'innerEl', 'focusEl');
|
|
|
|
me.callParent(arguments);
|
|
|
|
|
|
for (; i < len; i++) {
|
|
thumbs[i].render();
|
|
}
|
|
|
|
|
|
thumb = me.innerEl.down('.' + Ext.baseCSSPrefix + 'slider-thumb');
|
|
me.halfThumb = (me.vertical ? thumb.getHeight() : thumb.getWidth()) / 2;
|
|
|
|
},
|
|
|
|
|
|
onChange : function(slider, v) {
|
|
this.setValue(v, undefined, true);
|
|
},
|
|
|
|
|
|
initEvents : function() {
|
|
var me = this;
|
|
|
|
me.mon(me.el, {
|
|
scope : me,
|
|
mousedown: me.onMouseDown,
|
|
keydown : me.onKeyDown,
|
|
change : me.onChange
|
|
});
|
|
|
|
me.focusEl.swallowEvent("click", true);
|
|
},
|
|
|
|
|
|
onMouseDown : function(e) {
|
|
var me = this,
|
|
thumbClicked = false,
|
|
i = 0,
|
|
thumbs = me.thumbs,
|
|
len = thumbs.length,
|
|
local;
|
|
|
|
if (me.disabled) {
|
|
return;
|
|
}
|
|
|
|
|
|
for (; i < len; i++) {
|
|
thumbClicked = thumbClicked || e.target == thumbs[i].el.dom;
|
|
}
|
|
|
|
if (me.clickToChange && !thumbClicked) {
|
|
local = me.innerEl.translatePoints(e.getXY());
|
|
me.onClickChange(local);
|
|
}
|
|
me.focus();
|
|
},
|
|
|
|
|
|
onClickChange : function(local) {
|
|
var me = this,
|
|
thumb, index;
|
|
|
|
if (local.top > me.clickRange[0] && local.top < me.clickRange[1]) {
|
|
|
|
thumb = me.getNearest(local, 'left');
|
|
if (!thumb.disabled) {
|
|
index = thumb.index;
|
|
me.setValue(index, Ext.util.Format.round(me.reverseValue(local.left), me.decimalPrecision), undefined, true);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getNearest: function(local, prop) {
|
|
var me = this,
|
|
localValue = prop == 'top' ? me.innerEl.getHeight() - local[prop] : local[prop],
|
|
clickValue = me.reverseValue(localValue),
|
|
nearestDistance = (me.maxValue - me.minValue) + 5,
|
|
index = 0,
|
|
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;
|
|
index = i;
|
|
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();
|
|
}
|
|
},
|
|
|
|
|
|
afterRender : function() {
|
|
var me = this,
|
|
i = 0,
|
|
thumbs = me.thumbs,
|
|
len = thumbs.length,
|
|
thumb,
|
|
v;
|
|
|
|
me.callParent(arguments);
|
|
|
|
for (; i < len; i++) {
|
|
thumb = thumbs[i];
|
|
|
|
if (thumb.value !== undefined) {
|
|
v = me.normalizeValue(thumb.value);
|
|
if (v !== thumb.value) {
|
|
|
|
me.setValue(i, v, false);
|
|
} else {
|
|
thumb.move(me.translateValue(v), false);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getRatio : function() {
|
|
var w = this.innerEl.getWidth(),
|
|
v = this.maxValue - this.minValue;
|
|
return v === 0 ? w : (w/v);
|
|
},
|
|
|
|
|
|
normalizeValue : function(v) {
|
|
var me = this;
|
|
|
|
v = Ext.Number.snap(v, this.increment, this.minValue, this.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,
|
|
i = 0,
|
|
thumbs = me.thumbs,
|
|
len = thumbs.length,
|
|
t;
|
|
|
|
me.minValue = val;
|
|
if (me.rendered) {
|
|
me.inputEl.dom.setAttribute('aria-valuemin', val);
|
|
}
|
|
|
|
for (; i < len; ++i) {
|
|
t = thumbs[i];
|
|
t.value = t.value < val ? val : t.value;
|
|
}
|
|
me.syncThumbs();
|
|
},
|
|
|
|
|
|
setMaxValue : function(val) {
|
|
var me = this,
|
|
i = 0,
|
|
thumbs = me.thumbs,
|
|
len = thumbs.length,
|
|
t;
|
|
|
|
me.maxValue = val;
|
|
if (me.rendered) {
|
|
me.inputEl.dom.setAttribute('aria-valuemax', val);
|
|
}
|
|
|
|
for (; i < len; ++i) {
|
|
t = thumbs[i];
|
|
t.value = t.value > val ? val : t.value;
|
|
}
|
|
me.syncThumbs();
|
|
},
|
|
|
|
|
|
setValue : function(index, value, animate, changeComplete) {
|
|
var me = this,
|
|
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) {
|
|
|
|
|
|
me.inputEl.set({
|
|
'aria-valuenow': value,
|
|
'aria-valuetext': value
|
|
});
|
|
|
|
thumb.move(me.translateValue(value), Ext.isDefined(animate) ? animate !== false : me.animate);
|
|
|
|
me.fireEvent('change', me, value, thumb);
|
|
if (changeComplete) {
|
|
me.fireEvent('changecomplete', me, value, thumb);
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
translateValue : function(v) {
|
|
var ratio = this.getRatio();
|
|
return (v * ratio) - (this.minValue * ratio) - this.halfThumb;
|
|
},
|
|
|
|
|
|
reverseValue : function(pos) {
|
|
var ratio = this.getRatio();
|
|
return (pos + (this.minValue * ratio)) / ratio;
|
|
},
|
|
|
|
|
|
focus : function() {
|
|
this.focusEl.focus(10);
|
|
},
|
|
|
|
|
|
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({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.translateValue(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,
|
|
Array = Ext.Array;
|
|
Array.forEach(Array.from(me.originalValue), function(val, i) {
|
|
me.setValue(i, val);
|
|
});
|
|
me.clearInvalid();
|
|
|
|
delete me.wasValid;
|
|
},
|
|
|
|
|
|
beforeDestroy : function() {
|
|
var me = this;
|
|
|
|
Ext.destroy(me.innerEl, me.endEl, me.focusEl);
|
|
Ext.each(me.thumbs, function(thumb) {
|
|
Ext.destroy(thumb);
|
|
}, me);
|
|
|
|
me.callParent();
|
|
},
|
|
|
|
statics: {
|
|
|
|
Vertical: {
|
|
getRatio : function() {
|
|
var h = this.innerEl.getHeight(),
|
|
v = this.maxValue - this.minValue;
|
|
return h/v;
|
|
},
|
|
|
|
onClickChange : function(local) {
|
|
var me = this,
|
|
thumb, index, bottom;
|
|
|
|
if (local.left > me.clickRange[0] && local.left < me.clickRange[1]) {
|
|
thumb = me.getNearest(local, 'top');
|
|
if (!thumb.disabled) {
|
|
index = thumb.index;
|
|
bottom = me.reverseValue(me.innerEl.getHeight() - local.top);
|
|
|
|
me.setValue(index, Ext.util.Format.round(me.minValue + bottom, me.decimalPrecision), undefined, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
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 = Ext.toArray(arguments),
|
|
len = args.length;
|
|
|
|
|
|
|
|
|
|
if (len == 1 || (len <= 3 && typeof arguments[1] != 'number')) {
|
|
args.unshift(0);
|
|
}
|
|
|
|
return this.callParent(args);
|
|
},
|
|
|
|
|
|
getNearest : function(){
|
|
|
|
return this.thumbs[0];
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.tab.Tab', {
|
|
extend: 'Ext.button.Button',
|
|
alias: 'widget.tab',
|
|
|
|
requires: [
|
|
'Ext.layout.component.Tab',
|
|
'Ext.util.KeyNav'
|
|
],
|
|
|
|
componentLayout: 'tab',
|
|
|
|
isTab: true,
|
|
|
|
baseCls: Ext.baseCSSPrefix + 'tab',
|
|
|
|
|
|
activeCls: 'active',
|
|
|
|
|
|
|
|
|
|
closableCls: 'closable',
|
|
|
|
|
|
closable: true,
|
|
|
|
|
|
closeText: 'Close Tab',
|
|
|
|
|
|
active: false,
|
|
|
|
|
|
|
|
scale: false,
|
|
|
|
position: 'top',
|
|
|
|
initComponent: function() {
|
|
var me = this;
|
|
|
|
me.addEvents(
|
|
|
|
'activate',
|
|
|
|
|
|
'deactivate',
|
|
|
|
|
|
'beforeclose',
|
|
|
|
|
|
'close'
|
|
);
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (me.card) {
|
|
me.setCard(me.card);
|
|
}
|
|
},
|
|
|
|
|
|
onRender: function() {
|
|
var me = this,
|
|
tabBar = me.up('tabbar'),
|
|
tabPanel = me.up('tabpanel');
|
|
|
|
me.addClsWithUI(me.position);
|
|
|
|
|
|
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
me.callParent(arguments);
|
|
|
|
if (me.active) {
|
|
me.activate(true);
|
|
}
|
|
|
|
me.syncClosableElements();
|
|
|
|
me.keyNav = Ext.create('Ext.util.KeyNav', me.el, {
|
|
enter: me.onEnterKey,
|
|
del: me.onDeleteKey,
|
|
scope: me
|
|
});
|
|
},
|
|
|
|
|
|
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;
|
|
|
|
if (me.closeEl) {
|
|
me.closeEl.un('click', Ext.EventManager.preventDefault);
|
|
me.closeEl = null;
|
|
}
|
|
|
|
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.doComponentLayout();
|
|
if (me.ownerCt) {
|
|
me.ownerCt.doLayout();
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
syncClosableElements: function () {
|
|
var me = this;
|
|
|
|
if (me.closable) {
|
|
if (!me.closeEl) {
|
|
me.closeEl = me.el.createChild({
|
|
tag: 'a',
|
|
cls: me.baseCls + '-close-btn',
|
|
href: '#',
|
|
|
|
title: me.closeText
|
|
}).on('click', Ext.EventManager.preventDefault);
|
|
}
|
|
} else {
|
|
var closeEl = me.closeEl;
|
|
if (closeEl) {
|
|
closeEl.un('click', Ext.EventManager.preventDefault);
|
|
closeEl.remove();
|
|
me.closeEl = null;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
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);
|
|
},
|
|
|
|
|
|
onCloseClick: function() {
|
|
var me = this;
|
|
|
|
if (me.fireEvent('beforeclose', me) !== false) {
|
|
if (me.tabBar) {
|
|
if (me.tabBar.closeTab(me) === false) {
|
|
|
|
return;
|
|
}
|
|
} else {
|
|
|
|
me.fireEvent('close', me);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
fireClose: function(){
|
|
this.fireEvent('close', this);
|
|
},
|
|
|
|
|
|
onEnterKey: function(e) {
|
|
var me = this;
|
|
|
|
if (me.tabBar) {
|
|
me.tabBar.onClick(e, me.el);
|
|
}
|
|
},
|
|
|
|
|
|
onDeleteKey: function(e) {
|
|
var me = this;
|
|
|
|
if (me.closable) {
|
|
me.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.tab.Bar', {
|
|
extend: 'Ext.panel.Header',
|
|
alias: 'widget.tabbar',
|
|
baseCls: Ext.baseCSSPrefix + 'tab-bar',
|
|
|
|
requires: [
|
|
'Ext.tab.Tab',
|
|
'Ext.FocusManager'
|
|
],
|
|
|
|
isTabBar: true,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
defaultType: 'tab',
|
|
|
|
|
|
plain: false,
|
|
|
|
|
|
renderTpl: [
|
|
'<div id="{id}-body" class="{baseCls}-body <tpl if="bodyCls"> {bodyCls}</tpl> <tpl if="ui"> {baseCls}-body-{ui}<tpl for="uiCls"> {parent.baseCls}-body-{parent.ui}-{.}</tpl></tpl>"<tpl if="bodyStyle"> style="{bodyStyle}"</tpl>></div>',
|
|
'<div id="{id}-strip" class="{baseCls}-strip<tpl if="ui"> {baseCls}-strip-{ui}<tpl for="uiCls"> {parent.baseCls}-strip-{parent.ui}-{.}</tpl></tpl>"></div>'
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
keys;
|
|
|
|
if (me.plain) {
|
|
me.setUI(me.ui + '-plain');
|
|
}
|
|
|
|
me.addClsWithUI(me.dock);
|
|
|
|
me.addEvents(
|
|
|
|
'change'
|
|
);
|
|
|
|
me.addChildEls('body', 'strip');
|
|
me.callParent(arguments);
|
|
|
|
|
|
me.layout.align = (me.orientation == 'vertical') ? 'left' : 'top';
|
|
me.layout.overflowHandler = Ext.create('Ext.layout.container.boxOverflow.Scroller', me.layout);
|
|
|
|
me.remove(me.titleCmp);
|
|
delete me.titleCmp;
|
|
|
|
|
|
keys = me.orientation == 'vertical' ? ['up', 'down'] : ['left', 'right'];
|
|
Ext.FocusManager.subscribe(me, {
|
|
keys: keys
|
|
});
|
|
|
|
Ext.apply(me.renderData, {
|
|
bodyCls: me.bodyCls
|
|
});
|
|
},
|
|
|
|
|
|
onAdd: function(tab) {
|
|
tab.position = this.dock;
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
onRemove: function(tab) {
|
|
var me = this;
|
|
|
|
if (tab === me.previousTab) {
|
|
me.previousTab = null;
|
|
}
|
|
if (me.items.getCount() === 0) {
|
|
me.activeTab = null;
|
|
}
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
|
|
afterRender: function() {
|
|
var me = this;
|
|
|
|
me.mon(me.el, {
|
|
scope: me,
|
|
click: me.onClick,
|
|
delegate: '.' + Ext.baseCSSPrefix + 'tab'
|
|
});
|
|
me.callParent(arguments);
|
|
|
|
},
|
|
|
|
afterComponentLayout : function() {
|
|
var me = this;
|
|
|
|
me.callParent(arguments);
|
|
me.strip.setWidth(me.el.getWidth());
|
|
},
|
|
|
|
|
|
onClick: function(e, target) {
|
|
|
|
var tab = Ext.getCmp(target.id),
|
|
tabPanel = this.tabPanel;
|
|
|
|
target = e.getTarget();
|
|
|
|
if (tab && tab.isDisabled && !tab.isDisabled()) {
|
|
if (tab.closable && target === tab.closeEl.dom) {
|
|
tab.onCloseClick();
|
|
} else {
|
|
if (tabPanel) {
|
|
|
|
tabPanel.setActiveTab(tab.card);
|
|
} else {
|
|
this.setActiveTab(tab);
|
|
}
|
|
tab.focus();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
closeTab: function(tab) {
|
|
var me = this,
|
|
card = tab.card,
|
|
tabPanel = me.tabPanel,
|
|
nextTab;
|
|
|
|
if (card && card.fireEvent('beforeclose', card) === false) {
|
|
return false;
|
|
}
|
|
|
|
if (tab.active && me.items.getCount() > 1) {
|
|
nextTab = me.previousTab || tab.next('tab') || me.items.first();
|
|
me.setActiveTab(nextTab);
|
|
if (tabPanel) {
|
|
tabPanel.setActiveTab(nextTab.card);
|
|
}
|
|
}
|
|
|
|
tab.fireClose();
|
|
me.remove(tab);
|
|
|
|
if (tabPanel && card) {
|
|
card.fireEvent('close', card);
|
|
tabPanel.remove(card);
|
|
}
|
|
|
|
if (nextTab) {
|
|
nextTab.focus();
|
|
}
|
|
},
|
|
|
|
|
|
setActiveTab: function(tab) {
|
|
if (tab.disabled) {
|
|
return;
|
|
}
|
|
var me = this;
|
|
if (me.activeTab) {
|
|
me.previousTab = me.activeTab;
|
|
me.activeTab.deactivate();
|
|
}
|
|
tab.activate();
|
|
|
|
if (me.rendered) {
|
|
me.layout.layout();
|
|
tab.el && tab.el.scrollIntoView(me.layout.getRenderTarget());
|
|
}
|
|
me.activeTab = tab;
|
|
me.fireEvent('change', me, tab, tab.card);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.tab.Panel', {
|
|
extend: 'Ext.panel.Panel',
|
|
alias: 'widget.tabpanel',
|
|
alternateClassName: ['Ext.TabPanel'],
|
|
|
|
requires: ['Ext.layout.container.Card', 'Ext.tab.Bar'],
|
|
|
|
|
|
tabPosition : 'top',
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
removePanelHeader: true,
|
|
|
|
|
|
plain: false,
|
|
|
|
|
|
itemCls: 'x-tabpanel-child',
|
|
|
|
|
|
minTabWidth: undefined,
|
|
|
|
|
|
maxTabWidth: undefined,
|
|
|
|
|
|
deferredRender : true,
|
|
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
dockedItems = me.dockedItems || [],
|
|
activeTab = me.activeTab || 0;
|
|
|
|
me.layout = Ext.create('Ext.layout.container.Card', Ext.apply({
|
|
owner: me,
|
|
deferredRender: me.deferredRender,
|
|
itemCls: me.itemCls
|
|
}, me.layout));
|
|
|
|
|
|
me.tabBar = Ext.create('Ext.tab.Bar', Ext.apply({}, me.tabBar, {
|
|
dock: me.tabPosition,
|
|
plain: me.plain,
|
|
border: me.border,
|
|
cardLayout: me.layout,
|
|
tabPanel: me
|
|
}));
|
|
|
|
if (dockedItems && !Ext.isArray(dockedItems)) {
|
|
dockedItems = [dockedItems];
|
|
}
|
|
|
|
dockedItems.push(me.tabBar);
|
|
me.dockedItems = dockedItems;
|
|
|
|
me.addEvents(
|
|
|
|
'beforetabchange',
|
|
|
|
|
|
'tabchange'
|
|
);
|
|
me.callParent(arguments);
|
|
|
|
|
|
me.setActiveTab(activeTab);
|
|
|
|
me.on('afterlayout', me.afterInitialLayout, me, {single: true});
|
|
},
|
|
|
|
|
|
afterInitialLayout: function() {
|
|
var me = this,
|
|
card = me.getComponent(me.activeTab);
|
|
|
|
if (card) {
|
|
me.layout.setActiveItem(card);
|
|
}
|
|
},
|
|
|
|
|
|
setActiveTab: function(card) {
|
|
var me = this,
|
|
previous;
|
|
|
|
card = me.getComponent(card);
|
|
if (card) {
|
|
previous = me.getActiveTab();
|
|
|
|
if (previous && previous !== card && me.fireEvent('beforetabchange', me, card, previous) === false) {
|
|
return false;
|
|
}
|
|
|
|
me.tabBar.setActiveTab(card.tab);
|
|
me.activeTab = card;
|
|
if (me.rendered) {
|
|
me.layout.setActiveItem(card);
|
|
}
|
|
|
|
if (previous && previous !== card) {
|
|
me.fireEvent('tabchange', me, card, previous);
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
getActiveTab: function() {
|
|
return this.activeTab;
|
|
},
|
|
|
|
|
|
getTabBar: function() {
|
|
return this.tabBar;
|
|
},
|
|
|
|
|
|
onAdd: function(item, index) {
|
|
var me = this,
|
|
cfg = item.tabConfig || {},
|
|
defaultConfig = {
|
|
xtype: 'tab',
|
|
card: item,
|
|
disabled: item.disabled,
|
|
closable: item.closable,
|
|
hidden: item.hidden,
|
|
tabBar: me.tabBar
|
|
};
|
|
|
|
if (item.closeText) {
|
|
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,
|
|
titlechange: me.onItemTitleChange
|
|
});
|
|
|
|
if (item.isPanel) {
|
|
if (me.removePanelHeader) {
|
|
item.preventHeader = true;
|
|
if (item.rendered) {
|
|
item.updateHeader();
|
|
}
|
|
}
|
|
if (item.isPanel && me.border) {
|
|
item.setBorder(false);
|
|
}
|
|
}
|
|
|
|
|
|
if (this.rendered && me.items.getCount() === 1) {
|
|
me.setActiveTab(0);
|
|
}
|
|
},
|
|
|
|
|
|
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, newIconCls) {
|
|
item.tab.setIconCls(newIconCls);
|
|
this.getTabBar().doLayout();
|
|
},
|
|
|
|
|
|
onItemTitleChange: function(item, newTitle) {
|
|
item.tab.setText(newTitle);
|
|
this.getTabBar().doLayout();
|
|
},
|
|
|
|
|
|
|
|
doRemove: function(item, autoDestroy) {
|
|
var me = this,
|
|
items = me.items,
|
|
|
|
|
|
|
|
hasItemsLeft = items.getCount() > 1;
|
|
|
|
if (me.destroying || !hasItemsLeft) {
|
|
me.activeTab = null;
|
|
} else if (item === me.activeTab) {
|
|
me.setActiveTab(item.next() || items.getAt(0));
|
|
}
|
|
me.callParent(arguments);
|
|
|
|
|
|
delete item.tab.card;
|
|
delete item.tab;
|
|
},
|
|
|
|
|
|
onRemove: function(item, autoDestroy) {
|
|
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
|
|
});
|
|
|
|
Ext.define('Ext.tree.Column', {
|
|
extend: 'Ext.grid.column.Column',
|
|
alias: 'widget.treecolumn',
|
|
|
|
initComponent: function() {
|
|
var origRenderer = this.renderer || this.defaultRenderer,
|
|
origScope = this.scope || window;
|
|
|
|
this.renderer = function(value, metaData, record, rowIdx, colIdx, store, view) {
|
|
var buf = [],
|
|
format = Ext.String.format,
|
|
depth = record.getDepth(),
|
|
treePrefix = Ext.baseCSSPrefix + 'tree-',
|
|
elbowPrefix = treePrefix + 'elbow-',
|
|
expanderCls = treePrefix + 'expander',
|
|
imgText = '<img src="{1}" class="{0}" />',
|
|
checkboxText= '<input type="button" role="checkbox" class="{0}" {1} />',
|
|
formattedValue = origRenderer.apply(origScope, arguments),
|
|
href = record.get('href'),
|
|
target = record.get('hrefTarget'),
|
|
cls = record.get('cls');
|
|
|
|
while (record) {
|
|
if (!record.isRoot() || (record.isRoot() && view.rootVisible)) {
|
|
if (record.getDepth() === depth) {
|
|
buf.unshift(format(imgText,
|
|
treePrefix + 'icon ' +
|
|
treePrefix + 'icon' + (record.get('icon') ? '-inline ' : (record.isLeaf() ? '-leaf ' : '-parent ')) +
|
|
(record.get('iconCls') || ''),
|
|
record.get('icon') || Ext.BLANK_IMAGE_URL
|
|
));
|
|
if (record.get('checked') !== null) {
|
|
buf.unshift(format(
|
|
checkboxText,
|
|
(treePrefix + 'checkbox') + (record.get('checked') ? ' ' + treePrefix + 'checkbox-checked' : ''),
|
|
record.get('checked') ? 'aria-checked="true"' : ''
|
|
));
|
|
if (record.get('checked')) {
|
|
metaData.tdCls += (' ' + treePrefix + 'checked');
|
|
}
|
|
}
|
|
if (record.isLast()) {
|
|
if (record.isExpandable()) {
|
|
buf.unshift(format(imgText, (elbowPrefix + 'end-plus ' + expanderCls), Ext.BLANK_IMAGE_URL));
|
|
} else {
|
|
buf.unshift(format(imgText, (elbowPrefix + 'end'), Ext.BLANK_IMAGE_URL));
|
|
}
|
|
|
|
} else {
|
|
if (record.isExpandable()) {
|
|
buf.unshift(format(imgText, (elbowPrefix + 'plus ' + expanderCls), Ext.BLANK_IMAGE_URL));
|
|
} else {
|
|
buf.unshift(format(imgText, (treePrefix + 'elbow'), Ext.BLANK_IMAGE_URL));
|
|
}
|
|
}
|
|
} else {
|
|
if (record.isLast() || record.getDepth() === 0) {
|
|
buf.unshift(format(imgText, (elbowPrefix + 'empty'), Ext.BLANK_IMAGE_URL));
|
|
} else if (record.getDepth() !== 0) {
|
|
buf.unshift(format(imgText, (elbowPrefix + 'line'), Ext.BLANK_IMAGE_URL));
|
|
}
|
|
}
|
|
}
|
|
record = record.parentNode;
|
|
}
|
|
if (href) {
|
|
buf.push('<a href="', href, '" target="', target, '">', formattedValue, '</a>');
|
|
} else {
|
|
buf.push(formattedValue);
|
|
}
|
|
if (cls) {
|
|
metaData.tdCls += ' ' + cls;
|
|
}
|
|
return buf.join('');
|
|
};
|
|
this.callParent(arguments);
|
|
},
|
|
|
|
defaultRenderer: function(value) {
|
|
return value;
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.tree.View', {
|
|
extend: 'Ext.view.Table',
|
|
alias: 'widget.treeview',
|
|
|
|
loadingCls: Ext.baseCSSPrefix + 'grid-tree-loading',
|
|
expandedCls: Ext.baseCSSPrefix + 'grid-tree-node-expanded',
|
|
|
|
expanderSelector: '.' + Ext.baseCSSPrefix + 'tree-expander',
|
|
checkboxSelector: '.' + Ext.baseCSSPrefix + 'tree-checkbox',
|
|
expanderIconOverCls: Ext.baseCSSPrefix + 'tree-expander-over',
|
|
|
|
|
|
|
|
|
|
nodeAnimWrapCls: Ext.baseCSSPrefix + 'tree-animator-wrap',
|
|
|
|
blockRefresh: true,
|
|
|
|
|
|
rootVisible: true,
|
|
|
|
|
|
|
|
expandDuration: 250,
|
|
collapseDuration: 250,
|
|
|
|
toggleOnDblClick: true,
|
|
|
|
initComponent: function() {
|
|
var me = this;
|
|
|
|
if (me.initialConfig.animate === undefined) {
|
|
me.animate = Ext.enableFx;
|
|
}
|
|
|
|
me.store = Ext.create('Ext.data.NodeStore', {
|
|
recursive: true,
|
|
rootVisible: me.rootVisible,
|
|
listeners: {
|
|
beforeexpand: me.onBeforeExpand,
|
|
expand: me.onExpand,
|
|
beforecollapse: me.onBeforeCollapse,
|
|
collapse: me.onCollapse,
|
|
scope: me
|
|
}
|
|
});
|
|
|
|
if (me.node) {
|
|
me.setRootNode(me.node);
|
|
}
|
|
me.animQueue = {};
|
|
me.callParent(arguments);
|
|
},
|
|
|
|
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;
|
|
if (!me.rootVisible) {
|
|
node.expand();
|
|
}
|
|
},
|
|
|
|
onRender: function() {
|
|
var me = this,
|
|
el;
|
|
|
|
me.callParent(arguments);
|
|
|
|
el = me.el;
|
|
el.on({
|
|
scope: me,
|
|
delegate: me.expanderSelector,
|
|
mouseover: me.onExpanderMouseOver,
|
|
mouseout: me.onExpanderMouseOut
|
|
});
|
|
el.on({
|
|
scope: me,
|
|
delegate: me.checkboxSelector,
|
|
click: me.onCheckboxChange
|
|
});
|
|
},
|
|
|
|
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 thHtml = '',
|
|
headerCt = this.panel.headerCt,
|
|
headers = headerCt.getGridColumns(),
|
|
i = 0, len = headers.length, item,
|
|
node = this.getNode(record),
|
|
tmpEl, nodeEl;
|
|
|
|
for (; i < len; i++) {
|
|
item = headers[i];
|
|
thHtml += '<th style="width: ' + (item.hidden ? 0 : item.getDesiredWidth()) + 'px; height: 0px;"></th>';
|
|
}
|
|
|
|
nodeEl = Ext.get(node);
|
|
tmpEl = nodeEl.insertSibling({
|
|
tag: 'tr',
|
|
html: [
|
|
'<td colspan="' + headerCt.getColumnCount() + '">',
|
|
'<div class="' + this.nodeAnimWrapCls + '">',
|
|
'<table class="' + Ext.baseCSSPrefix + 'grid-table" style="width: ' + headerCt.getFullWidth() + 'px;"><tbody>',
|
|
thHtml,
|
|
'</tbody></table>',
|
|
'</div>',
|
|
'</td>'
|
|
].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) {
|
|
if (!this.animate) {
|
|
return null;
|
|
}
|
|
|
|
|
|
while (parent) {
|
|
if (parent.animWrap) {
|
|
return parent.animWrap;
|
|
}
|
|
parent = parent.parentNode;
|
|
}
|
|
return null;
|
|
},
|
|
|
|
doAdd: function(nodes, records, index) {
|
|
|
|
|
|
var me = this,
|
|
record = records[0],
|
|
parent = record.parentNode,
|
|
a = me.all.elements,
|
|
relativeIndex = 0,
|
|
animWrap = me.getAnimWrap(parent),
|
|
targetEl, children, len;
|
|
|
|
if (!animWrap || !animWrap.expanding) {
|
|
me.resetScrollers();
|
|
return me.callParent(arguments);
|
|
}
|
|
|
|
|
|
parent = animWrap.record;
|
|
|
|
|
|
targetEl = animWrap.targetEl;
|
|
children = targetEl.dom.childNodes;
|
|
|
|
|
|
len = children.length - 1;
|
|
|
|
|
|
relativeIndex = index - me.indexOf(parent) - 1;
|
|
|
|
|
|
|
|
if (!len || relativeIndex >= len) {
|
|
targetEl.appendChild(nodes);
|
|
}
|
|
|
|
|
|
else {
|
|
|
|
Ext.fly(children[relativeIndex + 1]).insertSibling(nodes, 'before', true);
|
|
}
|
|
|
|
|
|
Ext.Array.insert(a, index, nodes);
|
|
|
|
|
|
|
|
if (animWrap.isAnimating) {
|
|
me.onExpand(parent);
|
|
}
|
|
},
|
|
|
|
beginBulkUpdate: function(){
|
|
this.bulkUpdate = true;
|
|
this.ownerCt.changingScrollbars = true;
|
|
},
|
|
|
|
endBulkUpdate: function(){
|
|
var me = this,
|
|
ownerCt = me.ownerCt;
|
|
|
|
me.bulkUpdate = false;
|
|
me.ownerCt.changingScrollbars = true;
|
|
me.resetScrollers();
|
|
},
|
|
|
|
onRemove : function(ds, record, index) {
|
|
var me = this,
|
|
bulk = me.bulkUpdate;
|
|
|
|
me.doRemove(record, index);
|
|
if (!bulk) {
|
|
me.updateIndexes(index);
|
|
}
|
|
if (me.store.getCount() === 0){
|
|
me.refresh();
|
|
}
|
|
if (!bulk) {
|
|
me.fireEvent('itemremove', record, index);
|
|
}
|
|
},
|
|
|
|
doRemove: function(record, index) {
|
|
|
|
|
|
var me = this,
|
|
parent = record.parentNode,
|
|
all = me.all,
|
|
animWrap = me.getAnimWrap(record),
|
|
node = all.item(index).dom;
|
|
|
|
if (!animWrap || !animWrap.collapsing) {
|
|
me.resetScrollers();
|
|
return me.callParent(arguments);
|
|
}
|
|
|
|
animWrap.targetEl.appendChild(node);
|
|
all.removeElement(index);
|
|
},
|
|
|
|
onBeforeExpand: function(parent, records, index) {
|
|
var me = this,
|
|
animWrap;
|
|
|
|
if (!me.rendered || !me.animate) {
|
|
return;
|
|
}
|
|
|
|
if (me.getNode(parent)) {
|
|
animWrap = me.getAnimWrap(parent);
|
|
if (!animWrap) {
|
|
animWrap = parent.animWrap = 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(),
|
|
animWrap,
|
|
animateEl,
|
|
targetEl,
|
|
queueItem;
|
|
|
|
if (me.singleExpand) {
|
|
me.ensureSingleExpand(parent);
|
|
}
|
|
|
|
animWrap = me.getAnimWrap(parent);
|
|
|
|
if (!animWrap) {
|
|
me.resetScrollers();
|
|
return;
|
|
}
|
|
|
|
animateEl = animWrap.animateEl;
|
|
targetEl = animWrap.targetEl;
|
|
|
|
animateEl.stopAnimation();
|
|
|
|
queue[id] = true;
|
|
animateEl.slideIn('t', {
|
|
duration: me.expandDuration,
|
|
listeners: {
|
|
scope: me,
|
|
lastframe: function() {
|
|
|
|
animWrap.el.insertSibling(targetEl.query(me.itemSelector), 'before');
|
|
animWrap.el.remove();
|
|
me.resetScrollers();
|
|
delete animWrap.record.animWrap;
|
|
delete queue[id];
|
|
}
|
|
}
|
|
});
|
|
|
|
animWrap.isAnimating = true;
|
|
},
|
|
|
|
resetScrollers: function(){
|
|
if (!this.bulkUpdate) {
|
|
var panel = this.panel;
|
|
|
|
panel.determineScrollbars();
|
|
panel.invalidateScroller();
|
|
}
|
|
},
|
|
|
|
onBeforeCollapse: function(parent, records, index) {
|
|
var me = this,
|
|
animWrap;
|
|
|
|
if (!me.rendered || !me.animate) {
|
|
return;
|
|
}
|
|
|
|
if (me.getNode(parent)) {
|
|
animWrap = me.getAnimWrap(parent);
|
|
if (!animWrap) {
|
|
animWrap = parent.animWrap = me.createAnimWrap(parent, index);
|
|
}
|
|
else if (animWrap.expanding) {
|
|
|
|
|
|
animWrap.targetEl.select(this.itemSelector).remove();
|
|
}
|
|
animWrap.expanding = false;
|
|
animWrap.collapsing = true;
|
|
}
|
|
},
|
|
|
|
onCollapse: function(parent) {
|
|
var me = this,
|
|
queue = me.animQueue,
|
|
id = parent.getId(),
|
|
animWrap = me.getAnimWrap(parent),
|
|
animateEl, targetEl;
|
|
|
|
if (!animWrap) {
|
|
me.resetScrollers();
|
|
return;
|
|
}
|
|
|
|
animateEl = animWrap.animateEl;
|
|
targetEl = animWrap.targetEl;
|
|
|
|
queue[id] = true;
|
|
|
|
|
|
animateEl.stopAnimation();
|
|
animateEl.slideOut('t', {
|
|
duration: me.collapseDuration,
|
|
listeners: {
|
|
scope: me,
|
|
lastframe: function() {
|
|
animWrap.el.remove();
|
|
delete animWrap.record.animWrap;
|
|
me.resetScrollers();
|
|
delete queue[id];
|
|
}
|
|
}
|
|
});
|
|
animWrap.isAnimating = true;
|
|
},
|
|
|
|
|
|
isAnimating: function(node) {
|
|
return !!this.animQueue[node.getId()];
|
|
},
|
|
|
|
collectData: function(records) {
|
|
var data = this.callParent(arguments),
|
|
rows = data.rows,
|
|
len = rows.length,
|
|
i = 0,
|
|
row, record;
|
|
|
|
for (; i < len; i++) {
|
|
row = rows[i];
|
|
record = records[i];
|
|
if (record.get('qtip')) {
|
|
row.rowAttr = 'data-qtip="' + record.get('qtip') + '"';
|
|
if (record.get('qtitle')) {
|
|
row.rowAttr += ' ' + 'data-qtitle="' + record.get('qtitle') + '"';
|
|
}
|
|
}
|
|
if (record.isExpanded()) {
|
|
row.rowCls = (row.rowCls || '') + ' ' + this.expandedCls;
|
|
}
|
|
if (record.isLoading()) {
|
|
row.rowCls = (row.rowCls || '') + ' ' + this.loadingCls;
|
|
}
|
|
}
|
|
|
|
return data;
|
|
},
|
|
|
|
|
|
expand: function(record, deep, callback, scope) {
|
|
return record.expand(deep, callback, scope);
|
|
},
|
|
|
|
|
|
collapse: function(record, deep, callback, scope) {
|
|
return record.collapse(deep, callback, scope);
|
|
},
|
|
|
|
|
|
toggle: function(record) {
|
|
this[record.isExpanded() ? 'collapse' : 'expand'](record);
|
|
},
|
|
|
|
onItemDblClick: function(record, item, index) {
|
|
this.callParent(arguments);
|
|
if (this.toggleOnDblClick) {
|
|
this.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)) {
|
|
this.toggle(record);
|
|
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);
|
|
},
|
|
|
|
|
|
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();
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.tree.Panel', {
|
|
extend: 'Ext.panel.Table',
|
|
alias: 'widget.treepanel',
|
|
alternateClassName: ['Ext.tree.TreePanel', 'Ext.TreePanel'],
|
|
requires: ['Ext.tree.View', 'Ext.selection.TreeModel', 'Ext.tree.Column'],
|
|
viewType: 'treeview',
|
|
selType: 'treemodel',
|
|
|
|
treeCls: Ext.baseCSSPrefix + 'tree-panel',
|
|
|
|
deferRowRender: 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'],
|
|
|
|
|
|
|
|
|
|
|
|
constructor: function(config) {
|
|
config = config || {};
|
|
if (config.animate === undefined) {
|
|
config.animate = Ext.enableFx;
|
|
}
|
|
this.enableAnimations = config.animate;
|
|
delete config.animate;
|
|
|
|
this.callParent([config]);
|
|
},
|
|
|
|
initComponent: function() {
|
|
var me = this,
|
|
cls = [me.treeCls];
|
|
|
|
if (me.useArrows) {
|
|
cls.push(Ext.baseCSSPrefix + 'tree-arrows');
|
|
me.lines = false;
|
|
}
|
|
|
|
if (me.lines) {
|
|
cls.push(Ext.baseCSSPrefix + 'tree-lines');
|
|
} else if (!me.useArrows) {
|
|
cls.push(Ext.baseCSSPrefix + 'tree-no-lines');
|
|
}
|
|
|
|
if (Ext.isString(me.store)) {
|
|
me.store = Ext.StoreMgr.lookup(me.store);
|
|
} else if (!me.store || Ext.isObject(me.store) && !me.store.isStore) {
|
|
me.store = Ext.create('Ext.data.TreeStore', Ext.apply({}, me.store || {}, {
|
|
root: me.root,
|
|
fields: me.fields,
|
|
model: me.model,
|
|
folderSort: me.folderSort
|
|
}));
|
|
} else if (me.root) {
|
|
me.store = Ext.data.StoreManager.lookup(me.store);
|
|
me.store.setRootNode(me.root);
|
|
if (me.folderSort !== undefined) {
|
|
me.store.folderSort = me.folderSort;
|
|
me.store.sort();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
me.viewConfig = Ext.applyIf(me.viewConfig || {}, {
|
|
rootVisible: me.rootVisible,
|
|
animate: me.enableAnimations,
|
|
singleExpand: me.singleExpand,
|
|
node: me.store.getRootNode(),
|
|
hideHeaders: me.hideHeaders
|
|
});
|
|
|
|
me.mon(me.store, {
|
|
scope: me,
|
|
rootchange: me.onRootChange,
|
|
clear: me.onClear
|
|
});
|
|
|
|
me.relayEvents(me.store, [
|
|
|
|
'beforeload',
|
|
|
|
|
|
'load'
|
|
]);
|
|
|
|
me.store.on({
|
|
|
|
append: me.createRelayer('itemappend'),
|
|
|
|
|
|
remove: me.createRelayer('itemremove'),
|
|
|
|
|
|
move: me.createRelayer('itemmove'),
|
|
|
|
|
|
insert: me.createRelayer('iteminsert'),
|
|
|
|
|
|
beforeappend: me.createRelayer('beforeitemappend'),
|
|
|
|
|
|
beforeremove: me.createRelayer('beforeitemremove'),
|
|
|
|
|
|
beforemove: me.createRelayer('beforeitemmove'),
|
|
|
|
|
|
beforeinsert: me.createRelayer('beforeiteminsert'),
|
|
|
|
|
|
expand: me.createRelayer('itemexpand'),
|
|
|
|
|
|
collapse: me.createRelayer('itemcollapse'),
|
|
|
|
|
|
beforeexpand: me.createRelayer('beforeitemexpand'),
|
|
|
|
|
|
beforecollapse: me.createRelayer('beforeitemcollapse')
|
|
});
|
|
|
|
|
|
if (!me.columns) {
|
|
if (me.initialConfig.hideHeaders === undefined) {
|
|
me.hideHeaders = true;
|
|
}
|
|
me.columns = [{
|
|
xtype : 'treecolumn',
|
|
text : 'Name',
|
|
flex : 1,
|
|
dataIndex: me.displayField
|
|
}];
|
|
}
|
|
|
|
if (me.cls) {
|
|
cls.push(me.cls);
|
|
}
|
|
me.cls = cls.join(' ');
|
|
me.callParent();
|
|
|
|
me.relayEvents(me.getView(), [
|
|
|
|
'checkchange'
|
|
]);
|
|
|
|
|
|
if (!me.getView().rootVisible && !me.getRootNode()) {
|
|
me.setRootNode({
|
|
expanded: true
|
|
});
|
|
}
|
|
},
|
|
|
|
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');
|
|
},
|
|
|
|
|
|
expandAll : function(callback, scope) {
|
|
var root = this.getRootNode(),
|
|
animate = this.enableAnimations,
|
|
view = this.getView();
|
|
if (root) {
|
|
if (!animate) {
|
|
view.beginBulkUpdate();
|
|
}
|
|
root.expand(true, callback, scope);
|
|
if (!animate) {
|
|
view.endBulkUpdate();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
collapseAll : function(callback, scope) {
|
|
var root = this.getRootNode(),
|
|
animate = this.enableAnimations,
|
|
view = this.getView();
|
|
|
|
if (root) {
|
|
if (!animate) {
|
|
view.beginBulkUpdate();
|
|
}
|
|
if (view.rootVisible) {
|
|
root.collapse(true, callback, scope);
|
|
} else {
|
|
root.collapseChildren(true, callback, scope);
|
|
}
|
|
if (!animate) {
|
|
view.endBulkUpdate();
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
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,
|
|
keys,
|
|
last;
|
|
|
|
field = field || me.getRootNode().idProperty;
|
|
separator = separator || '/';
|
|
|
|
keys = path.split(separator);
|
|
last = keys.pop();
|
|
|
|
me.expandPath(keys.join(separator), field, separator, function(success, node){
|
|
var doSuccess = false;
|
|
if (success && node) {
|
|
node = node.findChild(field, last);
|
|
if (node) {
|
|
me.getSelectionModel().select(node);
|
|
Ext.callback(callback, scope || me, [true, node]);
|
|
doSuccess = true;
|
|
}
|
|
} else if (node === me.getRootNode()) {
|
|
doSuccess = true;
|
|
}
|
|
Ext.callback(callback, scope || me, [doSuccess, node]);
|
|
}, me);
|
|
}
|
|
});
|
|
|
|
|
|
Ext.define('Ext.view.DragZone', {
|
|
extend: 'Ext.dd.DragZone',
|
|
containerScroll: false,
|
|
|
|
constructor: function(config) {
|
|
var me = this;
|
|
|
|
Ext.apply(me, config);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!me.ddGroup) {
|
|
me.ddGroup = 'view-dd-zone-' + me.view.id;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
me.callParent([me.view.el.dom.parentNode]);
|
|
|
|
me.ddel = Ext.get(document.createElement('div'));
|
|
me.ddel.addCls(Ext.baseCSSPrefix + 'grid-dd-wrap');
|
|
},
|
|
|
|
init: function(id, sGroup, config) {
|
|
this.initTarget(id, sGroup, config);
|
|
this.view.mon(this.view, {
|
|
itemmousedown: this.onItemMouseDown,
|
|
scope: this
|
|
});
|
|
},
|
|
|
|
onItemMouseDown: function(view, record, item, index, e) {
|
|
if (!this.isPreventDrag(e, record, item, index)) {
|
|
this.handleMouseDown(e);
|
|
|
|
|
|
|
|
if (view.getSelectionModel().selectionMode == 'MULTI' && !e.ctrlKey && view.getSelectionModel().isSelected(record)) {
|
|
return false;
|
|
}
|
|
}
|
|
},
|
|
|
|
|
|
isPreventDrag: function(e) {
|
|
return false;
|
|
},
|
|
|
|
getDragData: function(e) {
|
|
var view = this.view,
|
|
item = e.getTarget(view.getItemSelector()),
|
|
record, selectionModel, records;
|
|
|
|
if (item) {
|
|
record = view.getRecord(item);
|
|
selectionModel = view.getSelectionModel();
|
|
records = selectionModel.getSelection();
|
|
return {
|
|
copy: this.view.copy || (this.view.allowCopy && e.ctrlKey),
|
|
event: new Ext.EventObjectImpl(e),
|
|
view: view,
|
|
ddel: this.ddel,
|
|
item: item,
|
|
records: records,
|
|
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),
|
|
e = data.event;
|
|
|
|
|
|
|
|
if (!selectionModel.isSelected(record) || e.hasModifier()) {
|
|
selectionModel.selectWithEvent(record, e, true);
|
|
}
|
|
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);
|
|
},
|
|
|
|
afterRepair: function() {
|
|
var me = this,
|
|
view = me.view,
|
|
selectedRowCls = view.selectedItemCls,
|
|
records = me.dragData.records,
|
|
fly = Ext.fly;
|
|
|
|
if (Ext.enableFx && me.repairHighlight) {
|
|
|
|
Ext.Array.forEach(records, function(record) {
|
|
|
|
|
|
var item = view.getNode(record);
|
|
|
|
|
|
|
|
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: 'x-tree-ddindicator',
|
|
|
|
|
|
expandNode : function(node) {
|
|
var view = this.view;
|
|
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.allowParentInsert) {
|
|
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 true;
|
|
},
|
|
|
|
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(),
|
|
indicatorX = 0,
|
|
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;
|
|
},
|
|
|
|
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,
|
|
view = me.view,
|
|
parentNode = targetNode.parentNode,
|
|
store = view.getStore(),
|
|
recordDomNodes = [],
|
|
records, i, len,
|
|
insertionMethod, argList,
|
|
needTargetExpand,
|
|
transferData,
|
|
processDrop;
|
|
|
|
|
|
if (data.copy) {
|
|
records = data.records;
|
|
data.records = [];
|
|
for (i = 0, len = records.length; i < len; i++) {
|
|
data.records.push(Ext.apply({}, records[i].data));
|
|
}
|
|
}
|
|
|
|
|
|
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()) {
|
|
needTargetExpand = true;
|
|
}
|
|
insertionMethod = targetNode.appendChild;
|
|
argList = [null];
|
|
}
|
|
|
|
|
|
transferData = function() {
|
|
var node;
|
|
for (i = 0, len = data.records.length; i < len; i++) {
|
|
argList[0] = data.records[i];
|
|
node = insertionMethod.apply(targetNode, argList);
|
|
|
|
if (Ext.enableFx && me.dropHighlight) {
|
|
recordDomNodes.push(view.getNode(node));
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if (Ext.enableFx && me.dropHighlight) {
|
|
|
|
|
|
Ext.Array.forEach(recordDomNodes, function(n) {
|
|
if (n) {
|
|
Ext.fly(n.firstChild ? n.firstChild : n).highlight(me.dropHighlightColor);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
|
|
if (needTargetExpand) {
|
|
targetNode.expand(false, transferData);
|
|
}
|
|
|
|
else {
|
|
transferData();
|
|
}
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.tree.plugin.TreeViewDragDrop', {
|
|
extend: 'Ext.AbstractPlugin',
|
|
alias: 'plugin.treeviewdragdrop',
|
|
|
|
uses: [
|
|
'Ext.tree.ViewDragZone',
|
|
'Ext.tree.ViewDropZone'
|
|
],
|
|
|
|
|
|
|
|
|
|
|
|
dragText : '{0} selected node{1}',
|
|
|
|
|
|
allowParentInserts: false,
|
|
|
|
|
|
allowContainerDrops: false,
|
|
|
|
|
|
appendOnly: false,
|
|
|
|
|
|
ddGroup : "TreeDD",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expandDelay : 1000,
|
|
|
|
|
|
enableDrop: true,
|
|
|
|
|
|
enableDrag: true,
|
|
|
|
|
|
nodeHighlightColor: 'c3daf9',
|
|
|
|
|
|
nodeHighlightOnDrop: Ext.enableFx,
|
|
|
|
|
|
nodeHighlightOnRepair: Ext.enableFx,
|
|
|
|
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;
|
|
|
|
if (me.enableDrag) {
|
|
me.dragZone = Ext.create('Ext.tree.ViewDragZone', {
|
|
view: view,
|
|
ddGroup: me.dragGroup || me.ddGroup,
|
|
dragText: me.dragText,
|
|
repairHighlightColor: me.nodeHighlightColor,
|
|
repairHighlight: me.nodeHighlightOnRepair
|
|
});
|
|
}
|
|
|
|
if (me.enableDrop) {
|
|
me.dropZone = Ext.create('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
|
|
});
|
|
}
|
|
}
|
|
});
|
|
|
|
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.CSS', function() {
|
|
var rules = null;
|
|
var doc = document;
|
|
|
|
var camelRe = /(-[a-z])/gi;
|
|
var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
|
|
|
|
return {
|
|
|
|
singleton: true,
|
|
|
|
constructor: function() {
|
|
this.rules = {};
|
|
this.initialized = false;
|
|
},
|
|
|
|
|
|
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]);
|
|
}
|
|
this.cacheStyleSheet(ss);
|
|
return ss;
|
|
},
|
|
|
|
|
|
removeStyleSheet : function(id) {
|
|
var existing = document.getElementById(id);
|
|
if (existing) {
|
|
existing.parentNode.removeChild(existing);
|
|
}
|
|
},
|
|
|
|
|
|
swapStyleSheet : function(id, url) {
|
|
var doc = document;
|
|
this.removeStyleSheet(id);
|
|
var 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);
|
|
},
|
|
|
|
|
|
refreshCache : function() {
|
|
return this.getRules(true);
|
|
},
|
|
|
|
|
|
cacheStyleSheet : function(ss) {
|
|
if(!rules){
|
|
rules = {};
|
|
}
|
|
try {
|
|
var ssRules = ss.cssRules || ss.rules,
|
|
selectorText,
|
|
i = ssRules.length - 1,
|
|
j,
|
|
selectors;
|
|
|
|
for (; i >= 0; --i) {
|
|
selectorText = ssRules[i].selectorText;
|
|
if (selectorText) {
|
|
|
|
|
|
selectorText = selectorText.split(',');
|
|
selectors = selectorText.length;
|
|
for (j = 0; j < selectors; j++) {
|
|
rules[Ext.String.trim(selectorText[j]).toLowerCase()] = ssRules[i];
|
|
}
|
|
}
|
|
}
|
|
} catch(e) {}
|
|
},
|
|
|
|
|
|
getRules : function(refreshCache) {
|
|
if (rules === null || refreshCache) {
|
|
rules = {};
|
|
var ds = doc.styleSheets,
|
|
i = 0,
|
|
len = ds.length;
|
|
|
|
for (; i < len; i++) {
|
|
try {
|
|
if (!ds[i].disabled) {
|
|
this.cacheStyleSheet(ds[i]);
|
|
}
|
|
} catch(e) {}
|
|
}
|
|
}
|
|
return rules;
|
|
},
|
|
|
|
|
|
getRule: function(selector, refreshCache) {
|
|
var rs = this.getRules(refreshCache);
|
|
if (!Ext.isArray(selector)) {
|
|
return rs[selector.toLowerCase()];
|
|
}
|
|
for (var i = 0; i < selector.length; i++) {
|
|
if (rs[selector[i]]) {
|
|
return rs[selector[i].toLowerCase()];
|
|
}
|
|
}
|
|
return null;
|
|
},
|
|
|
|
|
|
updateRule : function(selector, property, value){
|
|
if (!Ext.isArray(selector)) {
|
|
var rule = this.getRule(selector);
|
|
if (rule) {
|
|
rule.style[property.replace(camelRe, camelFn)] = value;
|
|
return true;
|
|
}
|
|
} else {
|
|
for (var i = 0; i < selector.length; i++) {
|
|
if (this.updateRule(selector[i], property, value)) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
}());
|
|
|
|
Ext.define('Ext.util.History', {
|
|
singleton: true,
|
|
alternateClassName: 'Ext.History',
|
|
mixins: {
|
|
observable: 'Ext.util.Observable'
|
|
},
|
|
|
|
constructor: function() {
|
|
var me = this;
|
|
me.oldIEMode = Ext.isIE6 || Ext.isIE7 || !Ext.isStrict && Ext.isIE8;
|
|
me.iframe = null;
|
|
me.hiddenField = null;
|
|
me.ready = false;
|
|
me.currentToken = null;
|
|
},
|
|
|
|
getHash: function() {
|
|
var href = window.location.href,
|
|
i = href.indexOf("#");
|
|
|
|
return i >= 0 ? href.substr(i + 1) : null;
|
|
},
|
|
|
|
doSave: function() {
|
|
this.hiddenField.value = this.currentToken;
|
|
},
|
|
|
|
|
|
handleStateChange: function(token) {
|
|
this.currentToken = token;
|
|
this.fireEvent('change', token);
|
|
},
|
|
|
|
updateIFrame: function(token) {
|
|
var html = '<html><body><div id="state">' +
|
|
Ext.util.Format.htmlEncode(token) +
|
|
'</div></body></html>';
|
|
|
|
try {
|
|
var 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;
|
|
|
|
if (!contentWindow || !contentWindow.document) {
|
|
Ext.Function.defer(this.checkIFrame, 10, this);
|
|
return;
|
|
}
|
|
|
|
var 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);
|
|
window.top.location.hash = 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;
|
|
|
|
me.currentToken = me.hiddenField.value || this.getHash();
|
|
|
|
if (me.oldIEMode) {
|
|
me.checkIFrame();
|
|
} else {
|
|
var 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);
|
|
}
|
|
|
|
},
|
|
|
|
|
|
fieldId: Ext.baseCSSPrefix + 'history-field',
|
|
|
|
iframeId: Ext.baseCSSPrefix + 'history-frame',
|
|
|
|
|
|
init: function (onReady, scope) {
|
|
var me = this;
|
|
|
|
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.oldIEMode) {
|
|
me.iframe = Ext.getDom(me.iframeId);
|
|
}
|
|
|
|
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 {
|
|
window.top.location.hash = token;
|
|
return true;
|
|
}
|
|
},
|
|
|
|
|
|
back: function() {
|
|
window.history.go(-1);
|
|
},
|
|
|
|
|
|
forward: function(){
|
|
window.history.go(1);
|
|
},
|
|
|
|
|
|
getToken: function() {
|
|
return this.ready ? this.currentToken : this.getHash();
|
|
}
|
|
});
|
|
|
|
Ext.define('Ext.view.TableChunker', {
|
|
singleton: true,
|
|
requires: ['Ext.XTemplate'],
|
|
metaTableTpl: [
|
|
'{[this.openTableWrap()]}',
|
|
'<table class="' + Ext.baseCSSPrefix + 'grid-table ' + Ext.baseCSSPrefix + 'grid-table-resizer" border="0" cellspacing="0" cellpadding="0" {[this.embedFullWidth()]}>',
|
|
'<tbody>',
|
|
'<tr class="' + Ext.baseCSSPrefix + 'grid-header-row">',
|
|
'<tpl for="columns">',
|
|
'<th class="' + Ext.baseCSSPrefix + 'grid-col-resizer-{id}" style="width: {width}px; height: 0px;"></th>',
|
|
'</tpl>',
|
|
'</tr>',
|
|
'{[this.openRows()]}',
|
|
'{row}',
|
|
'<tpl for="features">',
|
|
'{[this.embedFeature(values, parent, xindex, xcount)]}',
|
|
'</tpl>',
|
|
'{[this.closeRows()]}',
|
|
'</tbody>',
|
|
'</table>',
|
|
'{[this.closeTableWrap()]}'
|
|
],
|
|
|
|
constructor: function() {
|
|
Ext.XTemplate.prototype.recurse = function(values, reference) {
|
|
return this.apply(reference ? values[reference] : values);
|
|
};
|
|
},
|
|
|
|
embedFeature: function(values, parent, x, xcount) {
|
|
var tpl = '';
|
|
if (!values.disabled) {
|
|
tpl = values.getFeatureTpl(values, parent, x, xcount);
|
|
}
|
|
return tpl;
|
|
},
|
|
|
|
embedFullWidth: function() {
|
|
return 'style="width: {fullWidth}px;"';
|
|
},
|
|
|
|
openRows: function() {
|
|
return '<tpl for="rows">';
|
|
},
|
|
|
|
closeRows: function() {
|
|
return '</tpl>';
|
|
},
|
|
|
|
metaRowTpl: [
|
|
'<tr class="' + Ext.baseCSSPrefix + 'grid-row {addlSelector} {[this.embedRowCls()]}" {[this.embedRowAttr()]}>',
|
|
'<tpl for="columns">',
|
|
'<td class="{cls} ' + Ext.baseCSSPrefix + 'grid-cell ' + Ext.baseCSSPrefix + 'grid-cell-{columnId} {{id}-modified} {{id}-tdCls} {[this.firstOrLastCls(xindex, xcount)]}" {{id}-tdAttr}><div unselectable="on" class="' + Ext.baseCSSPrefix + 'grid-cell-inner ' + Ext.baseCSSPrefix + 'unselectable" style="{{id}-style}; text-align: {align};">{{id}}</div></td>',
|
|
'</tpl>',
|
|
'</tr>'
|
|
],
|
|
|
|
firstOrLastCls: function(xindex, xcount) {
|
|
var cssCls = '';
|
|
if (xindex === 1) {
|
|
cssCls = Ext.baseCSSPrefix + 'grid-cell-first';
|
|
} else if (xindex === xcount) {
|
|
cssCls = Ext.baseCSSPrefix + 'grid-cell-last';
|
|
}
|
|
return cssCls;
|
|
},
|
|
|
|
embedRowCls: function() {
|
|
return '{rowCls}';
|
|
},
|
|
|
|
embedRowAttr: function() {
|
|
return '{rowAttr}';
|
|
},
|
|
|
|
openTableWrap: function() {
|
|
return '';
|
|
},
|
|
|
|
closeTableWrap: function() {
|
|
return '';
|
|
},
|
|
|
|
getTableTpl: function(cfg, textOnly) {
|
|
var tpl,
|
|
tableTplMemberFns = {
|
|
openRows: this.openRows,
|
|
closeRows: this.closeRows,
|
|
embedFeature: this.embedFeature,
|
|
embedFullWidth: this.embedFullWidth,
|
|
openTableWrap: this.openTableWrap,
|
|
closeTableWrap: this.closeTableWrap
|
|
},
|
|
tplMemberFns = {},
|
|
features = cfg.features || [],
|
|
ln = features.length,
|
|
i = 0,
|
|
memberFns = {
|
|
embedRowCls: this.embedRowCls,
|
|
embedRowAttr: this.embedRowAttr,
|
|
firstOrLastCls: this.firstOrLastCls
|
|
},
|
|
|
|
metaRowTpl = Array.prototype.slice.call(this.metaRowTpl, 0),
|
|
metaTableTpl;
|
|
|
|
for (; i < ln; i++) {
|
|
if (!features[i].disabled) {
|
|
features[i].mutateMetaRowTpl(metaRowTpl);
|
|
Ext.apply(memberFns, features[i].getMetaRowTplFragments());
|
|
Ext.apply(tplMemberFns, features[i].getFragmentTpl());
|
|
Ext.apply(tableTplMemberFns, features[i].getTableFragments());
|
|
}
|
|
}
|
|
|
|
metaRowTpl = Ext.create('Ext.XTemplate', metaRowTpl.join(''), memberFns);
|
|
cfg.row = metaRowTpl.applyTemplate(cfg);
|
|
|
|
metaTableTpl = Ext.create('Ext.XTemplate', this.metaTableTpl.join(''), tableTplMemberFns);
|
|
|
|
tpl = metaTableTpl.applyTemplate(cfg);
|
|
|
|
|
|
if (!textOnly) {
|
|
tpl = Ext.create('Ext.XTemplate', tpl, tplMemberFns);
|
|
}
|
|
return tpl;
|
|
|
|
}
|
|
});
|
|
|
|
|
|
|
|
|