/*
|
This file is part of Ext JS 4.2
|
|
Copyright (c) 2011-2013 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.
|
|
Build date: 2013-05-16 14:36:50 (f9be68accb407158ba2b1be2c226a6ce1f649314)
|
*/
|
// @tag extras,core
|
// @require misc/JSON.js
|
// @define Ext
|
|
/**
|
* @class Ext
|
*
|
* The Ext namespace (global object) encapsulates all classes, singletons, and
|
* utility methods provided by Sencha's libraries.
|
*
|
* Most user interface Components are at a lower level of nesting in the namespace,
|
* but many common utility functions are provided as direct properties of the Ext namespace.
|
*
|
* Also many frequently used methods from other classes are provided as shortcuts
|
* within the Ext namespace. For example {@link Ext#getCmp Ext.getCmp} aliases
|
* {@link Ext.ComponentManager#get Ext.ComponentManager.get}.
|
*
|
* Many applications are initiated with {@link Ext#onReady Ext.onReady} which is
|
* called once the DOM is ready. This ensures all scripts have been loaded,
|
* preventing dependency issues. For example:
|
*
|
* Ext.onReady(function(){
|
* new Ext.Component({
|
* renderTo: document.body,
|
* html: 'DOM ready!'
|
* });
|
* });
|
*
|
* For more information about how to use the Ext classes, see:
|
*
|
* - <a href="http://www.sencha.com/learn/">The Learning Center</a>
|
* - <a href="http://www.sencha.com/learn/Ext_FAQ">The FAQ</a>
|
* - <a href="http://www.sencha.com/forum/">The forums</a>
|
*
|
* @singleton
|
*/
|
Ext.apply(Ext, {
|
userAgent: navigator.userAgent.toLowerCase(),
|
cache: {},
|
idSeed: 1000,
|
windowId: 'ext-window',
|
documentId: 'ext-document',
|
|
/**
|
* True when the document is fully initialized and ready for action
|
*/
|
isReady: false,
|
|
/**
|
* True to automatically uncache orphaned Ext.Elements periodically
|
*/
|
enableGarbageCollector: true,
|
|
/**
|
* True to automatically purge event listeners during garbageCollection.
|
*/
|
enableListenerCollection: true,
|
|
/**
|
* @property {Object} rootHierarchyState the top level hierarchy state to which
|
* all other hierarchy states are chained. If there is a viewport instance,
|
* this object becomes the viewport's heirarchyState. See also
|
* {@link Ext.AbstractComponent#getHierarchyState}
|
* @private
|
*/
|
rootHierarchyState: {},
|
|
addCacheEntry: function(id, el, dom) {
|
dom = dom || el.dom;
|
|
//<debug>
|
if (!dom) {
|
// Without the DOM node we can't GC the entry
|
Ext.Error.raise('Cannot add an entry to the element cache without the DOM node');
|
}
|
//</debug>
|
|
var cache = Ext.cache,
|
key = id || (el && el.id) || dom.id,
|
entry = cache[key] || (cache[key] = {
|
data: {},
|
events: {},
|
|
dom: dom,
|
|
// Skip garbage collection for special elements (window, document, iframes)
|
skipGarbageCollection: !!(dom.getElementById || dom.navigator)
|
});
|
|
if (el) {
|
el.$cache = entry;
|
// Inject the back link from the cache in case the cache entry
|
// had already been created by Ext.fly. Ext.fly creates a cache entry with no el link.
|
entry.el = el;
|
}
|
|
return entry;
|
},
|
|
updateCacheEntry: function(cacheItem, dom){
|
cacheItem.dom = dom;
|
if (cacheItem.el) {
|
cacheItem.el.dom = dom;
|
}
|
return cacheItem;
|
},
|
|
/**
|
* Generates unique ids. If the element already has an id, it is unchanged
|
* @param {HTMLElement/Ext.Element} [el] The element to generate an id for
|
* @param {String} prefix (optional) Id prefix (defaults "ext-gen")
|
* @return {String} The generated Id.
|
*/
|
id: function(el, prefix) {
|
var me = this,
|
sandboxPrefix = '';
|
el = Ext.getDom(el, true) || {};
|
if (el === document) {
|
el.id = me.documentId;
|
}
|
else if (el === window) {
|
el.id = me.windowId;
|
}
|
if (!el.id) {
|
if (me.isSandboxed) {
|
sandboxPrefix = Ext.sandboxName.toLowerCase() + '-';
|
}
|
el.id = sandboxPrefix + (prefix || "ext-gen") + (++Ext.idSeed);
|
}
|
return el.id;
|
},
|
|
escapeId: (function(){
|
var validIdRe = /^[a-zA-Z_][a-zA-Z0-9_\-]*$/i,
|
escapeRx = /([\W]{1})/g,
|
leadingNumRx = /^(\d)/g,
|
escapeFn = function(match, capture){
|
return "\\" + capture;
|
},
|
numEscapeFn = function(match, capture){
|
return '\\00' + capture.charCodeAt(0).toString(16) + ' ';
|
};
|
|
return function(id) {
|
return validIdRe.test(id)
|
? id
|
// replace the number portion last to keep the trailing ' '
|
// from being escaped
|
: id.replace(escapeRx, escapeFn)
|
.replace(leadingNumRx, numEscapeFn);
|
};
|
}()),
|
|
/**
|
* Returns the current document body as an {@link Ext.Element}.
|
* @return {Ext.Element} The document body
|
*/
|
getBody: (function() {
|
var body;
|
return function() {
|
return body || (body = Ext.get(document.body));
|
};
|
}()),
|
|
/**
|
* Returns the current document head as an {@link Ext.Element}.
|
* @return {Ext.Element} The document head
|
* @method
|
*/
|
getHead: (function() {
|
var head;
|
return function() {
|
return head || (head = Ext.get(document.getElementsByTagName("head")[0]));
|
};
|
}()),
|
|
/**
|
* Returns the current HTML document object as an {@link Ext.Element}.
|
* @return {Ext.Element} The document
|
*/
|
getDoc: (function() {
|
var doc;
|
return function() {
|
return doc || (doc = Ext.get(document));
|
};
|
}()),
|
|
/**
|
* Returns the current orientation of the mobile device
|
* @return {String} Either 'portrait' or 'landscape'
|
*/
|
getOrientation: function() {
|
return window.innerHeight > window.innerWidth ? 'portrait' : 'landscape';
|
},
|
|
/**
|
* Attempts to destroy any objects passed to it by removing all event listeners, removing them from the
|
* DOM (if applicable) and calling their destroy functions (if available). This method is primarily
|
* intended for arguments of type {@link Ext.Element} and {@link Ext.Component}, but any subclass of
|
* {@link Ext.util.Observable} can be passed in. Any number of elements and/or components can be
|
* passed into this function in a single call as separate arguments.
|
*
|
* @param {Ext.dom.Element/Ext.util.Observable/Ext.dom.Element[]/Ext.util.Observable[]...} args
|
* Any number of elements or components, or an Array of either of these to destroy.
|
*/
|
destroy: function() {
|
var ln = arguments.length,
|
i, arg;
|
|
for (i = 0; i < ln; i++) {
|
arg = arguments[i];
|
if (arg) {
|
if (Ext.isArray(arg)) {
|
this.destroy.apply(this, arg);
|
} else if (arg.isStore) {
|
arg.destroyStore();
|
} else if (Ext.isFunction(arg.destroy)) {
|
arg.destroy();
|
} else if (arg.dom) {
|
arg.remove();
|
}
|
}
|
}
|
},
|
|
/**
|
* Execute a callback function in a particular scope. If `callback` argument is a
|
* function reference, that is called. If it is a string, the string is assumed to
|
* be the name of a method on the given `scope`. If no function is passed the call
|
* is ignored.
|
*
|
* For example, these calls are equivalent:
|
*
|
* var myFunc = this.myFunc;
|
*
|
* Ext.callback('myFunc', this, [arg1, arg2]);
|
* Ext.callback(myFunc, this, [arg1, arg2]);
|
*
|
* Ext.isFunction(myFunc) && this.myFunc(arg1, arg2);
|
*
|
* @param {Function} callback The callback to execute
|
* @param {Object} [scope] The scope to execute in
|
* @param {Array} [args] The arguments to pass to the function
|
* @param {Number} [delay] Pass a number to delay the call by a number of milliseconds.
|
* @return The value returned by the callback or `undefined` (if there is a `delay`
|
* or if the `callback` is not a function).
|
*/
|
callback: function (callback, scope, args, delay) {
|
var fn, ret;
|
|
if (Ext.isFunction(callback)){
|
fn = callback;
|
} else if (scope && Ext.isString(callback)) {
|
fn = scope[callback];
|
//<debug>
|
if (!fn) {
|
Ext.Error.raise('No method named "' + callback + '"');
|
}
|
//</debug>
|
}
|
|
if (fn) {
|
args = args || [];
|
scope = scope || window;
|
if (delay) {
|
Ext.defer(fn, delay, scope, args);
|
} else {
|
ret = fn.apply(scope, args);
|
}
|
}
|
|
return ret;
|
},
|
|
/**
|
* @private
|
*/
|
resolveMethod: function(fn, scope) {
|
if (Ext.isFunction(fn)) {
|
return fn;
|
}
|
|
//<debug>
|
if (!Ext.isObject(scope) || !Ext.isFunction(scope[fn])) {
|
Ext.Error.raise('No method named "' + fn + '"');
|
}
|
//</debug>
|
|
return scope[fn];
|
},
|
|
/**
|
* Alias for {@link Ext.String#htmlEncode}.
|
* @inheritdoc Ext.String#htmlEncode
|
* @ignore
|
*/
|
htmlEncode : function(value) {
|
return Ext.String.htmlEncode(value);
|
},
|
|
/**
|
* Alias for {@link Ext.String#htmlDecode}.
|
* @inheritdoc Ext.String#htmlDecode
|
* @ignore
|
*/
|
htmlDecode : function(value) {
|
return Ext.String.htmlDecode(value);
|
},
|
|
/**
|
* Alias for {@link Ext.String#urlAppend}.
|
* @inheritdoc Ext.String#urlAppend
|
* @ignore
|
*/
|
urlAppend : function(url, s) {
|
return Ext.String.urlAppend(url, s);
|
}
|
});
|
|
|
Ext.ns = Ext.namespace;
|
|
// for old browsers
|
window.undefined = window.undefined;
|
|
/**
|
* @class Ext
|
*/
|
(function(){
|
/*
|
FF 3.6 - Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.17) Gecko/20110420 Firefox/3.6.17
|
FF 4.0.1 - Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1
|
FF 5.0 - Mozilla/5.0 (Windows NT 6.1; WOW64; rv:5.0) Gecko/20100101 Firefox/5.0
|
|
IE6 - Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;)
|
IE7 - Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; SV1;)
|
IE8 - Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)
|
IE9 - Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)]
|
IE10 - Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; MS-RTC LM 8)
|
|
Chrome 11 - Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.60 Safari/534.24
|
|
Safari 5 - Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.21.1 (KHTML, like Gecko) Version/5.0.5 Safari/533.21.1
|
|
Opera 11.11 - Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11
|
*/
|
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/), // unique to Safari 2
|
isSafari3 = isSafari && check(/version\/3/),
|
isSafari4 = isSafari && check(/version\/4/),
|
isSafari5_0 = isSafari && check(/version\/5\.0/),
|
isSafari5 = isSafari && check(/version\/5/),
|
isIE = !isOpera && check(/msie/),
|
isIE7 = isIE && ((check(/msie 7/) && docMode != 8 && docMode != 9 && docMode != 10) || docMode == 7),
|
isIE8 = isIE && ((check(/msie 8/) && docMode != 7 && docMode != 9 && docMode != 10) || docMode == 8),
|
isIE9 = isIE && ((check(/msie 9/) && docMode != 7 && docMode != 8 && docMode != 10) || docMode == 9),
|
isIE10 = isIE && ((check(/msie 10/) && docMode != 7 && docMode != 8 && docMode != 9) || docMode == 10),
|
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\./),
|
isGecko10 = isGecko && check(/rv:10\./),
|
isFF3_0 = isGecko3 && check(/rv:1\.9\.0/),
|
isFF3_5 = isGecko3 && check(/rv:1\.9\.1/),
|
isFF3_6 = isGecko3 && check(/rv:1\.9\.2/),
|
isWindows = check(/windows|win32/),
|
isMac = check(/macintosh|mac os x/),
|
isLinux = check(/linux/),
|
scrollbarSize = null,
|
chromeVersion = version(true, /\bchrome\/(\d+\.\d+)/),
|
firefoxVersion = version(true, /\bfirefox\/(\d+\.\d+)/),
|
ieVersion = version(isIE, /msie (\d+\.\d+)/),
|
operaVersion = version(isOpera, /version\/(\d+\.\d+)/),
|
safariVersion = version(isSafari, /version\/(\d+\.\d+)/),
|
webKitVersion = version(isWebKit, /webkit\/(\d+\.\d+)/),
|
isSecure = /^https/i.test(window.location.protocol),
|
nullLog;
|
|
// remove css image flicker
|
try {
|
document.execCommand("BackgroundImageCache", false, true);
|
} catch(e) {}
|
|
|
//<debug>
|
var primitiveRe = /string|number|boolean/;
|
function dumpObject (object) {
|
var member, type, value, name,
|
members = [];
|
|
// Cannot use Ext.encode since it can recurse endlessly (if we're lucky)
|
// ...and the data could be prettier!
|
for (name in object) {
|
if (object.hasOwnProperty(name)) {
|
value = object[name];
|
|
type = typeof value;
|
if (type == "function") {
|
continue;
|
}
|
|
if (type == 'undefined') {
|
member = type;
|
} else if (value === null || primitiveRe.test(type) || Ext.isDate(value)) {
|
member = Ext.encode(value);
|
} else if (Ext.isArray(value)) {
|
member = '[ ]';
|
} else if (Ext.isObject(value)) {
|
member = '{ }';
|
} else {
|
member = type;
|
}
|
members.push(Ext.encode(name) + ': ' + member);
|
}
|
}
|
|
if (members.length) {
|
return ' \nData: {\n ' + members.join(',\n ') + '\n}';
|
}
|
return '';
|
}
|
|
function log (message) {
|
var options, dump,
|
con = Ext.global.console,
|
level = 'log',
|
indent = log.indent || 0,
|
stack,
|
out,
|
max;
|
|
log.indent = indent;
|
|
if (typeof message != 'string') {
|
options = message;
|
message = options.msg || '';
|
level = options.level || level;
|
dump = options.dump;
|
stack = options.stack;
|
|
if (options.indent) {
|
++log.indent;
|
} else if (options.outdent) {
|
log.indent = indent = Math.max(indent - 1, 0);
|
}
|
|
if (dump && !(con && con.dir)) {
|
message += dumpObject(dump);
|
dump = null;
|
}
|
}
|
|
if (arguments.length > 1) {
|
message += Array.prototype.slice.call(arguments, 1).join('');
|
}
|
|
message = indent ? Ext.String.repeat(' ', log.indentSize * indent) + message : message;
|
// w/o console, all messages are equal, so munge the level into the message:
|
if (level != 'log') {
|
message = '[' + level.charAt(0).toUpperCase() + '] ' + message;
|
}
|
|
// Not obvious, but 'console' comes and goes when Firebug is turned on/off, so
|
// an early test may fail either direction if Firebug is toggled.
|
//
|
if (con) { // if (Firebug-like console)
|
if (con[level]) {
|
con[level](message);
|
} else {
|
con.log(message);
|
}
|
|
if (dump) {
|
con.dir(dump);
|
}
|
|
if (stack && con.trace) {
|
// Firebug's console.error() includes a trace already...
|
if (!con.firebug || level != 'error') {
|
con.trace();
|
}
|
}
|
} else {
|
if (Ext.isOpera) {
|
opera.postError(message);
|
} else {
|
out = log.out;
|
max = log.max;
|
|
if (out.length >= max) {
|
// this formula allows out.max to change (via debugger), where the
|
// more obvious "max/4" would not quite be the same
|
Ext.Array.erase(out, 0, out.length - 3 * Math.floor(max / 4)); // keep newest 75%
|
}
|
|
out.push(message);
|
}
|
}
|
|
// Mostly informational, but the Ext.Error notifier uses them:
|
++log.count;
|
++log.counters[level];
|
}
|
|
function logx (level, args) {
|
if (typeof args[0] == 'string') {
|
args.unshift({});
|
}
|
args[0].level = level;
|
log.apply(this, args);
|
}
|
|
log.error = function () {
|
logx('error', Array.prototype.slice.call(arguments));
|
};
|
log.info = function () {
|
logx('info', Array.prototype.slice.call(arguments));
|
};
|
log.warn = function () {
|
logx('warn', Array.prototype.slice.call(arguments));
|
};
|
|
log.count = 0;
|
log.counters = { error: 0, warn: 0, info: 0, log: 0 };
|
log.indentSize = 2;
|
log.out = [];
|
log.max = 750;
|
log.show = function () {
|
window.open('','extlog').document.write([
|
'<html><head><script type="text/javascript">',
|
'var lastCount = 0;',
|
'function update () {',
|
'var ext = window.opener.Ext,',
|
'extlog = ext && ext.log;',
|
'if (extlog && extlog.out && lastCount != extlog.count) {',
|
'lastCount = extlog.count;',
|
'var s = "<tt>" + extlog.out.join("~~~").replace(/[&]/g, "&").replace(/[<]/g, "<").replace(/[ ]/g, " ").replace(/\\~\\~\\~/g, "<br/>") + "</tt>";',
|
'document.body.innerHTML = s;',
|
'}',
|
'setTimeout(update, 1000);',
|
'}',
|
'setTimeout(update, 1000);',
|
'</script></head><body></body></html>'].join(''));
|
};
|
//</debug>
|
|
nullLog = function () {};
|
nullLog.info = nullLog.warn = nullLog.error = Ext.emptyFn;
|
|
// also update Version.js
|
Ext.setVersion('extjs', '4.2.1.883');
|
Ext.apply(Ext, {
|
/**
|
* @property {String} SSL_SECURE_URL
|
* URL to a blank file used by Ext when in secure mode for iframe src and onReady src
|
* to prevent the IE insecure content warning (`'about:blank'`, except for IE
|
* in secure mode, which is `'javascript:""'`).
|
*/
|
SSL_SECURE_URL : isSecure && isIE ? 'javascript:\'\'' : 'about:blank',
|
|
/**
|
* @property {Boolean} enableFx
|
* True if the {@link Ext.fx.Anim} Class is available.
|
*/
|
|
plainTableCls: Ext.buildSettings.baseCSSPrefix + 'table-plain',
|
|
plainListCls: Ext.buildSettings.baseCSSPrefix + 'list-plain',
|
|
/**
|
* @property {Boolean} enableNestedListenerRemoval
|
* **Experimental.** True to cascade listener removal to child elements when an element
|
* is removed. Currently not optimized for performance.
|
*/
|
enableNestedListenerRemoval : false,
|
|
/**
|
* @property {Boolean} USE_NATIVE_JSON
|
* Indicates whether to use native browser parsing for JSON methods.
|
* This option is ignored if the browser does not support native JSON methods.
|
*
|
* **Note:** Native JSON methods will not work with objects that have functions.
|
* Also, property names must be quoted, otherwise the data will not parse.
|
*/
|
USE_NATIVE_JSON : false,
|
|
/**
|
* Returns the dom node for the passed String (id), dom node, or Ext.Element.
|
* Optional 'strict' flag is needed for IE since it can return 'name' and
|
* 'id' elements by using getElementById.
|
*
|
* Here are some examples:
|
*
|
* // gets dom node based on id
|
* var elDom = Ext.getDom('elId');
|
* // gets dom node based on the dom node
|
* var elDom1 = Ext.getDom(elDom);
|
*
|
* // If we don't know if we are working with an
|
* // Ext.Element or a dom node use Ext.getDom
|
* function(el){
|
* var dom = Ext.getDom(el);
|
* // do something with the dom node
|
* }
|
*
|
* **Note:** the dom node to be found actually needs to exist (be rendered, etc)
|
* when this method is called to be successful.
|
*
|
* @param {String/HTMLElement/Ext.Element} el
|
* @return HTMLElement
|
*/
|
getDom : function(el, strict) {
|
if (!el || !document) {
|
return null;
|
}
|
if (el.dom) {
|
return el.dom;
|
} else {
|
if (typeof el == 'string') {
|
var e = Ext.getElementById(el);
|
// IE returns elements with the 'name' and 'id' attribute.
|
// we do a strict check to return the element with only the id attribute
|
if (e && isIE && strict) {
|
if (el == e.getAttribute('id')) {
|
return e;
|
} else {
|
return null;
|
}
|
}
|
return e;
|
} else {
|
return el;
|
}
|
}
|
},
|
|
/**
|
* Removes a DOM node from the document.
|
*
|
* Removes this element from the document, removes all DOM event listeners, and
|
* deletes the cache reference. All DOM event listeners are removed from this element.
|
* If {@link Ext#enableNestedListenerRemoval Ext.enableNestedListenerRemoval} is
|
* `true`, then DOM event listeners are also removed from all child nodes.
|
* The body node will be ignored if passed in.
|
*
|
* @param {HTMLElement} node The node to remove
|
* @method
|
*/
|
removeNode : isIE6 || isIE7 || isIE8
|
? (function() {
|
var d;
|
return function(n){
|
if(n && n.tagName.toUpperCase() != 'BODY'){
|
(Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
|
|
var cache = Ext.cache,
|
id = n.id;
|
|
if (cache[id]) {
|
delete cache[id].dom;
|
delete cache[id];
|
}
|
|
if (isIE8 && n.parentNode) {
|
n.parentNode.removeChild(n);
|
}
|
d = d || document.createElement('div');
|
d.appendChild(n);
|
d.innerHTML = '';
|
}
|
};
|
}())
|
: function(n) {
|
if (n && n.parentNode && n.tagName.toUpperCase() != 'BODY') {
|
(Ext.enableNestedListenerRemoval) ? Ext.EventManager.purgeElement(n) : Ext.EventManager.removeAll(n);
|
|
var cache = Ext.cache,
|
id = n.id;
|
|
if (cache[id]) {
|
delete cache[id].dom;
|
delete cache[id];
|
}
|
|
n.parentNode.removeChild(n);
|
}
|
},
|
|
isStrict: isStrict,
|
|
// IE10 quirks behaves like Gecko/WebKit quirks, so don't include it here
|
isIEQuirks: isIE && (!isStrict && (isIE6 || isIE7 || isIE8 || isIE9)),
|
|
/**
|
* True if the detected browser is Opera.
|
* @type Boolean
|
*/
|
isOpera : isOpera,
|
|
/**
|
* True if the detected browser is Opera 10.5x.
|
* @type Boolean
|
*/
|
isOpera10_5 : isOpera10_5,
|
|
/**
|
* True if the detected browser uses WebKit.
|
* @type Boolean
|
*/
|
isWebKit : isWebKit,
|
|
/**
|
* True if the detected browser is Chrome.
|
* @type Boolean
|
*/
|
isChrome : isChrome,
|
|
/**
|
* True if the detected browser is Safari.
|
* @type Boolean
|
*/
|
isSafari : isSafari,
|
|
/**
|
* True if the detected browser is Safari 3.x.
|
* @type Boolean
|
*/
|
isSafari3 : isSafari3,
|
|
/**
|
* True if the detected browser is Safari 4.x.
|
* @type Boolean
|
*/
|
isSafari4 : isSafari4,
|
|
/**
|
* True if the detected browser is Safari 5.x.
|
* @type Boolean
|
*/
|
isSafari5 : isSafari5,
|
|
/**
|
* True if the detected browser is Safari 5.0.x.
|
* @type Boolean
|
*/
|
isSafari5_0 : isSafari5_0,
|
|
|
/**
|
* True if the detected browser is Safari 2.x.
|
* @type Boolean
|
*/
|
isSafari2 : isSafari2,
|
|
/**
|
* True if the detected browser is Internet Explorer.
|
* @type Boolean
|
*/
|
isIE : isIE,
|
|
/**
|
* True if the detected browser is Internet Explorer 6.x.
|
* @type Boolean
|
*/
|
isIE6 : isIE6,
|
|
/**
|
* True if the detected browser is Internet Explorer 7.x.
|
* @type Boolean
|
*/
|
isIE7 : isIE7,
|
|
/**
|
* True if the detected browser is Internet Explorer 7.x or lower.
|
* @type Boolean
|
*/
|
isIE7m : isIE6 || isIE7,
|
|
/**
|
* True if the detected browser is Internet Explorer 7.x or higher.
|
* @type Boolean
|
*/
|
isIE7p : isIE && !isIE6,
|
|
/**
|
* True if the detected browser is Internet Explorer 8.x.
|
* @type Boolean
|
*/
|
isIE8 : isIE8,
|
|
/**
|
* True if the detected browser is Internet Explorer 8.x or lower.
|
* @type Boolean
|
*/
|
isIE8m : isIE6 || isIE7 || isIE8,
|
|
/**
|
* True if the detected browser is Internet Explorer 8.x or higher.
|
* @type Boolean
|
*/
|
isIE8p : isIE && !(isIE6 || isIE7),
|
|
/**
|
* True if the detected browser is Internet Explorer 9.x.
|
* @type Boolean
|
*/
|
isIE9 : isIE9,
|
|
/**
|
* True if the detected browser is Internet Explorer 9.x or lower.
|
* @type Boolean
|
*/
|
isIE9m : isIE6 || isIE7 || isIE8 || isIE9,
|
|
/**
|
* True if the detected browser is Internet Explorer 9.x or higher.
|
* @type Boolean
|
*/
|
isIE9p : isIE && !(isIE6 || isIE7 || isIE8),
|
|
/**
|
* True if the detected browser is Internet Explorer 10.x.
|
* @type Boolean
|
*/
|
isIE10 : isIE10,
|
|
/**
|
* True if the detected browser is Internet Explorer 10.x or lower.
|
* @type Boolean
|
*/
|
isIE10m : isIE6 || isIE7 || isIE8 || isIE9 || isIE10,
|
|
/**
|
* True if the detected browser is Internet Explorer 10.x or higher.
|
* @type Boolean
|
*/
|
isIE10p : isIE && !(isIE6 || isIE7 || isIE8 || isIE9),
|
|
/**
|
* True if the detected browser uses the Gecko layout engine (e.g. Mozilla, Firefox).
|
* @type Boolean
|
*/
|
isGecko : isGecko,
|
|
/**
|
* True if the detected browser uses a Gecko 1.9+ layout engine (e.g. Firefox 3.x).
|
* @type Boolean
|
*/
|
isGecko3 : isGecko3,
|
|
/**
|
* True if the detected browser uses a Gecko 2.0+ layout engine (e.g. Firefox 4.x).
|
* @type Boolean
|
*/
|
isGecko4 : isGecko4,
|
|
/**
|
* True if the detected browser uses a Gecko 5.0+ layout engine (e.g. Firefox 5.x).
|
* @type Boolean
|
*/
|
isGecko5 : isGecko5,
|
|
/**
|
* True if the detected browser uses a Gecko 5.0+ layout engine (e.g. Firefox 5.x).
|
* @type Boolean
|
*/
|
isGecko10 : isGecko10,
|
|
/**
|
* True if the detected browser uses FireFox 3.0
|
* @type Boolean
|
*/
|
isFF3_0 : isFF3_0,
|
|
/**
|
* True if the detected browser uses FireFox 3.5
|
* @type Boolean
|
*/
|
isFF3_5 : isFF3_5,
|
|
/**
|
* True if the detected browser uses FireFox 3.6
|
* @type Boolean
|
*/
|
isFF3_6 : isFF3_6,
|
|
/**
|
* True if the detected browser uses FireFox 4
|
* @type Boolean
|
*/
|
isFF4 : 4 <= firefoxVersion && firefoxVersion < 5,
|
|
/**
|
* True if the detected browser uses FireFox 5
|
* @type Boolean
|
*/
|
isFF5 : 5 <= firefoxVersion && firefoxVersion < 6,
|
|
/**
|
* True if the detected browser uses FireFox 10
|
* @type Boolean
|
*/
|
isFF10 : 10 <= firefoxVersion && firefoxVersion < 11,
|
|
/**
|
* True if the detected platform is Linux.
|
* @type Boolean
|
*/
|
isLinux : isLinux,
|
|
/**
|
* True if the detected platform is Windows.
|
* @type Boolean
|
*/
|
isWindows : isWindows,
|
|
/**
|
* True if the detected platform is Mac OS.
|
* @type Boolean
|
*/
|
isMac : isMac,
|
|
/**
|
* The current version of Chrome (0 if the browser is not Chrome).
|
* @type Number
|
*/
|
chromeVersion: chromeVersion,
|
|
/**
|
* The current version of Firefox (0 if the browser is not Firefox).
|
* @type Number
|
*/
|
firefoxVersion: firefoxVersion,
|
|
/**
|
* The current version of IE (0 if the browser is not IE). This does not account
|
* for the documentMode of the current page, which is factored into {@link #isIE7},
|
* {@link #isIE8} and {@link #isIE9}. Thus this is not always true:
|
*
|
* Ext.isIE8 == (Ext.ieVersion == 8)
|
*
|
* @type Number
|
*/
|
ieVersion: ieVersion,
|
|
/**
|
* The current version of Opera (0 if the browser is not Opera).
|
* @type Number
|
*/
|
operaVersion: operaVersion,
|
|
/**
|
* The current version of Safari (0 if the browser is not Safari).
|
* @type Number
|
*/
|
safariVersion: safariVersion,
|
|
/**
|
* The current version of WebKit (0 if the browser does not use WebKit).
|
* @type Number
|
*/
|
webKitVersion: webKitVersion,
|
|
/**
|
* True if the page is running over SSL
|
* @type Boolean
|
*/
|
isSecure: isSecure,
|
|
/**
|
* URL to a 1x1 transparent gif image used by Ext to create inline icons with
|
* CSS background images. In older versions of IE, this defaults to
|
* "http://sencha.com/s.gif" and you should change this to a URL on your server.
|
* For other browsers it uses an inline data URL.
|
* @type String
|
*/
|
BLANK_IMAGE_URL : (isIE6 || isIE7) ? '/' + '/www.sencha.com/s.gif' : 'data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==',
|
|
/**
|
* Utility method for returning a default value if the passed value is empty.
|
*
|
* The value is deemed to be empty if it is:
|
*
|
* - null
|
* - undefined
|
* - an empty array
|
* - a zero length string (Unless the `allowBlank` parameter is `true`)
|
*
|
* @param {Object} value The value to test
|
* @param {Object} defaultValue The value to return if the original value is empty
|
* @param {Boolean} [allowBlank=false] true to allow zero length strings to qualify as non-empty.
|
* @return {Object} value, if non-empty, else defaultValue
|
* @deprecated 4.0.0 Use {@link Ext#valueFrom} instead
|
*/
|
value : function(v, defaultValue, allowBlank){
|
return Ext.isEmpty(v, allowBlank) ? defaultValue : v;
|
},
|
|
/**
|
* Escapes the passed string for use in a regular expression.
|
* @param {String} str
|
* @return {String}
|
* @deprecated 4.0.0 Use {@link Ext.String#escapeRegex} instead
|
*/
|
escapeRe : function(s) {
|
return s.replace(/([-.*+?\^${}()|\[\]\/\\])/g, "\\$1");
|
},
|
|
/**
|
* Applies event listeners to elements by selectors when the document is ready.
|
* The event name is specified with an `@` suffix.
|
*
|
* Ext.addBehaviors({
|
* // add a listener for click on all anchors in element with id foo
|
* '#foo a@click' : function(e, t){
|
* // do something
|
* },
|
*
|
* // add the same listener to multiple selectors (separated by comma BEFORE the @)
|
* '#foo a, #bar span.some-class@mouseover' : function(){
|
* // do something
|
* }
|
* });
|
*
|
* @param {Object} obj The list of behaviors to apply
|
*/
|
addBehaviors : function(o){
|
if(!Ext.isReady){
|
Ext.onReady(function(){
|
Ext.addBehaviors(o);
|
});
|
} else {
|
var cache = {}, // simple cache for applying multiple behaviors to same selector does query multiple times
|
parts,
|
b,
|
s;
|
for (b in o) {
|
if ((parts = b.split('@'))[1]) { // for Object prototype breakers
|
s = parts[0];
|
if(!cache[s]){
|
cache[s] = Ext.select(s);
|
}
|
cache[s].on(parts[1], o[b]);
|
}
|
}
|
cache = null;
|
}
|
},
|
|
/**
|
* Returns the size of the browser scrollbars. This can differ depending on
|
* operating system settings, such as the theme or font size.
|
* @param {Boolean} [force] true to force a recalculation of the value.
|
* @return {Object} An object containing scrollbar sizes.
|
* @return {Number} return.width The width of the vertical scrollbar.
|
* @return {Number} return.height The height of the horizontal scrollbar.
|
*/
|
getScrollbarSize: function (force) {
|
if (!Ext.isReady) {
|
return {};
|
}
|
|
if (force || !scrollbarSize) {
|
var db = document.body,
|
div = document.createElement('div');
|
|
div.style.width = div.style.height = '100px';
|
div.style.overflow = 'scroll';
|
div.style.position = 'absolute';
|
|
db.appendChild(div); // now we can measure the div...
|
|
// at least in iE9 the div is not 100px - the scrollbar size is removed!
|
scrollbarSize = {
|
width: div.offsetWidth - div.clientWidth,
|
height: div.offsetHeight - div.clientHeight
|
};
|
|
db.removeChild(div);
|
}
|
|
return scrollbarSize;
|
},
|
|
/**
|
* Utility method for getting the width of the browser's vertical scrollbar. This
|
* can differ depending on operating system settings, such as the theme or font size.
|
*
|
* This method is deprected in favor of {@link #getScrollbarSize}.
|
*
|
* @param {Boolean} [force] true to force a recalculation of the value.
|
* @return {Number} The width of a vertical scrollbar.
|
* @deprecated
|
*/
|
getScrollBarWidth: function(force){
|
var size = Ext.getScrollbarSize(force);
|
return size.width + 2; // legacy fudge factor
|
},
|
|
/**
|
* Copies a set of named properties fom the source object to the destination object.
|
*
|
* Example:
|
*
|
* ImageComponent = Ext.extend(Ext.Component, {
|
* initComponent: function() {
|
* this.autoEl = { tag: 'img' };
|
* MyComponent.superclass.initComponent.apply(this, arguments);
|
* this.initialBox = Ext.copyTo({}, this.initialConfig, 'x,y,width,height');
|
* }
|
* });
|
*
|
* Important note: To borrow class prototype methods, use {@link Ext.Base#borrow} instead.
|
*
|
* @param {Object} dest The destination object.
|
* @param {Object} source The source object.
|
* @param {String/String[]} names Either an Array of property names, or a comma-delimited list
|
* of property names to copy.
|
* @param {Boolean} [usePrototypeKeys] Defaults to false. Pass true to copy keys off of the
|
* prototype as well as the instance.
|
* @return {Object} The modified object.
|
*/
|
copyTo : function(dest, source, names, usePrototypeKeys){
|
if(typeof names == 'string'){
|
names = names.split(/[,;\s]/);
|
}
|
|
var n,
|
nLen = names? names.length : 0,
|
name;
|
|
for(n = 0; n < nLen; n++) {
|
name = names[n];
|
|
if(usePrototypeKeys || source.hasOwnProperty(name)){
|
dest[name] = source[name];
|
}
|
}
|
|
return dest;
|
},
|
|
/**
|
* Attempts to destroy and then remove a set of named properties of the passed object.
|
* @param {Object} o The object (most likely a Component) who's properties you wish to destroy.
|
* @param {String...} args One or more names of the properties to destroy and remove from the object.
|
*/
|
destroyMembers : function(o){
|
for (var i = 1, a = arguments, len = a.length; i < len; i++) {
|
Ext.destroy(o[a[i]]);
|
delete o[a[i]];
|
}
|
},
|
|
/**
|
* Logs a message. If a console is present it will be used. On Opera, the method
|
* "opera.postError" is called. In other cases, the message is logged to an array
|
* "Ext.log.out". An attached debugger can watch this array and view the log. The
|
* log buffer is limited to a maximum of "Ext.log.max" entries (defaults to 250).
|
* The `Ext.log.out` array can also be written to a popup window by entering the
|
* following in the URL bar (a "bookmarklet"):
|
*
|
* javascript:void(Ext.log.show());
|
*
|
* If additional parameters are passed, they are joined and appended to the message.
|
* A technique for tracing entry and exit of a function is this:
|
*
|
* function foo () {
|
* Ext.log({ indent: 1 }, '>> foo');
|
*
|
* // log statements in here or methods called from here will be indented
|
* // by one step
|
*
|
* Ext.log({ outdent: 1 }, '<< foo');
|
* }
|
*
|
* This method does nothing in a release build.
|
*
|
* @param {String/Object} [options] The message to log or an options object with any
|
* of the following properties:
|
*
|
* - `msg`: The message to log (required).
|
* - `level`: One of: "error", "warn", "info" or "log" (the default is "log").
|
* - `dump`: An object to dump to the log as part of the message.
|
* - `stack`: True to include a stack trace in the log.
|
* - `indent`: Cause subsequent log statements to be indented one step.
|
* - `outdent`: Cause this and following statements to be one step less indented.
|
*
|
* @param {String...} [message] The message to log (required unless specified in
|
* options object).
|
*
|
* @method
|
*/
|
log :
|
//<debug>
|
log ||
|
//</debug>
|
nullLog,
|
|
/**
|
* Partitions the set into two sets: a true set and a false set.
|
*
|
* Example 1:
|
*
|
* Ext.partition([true, false, true, true, false]);
|
* // returns [[true, true, true], [false, false]]
|
*
|
* Example 2:
|
*
|
* Ext.partition(
|
* Ext.query("p"),
|
* function(val){
|
* return val.className == "class1"
|
* }
|
* );
|
* // true are those paragraph elements with a className of "class1",
|
* // false set are those that do not have that className.
|
*
|
* @param {Array/NodeList} arr The array to partition
|
* @param {Function} truth (optional) a function to determine truth.
|
* If this is omitted the element itself must be able to be evaluated for its truthfulness.
|
* @return {Array} [array of truish values, array of falsy values]
|
* @deprecated 4.0.0 Will be removed in the next major version
|
*/
|
partition : function(arr, truth){
|
var ret = [[],[]],
|
a, v,
|
aLen = arr.length;
|
|
for (a = 0; a < aLen; a++) {
|
v = arr[a];
|
ret[ (truth && truth(v, a, arr)) || (!truth && v) ? 0 : 1].push(v);
|
}
|
|
return ret;
|
},
|
|
/**
|
* Invokes a method on each item in an Array.
|
*
|
* Example:
|
*
|
* Ext.invoke(Ext.query("p"), "getAttribute", "id");
|
* // [el1.getAttribute("id"), el2.getAttribute("id"), ..., elN.getAttribute("id")]
|
*
|
* @param {Array/NodeList} arr The Array of items to invoke the method on.
|
* @param {String} methodName The method name to invoke.
|
* @param {Object...} args Arguments to send into the method invocation.
|
* @return {Array} The results of invoking the method on each item in the array.
|
* @deprecated 4.0.0 Will be removed in the next major version
|
*/
|
invoke : function(arr, methodName){
|
var ret = [],
|
args = Array.prototype.slice.call(arguments, 2),
|
a, v,
|
aLen = arr.length;
|
|
for (a = 0; a < aLen; a++) {
|
v = arr[a];
|
|
if (v && typeof v[methodName] == 'function') {
|
ret.push(v[methodName].apply(v, args));
|
} else {
|
ret.push(undefined);
|
}
|
}
|
|
return ret;
|
},
|
|
/**
|
* Zips N sets together.
|
*
|
* Example 1:
|
*
|
* Ext.zip([1,2,3],[4,5,6]); // [[1,4],[2,5],[3,6]]
|
*
|
* Example 2:
|
*
|
* Ext.zip(
|
* [ "+", "-", "+"],
|
* [ 12, 10, 22],
|
* [ 43, 15, 96],
|
* function(a, b, c){
|
* return "$" + a + "" + b + "." + c
|
* }
|
* ); // ["$+12.43", "$-10.15", "$+22.96"]
|
*
|
* @param {Array/NodeList...} arr This argument may be repeated. Array(s)
|
* to contribute values.
|
* @param {Function} zipper (optional) The last item in the argument list.
|
* This will drive how the items are zipped together.
|
* @return {Array} The zipped set.
|
* @deprecated 4.0.0 Will be removed in the next major version
|
*/
|
zip : function(){
|
var parts = Ext.partition(arguments, function( val ){ return typeof val != 'function'; }),
|
arrs = parts[0],
|
fn = parts[1][0],
|
len = Ext.max(Ext.pluck(arrs, "length")),
|
ret = [],
|
i,
|
j,
|
aLen;
|
|
for (i = 0; i < len; i++) {
|
ret[i] = [];
|
if(fn){
|
ret[i] = fn.apply(fn, Ext.pluck(arrs, i));
|
}else{
|
for (j = 0, aLen = arrs.length; j < aLen; j++){
|
ret[i].push( arrs[j][i] );
|
}
|
}
|
}
|
return ret;
|
},
|
|
/**
|
* Turns an array into a sentence, joined by a specified connector - e.g.:
|
*
|
* Ext.toSentence(['Adama', 'Tigh', 'Roslin']); //'Adama, Tigh and Roslin'
|
* Ext.toSentence(['Adama', 'Tigh', 'Roslin'], 'or'); //'Adama, Tigh or Roslin'
|
*
|
* @param {String[]} items The array to create a sentence from
|
* @param {String} connector The string to use to connect the last two words.
|
* Usually 'and' or 'or' - defaults to 'and'.
|
* @return {String} The sentence string
|
* @deprecated 4.0.0 Will be removed in the next major version
|
*/
|
toSentence: function(items, connector) {
|
var length = items.length,
|
head,
|
tail;
|
|
if (length <= 1) {
|
return items[0];
|
} else {
|
head = items.slice(0, length - 1);
|
tail = items[length - 1];
|
|
return Ext.util.Format.format("{0} {1} {2}", head.join(", "), connector || 'and', tail);
|
}
|
},
|
|
/**
|
* Sets the default font-family to use for components that support a `glyph` config.
|
* @param {String} fontFamily The name of the font-family
|
*/
|
setGlyphFontFamily: function(fontFamily) {
|
Ext._glyphFontFamily = fontFamily;
|
},
|
|
/**
|
* @property {Boolean} useShims
|
* By default, Ext intelligently decides whether floating elements should be shimmed.
|
* If you are using flash, you may want to set this to true.
|
*/
|
useShims: isIE6
|
});
|
}());
|
|
/**
|
* Loads Ext.app.Application class and starts it up with given configuration after the
|
* page is ready.
|
*
|
* See `Ext.app.Application` for details.
|
*
|
* @param {Object/String} config Application config object or name of a class derived from Ext.app.Application.
|
*/
|
Ext.application = function(config) {
|
var App, paths, ns;
|
|
if (typeof config === "string") {
|
Ext.require(config, function(){
|
App = Ext.ClassManager.get(config);
|
});
|
}
|
else {
|
// We have to process `paths` before creating Application class,
|
// or `requires` won't work.
|
Ext.Loader.setPath(config.name, config.appFolder || 'app');
|
|
if (paths = config.paths) {
|
for (ns in paths) {
|
if (paths.hasOwnProperty(ns)) {
|
Ext.Loader.setPath(ns, paths[ns]);
|
}
|
}
|
}
|
|
config['paths processed'] = true;
|
|
// Let Ext.define do the hard work but don't assign a class name.
|
//
|
Ext.define(config.name + ".$application", Ext.apply({
|
extend: 'Ext.app.Application' // can be replaced by config!
|
}, config),
|
// call here when the App class gets full defined
|
function () {
|
App = this;
|
});
|
}
|
|
Ext.onReady(function() {
|
// this won't be called until App has been created and its requires have been
|
// met...
|
Ext.app.Application.instance = new App();
|
});
|
};
|