/*!
- * Ext JS Library 3.0.0
+ * Ext JS Library 3.0.3
* Copyright(c) 2006-2009 Ext JS, LLC
* licensing@extjs.com
* http://www.extjs.com/license
*/
-/**
- * @class Ext.DomHelper
- * <p>The DomHelper class provides a layer of abstraction from DOM and transparently supports creating
- * elements via DOM or using HTML fragments. It also has the ability to create HTML fragment templates
- * from your DOM building code.</p>
- *
- * <p><b><u>DomHelper element specification object</u></b></p>
- * <p>A specification object is used when creating elements. Attributes of this object
- * are assumed to be element attributes, except for 4 special attributes:
- * <div class="mdetail-params"><ul>
- * <li><b><tt>tag</tt></b> : <div class="sub-desc">The tag name of the element</div></li>
- * <li><b><tt>children</tt></b> : or <tt>cn</tt><div class="sub-desc">An array of the
- * same kind of element definition objects to be created and appended. These can be nested
- * as deep as you want.</div></li>
- * <li><b><tt>cls</tt></b> : <div class="sub-desc">The class attribute of the element.
- * This will end up being either the "class" attribute on a HTML fragment or className
- * for a DOM node, depending on whether DomHelper is using fragments or DOM.</div></li>
- * <li><b><tt>html</tt></b> : <div class="sub-desc">The innerHTML for the element</div></li>
- * </ul></div></p>
- *
- * <p><b><u>Insertion methods</u></b></p>
- * <p>Commonly used insertion methods:
- * <div class="mdetail-params"><ul>
- * <li><b><tt>{@link #append}</tt></b> : <div class="sub-desc"></div></li>
- * <li><b><tt>{@link #insertBefore}</tt></b> : <div class="sub-desc"></div></li>
- * <li><b><tt>{@link #insertAfter}</tt></b> : <div class="sub-desc"></div></li>
- * <li><b><tt>{@link #overwrite}</tt></b> : <div class="sub-desc"></div></li>
- * <li><b><tt>{@link #createTemplate}</tt></b> : <div class="sub-desc"></div></li>
- * <li><b><tt>{@link #insertHtml}</tt></b> : <div class="sub-desc"></div></li>
- * </ul></div></p>
- *
- * <p><b><u>Example</u></b></p>
- * <p>This is an example, where an unordered list with 3 children items is appended to an existing
- * element with id <tt>'my-div'</tt>:<br>
- <pre><code>
-var dh = Ext.DomHelper; // create shorthand alias
-// specification object
-var spec = {
- id: 'my-ul',
- tag: 'ul',
- cls: 'my-list',
- // append children after creating
- children: [ // may also specify 'cn' instead of 'children'
- {tag: 'li', id: 'item0', html: 'List Item 0'},
- {tag: 'li', id: 'item1', html: 'List Item 1'},
- {tag: 'li', id: 'item2', html: 'List Item 2'}
- ]
-};
-var list = dh.append(
- 'my-div', // the context element 'my-div' can either be the id or the actual node
- spec // the specification object
-);
- </code></pre></p>
- * <p>Element creation specification parameters in this class may also be passed as an Array of
- * specification objects. This can be used to insert multiple sibling nodes into an existing
- * container very efficiently. For example, to add more list items to the example above:<pre><code>
-dh.append('my-ul', [
- {tag: 'li', id: 'item3', html: 'List Item 3'},
- {tag: 'li', id: 'item4', html: 'List Item 4'}
-]);
- * </code></pre></p>
- *
- * <p><b><u>Templating</u></b></p>
- * <p>The real power is in the built-in templating. Instead of creating or appending any elements,
- * <tt>{@link #createTemplate}</tt> returns a Template object which can be used over and over to
- * insert new elements. Revisiting the example above, we could utilize templating this time:
- * <pre><code>
-// create the node
-var list = dh.append('my-div', {tag: 'ul', cls: 'my-list'});
-// get template
-var tpl = dh.createTemplate({tag: 'li', id: 'item{0}', html: 'List Item {0}'});
-
-for(var i = 0; i < 5, i++){
- tpl.append(list, [i]); // use template to append to the actual node
-}
- * </code></pre></p>
- * <p>An example using a template:<pre><code>
-var html = '<a id="{0}" href="{1}" class="nav">{2}</a>';
-
-var tpl = new Ext.DomHelper.createTemplate(html);
-tpl.append('blog-roll', ['link1', 'http://www.jackslocum.com/', "Jack's Site"]);
-tpl.append('blog-roll', ['link2', 'http://www.dustindiaz.com/', "Dustin's Site"]);
- * </code></pre></p>
- *
- * <p>The same example using named parameters:<pre><code>
-var html = '<a id="{id}" href="{url}" class="nav">{text}</a>';
-
-var tpl = new Ext.DomHelper.createTemplate(html);
-tpl.append('blog-roll', {
- id: 'link1',
- url: 'http://www.jackslocum.com/',
- text: "Jack's Site"
-});
-tpl.append('blog-roll', {
- id: 'link2',
- url: 'http://www.dustindiaz.com/',
- text: "Dustin's Site"
-});
- * </code></pre></p>
- *
- * <p><b><u>Compiling Templates</u></b></p>
- * <p>Templates are applied using regular expressions. The performance is great, but if
- * you are adding a bunch of DOM elements using the same template, you can increase
- * performance even further by {@link Ext.Template#compile "compiling"} the template.
- * The way "{@link Ext.Template#compile compile()}" works is the template is parsed and
- * broken up at the different variable points and a dynamic function is created and eval'ed.
- * The generated function performs string concatenation of these parts and the passed
- * variables instead of using regular expressions.
- * <pre><code>
-var html = '<a id="{id}" href="{url}" class="nav">{text}</a>';
-
-var tpl = new Ext.DomHelper.createTemplate(html);
-tpl.compile();
-
-//... use template like normal
- * </code></pre></p>
- *
- * <p><b><u>Performance Boost</u></b></p>
- * <p>DomHelper will transparently create HTML fragments when it can. Using HTML fragments instead
- * of DOM can significantly boost performance.</p>
- * <p>Element creation specification parameters may also be strings. If {@link #useDom} is <tt>false</tt>,
- * then the string is used as innerHTML. If {@link #useDom} is <tt>true</tt>, a string specification
- * results in the creation of a text node. Usage:</p>
- * <pre><code>
-Ext.DomHelper.useDom = true; // force it to use DOM; reduces performance
- * </code></pre>
- * @singleton
- */
-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,
- pub,
- // kill repeat to save bytes
- afterbegin = "afterbegin",
- afterend = "afterend",
- beforebegin = "beforebegin",
- beforeend = "beforeend",
- ts = '<table>',
- te = '</table>',
- tbs = ts+'<tbody>',
- tbe = '</tbody>'+te,
- trs = tbs + '<tr>',
- tre = '</tr>'+tbe;
-
- // private
- function doInsert(el, o, returnElement, pos, sibling, append){
- var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));
- return returnElement ? Ext.get(newNode, true) : newNode;
- }
-
- // build as innerHTML where available
- function createHtml(o){
- var b = "",
- attr,
- val,
- key,
- keyVal,
- cn;
-
- if(typeof o == 'string'){
- b = o;
- } else if (Ext.isArray(o)) {
- Ext.each(o, function(v) {
- b += createHtml(v);
- });
- } else {
- b += "<" + (o.tag = o.tag || "div");
- Ext.iterate(o, function(attr, val){
- if(!/tag|children|cn|html$/i.test(attr)){
- if (Ext.isObject(val)) {
- b += " " + attr + "='";
- Ext.iterate(val, function(key, keyVal){
- b += key + ":" + keyVal + ";";
- });
- b += "'";
- }else{
- b += " " + ({cls : "class", htmlFor : "for"}[attr] || attr) + "='" + val + "'";
- }
- }
- });
- // Now either just close the tag or try to add children and close the tag.
- 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;
- while(++i < depth){
- el = el.firstChild;
- }
- return el;
- }
-
- /**
- * @ignore
- * Nasty code for IE's broken table implementation
- */
- function insertIntoTable(tag, where, el, html) {
- var node,
- before;
-
- tempTableEl = tempTableEl || document.createElement('div');
-
- if(tag == 'td' && (where == afterbegin || where == beforeend) ||
- !/td|tr|tbody/i.test(tag) && (where == beforebegin || where == afterend)) {
- return;
- }
- 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;
- }
-
-
- pub = {
- /**
- * Returns the markup for the passed Element(s) config.
- * @param {Object} o The DOM object spec (and children)
- * @return {String}
- */
- markup : function(o){
- return createHtml(o);
- },
-
- /**
- * Inserts an HTML fragment into the DOM.
- * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
- * @param {HTMLElement} el The context element
- * @param {String} html The HTML fragmenet
- * @return {HTMLElement} The new node
- */
- insertHtml : function(where, el, html){
- var hash = {},
- hashVal,
- setStart,
- range,
- frag,
- rangeEl,
- rs;
-
- where = where.toLowerCase();
- // add these here because they are used in both branches of the condition.
- 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;
- }
- // add these two to the hash.
- hash[afterbegin] = ['AfterBegin', 'firstChild'];
- hash[beforeend] = ['BeforeEnd', 'lastChild'];
- if ((hashVal = hash[where])) {
- el.insertAdjacentHTML(hashVal[0], html);
- return el[hashVal[1]];
- }
- } else {
- range = el.ownerDocument.createRange();
- setStart = "setStart" + (/end/i.test(where) ? "After" : "Before");
- if (hash[where]) {
- range[setStart](el);
- frag = range.createContextualFragment(html);
- el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);
- return el[(where == beforebegin ? "previous" : "next") + "Sibling"];
- } else {
- rangeEl = (where == afterbegin ? "first" : "last") + "Child";
- if (el.firstChild) {
- range[setStart](el[rangeEl]);
- frag = range.createContextualFragment(html);
- if(where == afterbegin){
- el.insertBefore(frag, el.firstChild);
- }else{
- el.appendChild(frag);
- }
- } else {
- el.innerHTML = html;
- }
- return el[rangeEl];
- }
- }
- throw 'Illegal insertion point -> "' + where + '"';
- },
-
- /**
- * Creates new DOM element(s) and inserts them before el.
- * @param {Mixed} el The context element
- * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
- * @param {Boolean} returnElement (optional) true to return a Ext.Element
- * @return {HTMLElement/Ext.Element} The new node
- */
- insertBefore : function(el, o, returnElement){
- return doInsert(el, o, returnElement, beforebegin);
- },
-
- /**
- * Creates new DOM element(s) and inserts them after el.
- * @param {Mixed} el The context element
- * @param {Object} o The DOM object spec (and children)
- * @param {Boolean} returnElement (optional) true to return a Ext.Element
- * @return {HTMLElement/Ext.Element} The new node
- */
- insertAfter : function(el, o, returnElement){
- return doInsert(el, o, returnElement, afterend, "nextSibling");
- },
-
- /**
- * Creates new DOM element(s) and inserts them as the first child of el.
- * @param {Mixed} el The context element
- * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
- * @param {Boolean} returnElement (optional) true to return a Ext.Element
- * @return {HTMLElement/Ext.Element} The new node
- */
- insertFirst : function(el, o, returnElement){
- return doInsert(el, o, returnElement, afterbegin, "firstChild");
- },
-
- /**
- * Creates new DOM element(s) and appends them to el.
- * @param {Mixed} el The context element
- * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
- * @param {Boolean} returnElement (optional) true to return a Ext.Element
- * @return {HTMLElement/Ext.Element} The new node
- */
- append : function(el, o, returnElement){
- return doInsert(el, o, returnElement, beforeend, "", true);
- },
-
- /**
- * Creates new DOM element(s) and overwrites the contents of el with them.
- * @param {Mixed} el The context element
- * @param {Object/String} o The DOM object spec (and children) or raw HTML blob
- * @param {Boolean} returnElement (optional) true to return a Ext.Element
- * @return {HTMLElement/Ext.Element} The new node
- */
- overwrite : function(el, o, returnElement){
- el = Ext.getDom(el);
- el.innerHTML = createHtml(o);
- return returnElement ? Ext.get(el.firstChild) : el.firstChild;
- },
-
- createHtml : createHtml
- };
- return pub;
+/**\r
+ * @class Ext.DomHelper\r
+ * <p>The DomHelper class provides a layer of abstraction from DOM and transparently supports creating\r
+ * elements via DOM or using HTML fragments. It also has the ability to create HTML fragment templates\r
+ * from your DOM building code.</p>\r
+ *\r
+ * <p><b><u>DomHelper element specification object</u></b></p>\r
+ * <p>A specification object is used when creating elements. Attributes of this object\r
+ * are assumed to be element attributes, except for 4 special attributes:\r
+ * <div class="mdetail-params"><ul>\r
+ * <li><b><tt>tag</tt></b> : <div class="sub-desc">The tag name of the element</div></li>\r
+ * <li><b><tt>children</tt></b> : or <tt>cn</tt><div class="sub-desc">An array of the\r
+ * same kind of element definition objects to be created and appended. These can be nested\r
+ * as deep as you want.</div></li>\r
+ * <li><b><tt>cls</tt></b> : <div class="sub-desc">The class attribute of the element.\r
+ * This will end up being either the "class" attribute on a HTML fragment or className\r
+ * for a DOM node, depending on whether DomHelper is using fragments or DOM.</div></li>\r
+ * <li><b><tt>html</tt></b> : <div class="sub-desc">The innerHTML for the element</div></li>\r
+ * </ul></div></p>\r
+ *\r
+ * <p><b><u>Insertion methods</u></b></p>\r
+ * <p>Commonly used insertion methods:\r
+ * <div class="mdetail-params"><ul>\r
+ * <li><b><tt>{@link #append}</tt></b> : <div class="sub-desc"></div></li>\r
+ * <li><b><tt>{@link #insertBefore}</tt></b> : <div class="sub-desc"></div></li>\r
+ * <li><b><tt>{@link #insertAfter}</tt></b> : <div class="sub-desc"></div></li>\r
+ * <li><b><tt>{@link #overwrite}</tt></b> : <div class="sub-desc"></div></li>\r
+ * <li><b><tt>{@link #createTemplate}</tt></b> : <div class="sub-desc"></div></li>\r
+ * <li><b><tt>{@link #insertHtml}</tt></b> : <div class="sub-desc"></div></li>\r
+ * </ul></div></p>\r
+ *\r
+ * <p><b><u>Example</u></b></p>\r
+ * <p>This is an example, where an unordered list with 3 children items is appended to an existing\r
+ * element with id <tt>'my-div'</tt>:<br>\r
+ <pre><code>\r
+var dh = Ext.DomHelper; // create shorthand alias\r
+// specification object\r
+var spec = {\r
+ id: 'my-ul',\r
+ tag: 'ul',\r
+ cls: 'my-list',\r
+ // append children after creating\r
+ children: [ // may also specify 'cn' instead of 'children'\r
+ {tag: 'li', id: 'item0', html: 'List Item 0'},\r
+ {tag: 'li', id: 'item1', html: 'List Item 1'},\r
+ {tag: 'li', id: 'item2', html: 'List Item 2'}\r
+ ]\r
+};\r
+var list = dh.append(\r
+ 'my-div', // the context element 'my-div' can either be the id or the actual node\r
+ spec // the specification object\r
+);\r
+ </code></pre></p>\r
+ * <p>Element creation specification parameters in this class may also be passed as an Array of\r
+ * specification objects. This can be used to insert multiple sibling nodes into an existing\r
+ * container very efficiently. For example, to add more list items to the example above:<pre><code>\r
+dh.append('my-ul', [\r
+ {tag: 'li', id: 'item3', html: 'List Item 3'},\r
+ {tag: 'li', id: 'item4', html: 'List Item 4'}\r
+]);\r
+ * </code></pre></p>\r
+ *\r
+ * <p><b><u>Templating</u></b></p>\r
+ * <p>The real power is in the built-in templating. Instead of creating or appending any elements,\r
+ * <tt>{@link #createTemplate}</tt> returns a Template object which can be used over and over to\r
+ * insert new elements. Revisiting the example above, we could utilize templating this time:\r
+ * <pre><code>\r
+// create the node\r
+var list = dh.append('my-div', {tag: 'ul', cls: 'my-list'});\r
+// get template\r
+var tpl = dh.createTemplate({tag: 'li', id: 'item{0}', html: 'List Item {0}'});\r
+\r
+for(var i = 0; i < 5, i++){\r
+ tpl.append(list, [i]); // use template to append to the actual node\r
+}\r
+ * </code></pre></p>\r
+ * <p>An example using a template:<pre><code>\r
+var html = '<a id="{0}" href="{1}" class="nav">{2}</a>';\r
+\r
+var tpl = new Ext.DomHelper.createTemplate(html);\r
+tpl.append('blog-roll', ['link1', 'http://www.jackslocum.com/', "Jack's Site"]);\r
+tpl.append('blog-roll', ['link2', 'http://www.dustindiaz.com/', "Dustin's Site"]);\r
+ * </code></pre></p>\r
+ *\r
+ * <p>The same example using named parameters:<pre><code>\r
+var html = '<a id="{id}" href="{url}" class="nav">{text}</a>';\r
+\r
+var tpl = new Ext.DomHelper.createTemplate(html);\r
+tpl.append('blog-roll', {\r
+ id: 'link1',\r
+ url: 'http://www.jackslocum.com/',\r
+ text: "Jack's Site"\r
+});\r
+tpl.append('blog-roll', {\r
+ id: 'link2',\r
+ url: 'http://www.dustindiaz.com/',\r
+ text: "Dustin's Site"\r
+});\r
+ * </code></pre></p>\r
+ *\r
+ * <p><b><u>Compiling Templates</u></b></p>\r
+ * <p>Templates are applied using regular expressions. The performance is great, but if\r
+ * you are adding a bunch of DOM elements using the same template, you can increase\r
+ * performance even further by {@link Ext.Template#compile "compiling"} the template.\r
+ * The way "{@link Ext.Template#compile compile()}" works is the template is parsed and\r
+ * broken up at the different variable points and a dynamic function is created and eval'ed.\r
+ * The generated function performs string concatenation of these parts and the passed\r
+ * variables instead of using regular expressions.\r
+ * <pre><code>\r
+var html = '<a id="{id}" href="{url}" class="nav">{text}</a>';\r
+\r
+var tpl = new Ext.DomHelper.createTemplate(html);\r
+tpl.compile();\r
+\r
+//... use template like normal\r
+ * </code></pre></p>\r
+ *\r
+ * <p><b><u>Performance Boost</u></b></p>\r
+ * <p>DomHelper will transparently create HTML fragments when it can. Using HTML fragments instead\r
+ * of DOM can significantly boost performance.</p>\r
+ * <p>Element creation specification parameters may also be strings. If {@link #useDom} is <tt>false</tt>,\r
+ * then the string is used as innerHTML. If {@link #useDom} is <tt>true</tt>, a string specification\r
+ * results in the creation of a text node. Usage:</p>\r
+ * <pre><code>\r
+Ext.DomHelper.useDom = true; // force it to use DOM; reduces performance\r
+ * </code></pre>\r
+ * @singleton\r
+ */\r
+Ext.DomHelper = function(){\r
+ var tempTableEl = null,\r
+ emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i,\r
+ tableRe = /^table|tbody|tr|td$/i,\r
+ pub,\r
+ // kill repeat to save bytes\r
+ afterbegin = 'afterbegin',\r
+ afterend = 'afterend',\r
+ beforebegin = 'beforebegin',\r
+ beforeend = 'beforeend',\r
+ ts = '<table>',\r
+ te = '</table>',\r
+ tbs = ts+'<tbody>',\r
+ tbe = '</tbody>'+te,\r
+ trs = tbs + '<tr>',\r
+ tre = '</tr>'+tbe;\r
+\r
+ // private\r
+ function doInsert(el, o, returnElement, pos, sibling, append){\r
+ var newNode = pub.insertHtml(pos, Ext.getDom(el), createHtml(o));\r
+ return returnElement ? Ext.get(newNode, true) : newNode;\r
+ }\r
+\r
+ // build as innerHTML where available\r
+ function createHtml(o){\r
+ var b = '',\r
+ attr,\r
+ val,\r
+ key,\r
+ keyVal,\r
+ cn;\r
+\r
+ if(Ext.isString(o)){\r
+ b = o;\r
+ } else if (Ext.isArray(o)) {\r
+ Ext.each(o, function(v) {\r
+ b += createHtml(v);\r
+ });\r
+ } else {\r
+ b += '<' + (o.tag = o.tag || 'div');\r
+ Ext.iterate(o, function(attr, val){\r
+ if(!/tag|children|cn|html$/i.test(attr)){\r
+ if (Ext.isObject(val)) {\r
+ b += ' ' + attr + '="';\r
+ Ext.iterate(val, function(key, keyVal){\r
+ b += key + ':' + keyVal + ';';\r
+ });\r
+ b += '"';\r
+ }else{\r
+ b += ' ' + ({cls : 'class', htmlFor : 'for'}[attr] || attr) + '="' + val + '"';\r
+ }\r
+ }\r
+ });\r
+ // Now either just close the tag or try to add children and close the tag.\r
+ if (emptyTags.test(o.tag)) {\r
+ b += '/>';\r
+ } else {\r
+ b += '>';\r
+ if ((cn = o.children || o.cn)) {\r
+ b += createHtml(cn);\r
+ } else if(o.html){\r
+ b += o.html;\r
+ }\r
+ b += '</' + o.tag + '>';\r
+ }\r
+ }\r
+ return b;\r
+ }\r
+\r
+ function ieTable(depth, s, h, e){\r
+ tempTableEl.innerHTML = [s, h, e].join('');\r
+ var i = -1,\r
+ el = tempTableEl,\r
+ ns;\r
+ while(++i < depth){\r
+ el = el.firstChild;\r
+ }\r
+// If the result is multiple siblings, then encapsulate them into one fragment.\r
+ if(ns = el.nextSibling){\r
+ var df = document.createDocumentFragment();\r
+ while(el){\r
+ ns = el.nextSibling;\r
+ df.appendChild(el);\r
+ el = ns;\r
+ }\r
+ el = df;\r
+ }\r
+ return el;\r
+ }\r
+\r
+ /**\r
+ * @ignore\r
+ * Nasty code for IE's broken table implementation\r
+ */\r
+ function insertIntoTable(tag, where, el, html) {\r
+ var node,\r
+ before;\r
+\r
+ tempTableEl = tempTableEl || document.createElement('div');\r
+\r
+ if(tag == 'td' && (where == afterbegin || where == beforeend) ||\r
+ !/td|tr|tbody/i.test(tag) && (where == beforebegin || where == afterend)) {\r
+ return;\r
+ }\r
+ before = where == beforebegin ? el :\r
+ where == afterend ? el.nextSibling :\r
+ where == afterbegin ? el.firstChild : null;\r
+\r
+ if (where == beforebegin || where == afterend) {\r
+ el = el.parentNode;\r
+ }\r
+\r
+ if (tag == 'td' || (tag == 'tr' && (where == beforeend || where == afterbegin))) {\r
+ node = ieTable(4, trs, html, tre);\r
+ } else if ((tag == 'tbody' && (where == beforeend || where == afterbegin)) ||\r
+ (tag == 'tr' && (where == beforebegin || where == afterend))) {\r
+ node = ieTable(3, tbs, html, tbe);\r
+ } else {\r
+ node = ieTable(2, ts, html, te);\r
+ }\r
+ el.insertBefore(node, before);\r
+ return node;\r
+ }\r
+\r
+\r
+ pub = {\r
+ /**\r
+ * Returns the markup for the passed Element(s) config.\r
+ * @param {Object} o The DOM object spec (and children)\r
+ * @return {String}\r
+ */\r
+ markup : function(o){\r
+ return createHtml(o);\r
+ },\r
+ \r
+ /**\r
+ * Applies a style specification to an element.\r
+ * @param {String/HTMLElement} el The element to apply styles to\r
+ * @param {String/Object/Function} styles A style specification string e.g. 'width:100px', or object in the form {width:'100px'}, or\r
+ * a function which returns such a specification.\r
+ */\r
+ applyStyles : function(el, styles){\r
+ if(styles){\r
+ var i = 0,\r
+ len,\r
+ style;\r
+\r
+ el = Ext.fly(el);\r
+ if(Ext.isFunction(styles)){\r
+ styles = styles.call();\r
+ }\r
+ if(Ext.isString(styles)){\r
+ styles = styles.trim().split(/\s*(?::|;)\s*/);\r
+ for(len = styles.length; i < len;){\r
+ el.setStyle(styles[i++], styles[i++]);\r
+ }\r
+ }else if (Ext.isObject(styles)){\r
+ el.setStyle(styles);\r
+ }\r
+ }\r
+ },\r
+\r
+ /**\r
+ * Inserts an HTML fragment into the DOM.\r
+ * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.\r
+ * @param {HTMLElement} el The context element\r
+ * @param {String} html The HTML fragment\r
+ * @return {HTMLElement} The new node\r
+ */\r
+ insertHtml : function(where, el, html){\r
+ var hash = {},\r
+ hashVal,\r
+ setStart,\r
+ range,\r
+ frag,\r
+ rangeEl,\r
+ rs;\r
+\r
+ where = where.toLowerCase();\r
+ // add these here because they are used in both branches of the condition.\r
+ hash[beforebegin] = ['BeforeBegin', 'previousSibling'];\r
+ hash[afterend] = ['AfterEnd', 'nextSibling'];\r
+\r
+ if (el.insertAdjacentHTML) {\r
+ if(tableRe.test(el.tagName) && (rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html))){\r
+ return rs;\r
+ }\r
+ // add these two to the hash.\r
+ hash[afterbegin] = ['AfterBegin', 'firstChild'];\r
+ hash[beforeend] = ['BeforeEnd', 'lastChild'];\r
+ if ((hashVal = hash[where])) {\r
+ el.insertAdjacentHTML(hashVal[0], html);\r
+ return el[hashVal[1]];\r
+ }\r
+ } else {\r
+ range = el.ownerDocument.createRange();\r
+ setStart = 'setStart' + (/end/i.test(where) ? 'After' : 'Before');\r
+ if (hash[where]) {\r
+ range[setStart](el);\r
+ frag = range.createContextualFragment(html);\r
+ el.parentNode.insertBefore(frag, where == beforebegin ? el : el.nextSibling);\r
+ return el[(where == beforebegin ? 'previous' : 'next') + 'Sibling'];\r
+ } else {\r
+ rangeEl = (where == afterbegin ? 'first' : 'last') + 'Child';\r
+ if (el.firstChild) {\r
+ range[setStart](el[rangeEl]);\r
+ frag = range.createContextualFragment(html);\r
+ if(where == afterbegin){\r
+ el.insertBefore(frag, el.firstChild);\r
+ }else{\r
+ el.appendChild(frag);\r
+ }\r
+ } else {\r
+ el.innerHTML = html;\r
+ }\r
+ return el[rangeEl];\r
+ }\r
+ }\r
+ throw 'Illegal insertion point -> "' + where + '"';\r
+ },\r
+\r
+ /**\r
+ * Creates new DOM element(s) and inserts them before el.\r
+ * @param {Mixed} el The context element\r
+ * @param {Object/String} o The DOM object spec (and children) or raw HTML blob\r
+ * @param {Boolean} returnElement (optional) true to return a Ext.Element\r
+ * @return {HTMLElement/Ext.Element} The new node\r
+ */\r
+ insertBefore : function(el, o, returnElement){\r
+ return doInsert(el, o, returnElement, beforebegin);\r
+ },\r
+\r
+ /**\r
+ * Creates new DOM element(s) and inserts them after el.\r
+ * @param {Mixed} el The context element\r
+ * @param {Object} o The DOM object spec (and children)\r
+ * @param {Boolean} returnElement (optional) true to return a Ext.Element\r
+ * @return {HTMLElement/Ext.Element} The new node\r
+ */\r
+ insertAfter : function(el, o, returnElement){\r
+ return doInsert(el, o, returnElement, afterend, 'nextSibling');\r
+ },\r
+\r
+ /**\r
+ * Creates new DOM element(s) and inserts them as the first child of el.\r
+ * @param {Mixed} el The context element\r
+ * @param {Object/String} o The DOM object spec (and children) or raw HTML blob\r
+ * @param {Boolean} returnElement (optional) true to return a Ext.Element\r
+ * @return {HTMLElement/Ext.Element} The new node\r
+ */\r
+ insertFirst : function(el, o, returnElement){\r
+ return doInsert(el, o, returnElement, afterbegin, 'firstChild');\r
+ },\r
+\r
+ /**\r
+ * Creates new DOM element(s) and appends them to el.\r
+ * @param {Mixed} el The context element\r
+ * @param {Object/String} o The DOM object spec (and children) or raw HTML blob\r
+ * @param {Boolean} returnElement (optional) true to return a Ext.Element\r
+ * @return {HTMLElement/Ext.Element} The new node\r
+ */\r
+ append : function(el, o, returnElement){\r
+ return doInsert(el, o, returnElement, beforeend, '', true);\r
+ },\r
+\r
+ /**\r
+ * Creates new DOM element(s) and overwrites the contents of el with them.\r
+ * @param {Mixed} el The context element\r
+ * @param {Object/String} o The DOM object spec (and children) or raw HTML blob\r
+ * @param {Boolean} returnElement (optional) true to return a Ext.Element\r
+ * @return {HTMLElement/Ext.Element} The new node\r
+ */\r
+ overwrite : function(el, o, returnElement){\r
+ el = Ext.getDom(el);\r
+ el.innerHTML = createHtml(o);\r
+ return returnElement ? Ext.get(el.firstChild) : el.firstChild;\r
+ },\r
+\r
+ createHtml : createHtml\r
+ };\r
+ return pub;\r
}();/**\r
* @class Ext.DomHelper\r
*/\r
}\r
}\r
});\r
- pub.applyStyles(el, o.style);\r
+ Ext.DomHelper.applyStyles(el, o.style);\r
\r
if ((cn = o.children || o.cn)) {\r
createDom(cn, el);\r
/** True to force the use of DOM instead of html fragments @type Boolean */\r
useDom : false,\r
\r
- /**\r
- * Applies a style specification to an element.\r
- * @param {String/HTMLElement} el The element to apply styles to\r
- * @param {String/Object/Function} styles A style specification string e.g. 'width:100px', or object in the form {width:'100px'}, or\r
- * a function which returns such a specification.\r
- */\r
- applyStyles : function(el, styles){\r
- if(styles){\r
- var i = 0,\r
- len,\r
- style;\r
-\r
- el = Ext.fly(el);\r
- if(Ext.isFunction(styles)){\r
- styles = styles.call();\r
- }\r
- if(Ext.isString(styles)){\r
- styles = styles.trim().split(/\s*(?::|;)\s*/);\r
- for(len = styles.length; i < len;){\r
- el.setStyle(styles[i++], styles[i++]);\r
- }\r
- }else if (Ext.isObject(styles)){\r
- el.setStyle(styles);\r
- }\r
- }\r
- },\r
-\r
/**\r
* Creates new DOM element(s) and inserts them before el.\r
* @param {Mixed} el The context element\r
return pub;\r
}());/**
* @class Ext.Template
- * Represents an HTML fragment template. Templates can be precompiled for greater performance.
- * For a list of available format functions, see {@link Ext.util.Format}.<br />
- * Usage:
+ * <p>Represents an HTML fragment template. Templates may be {@link #compile precompiled}
+ * for greater performance.</p>
+ * <p>For example usage {@link #Template see the constructor}.</p>
+ *
+ * @constructor
+ * An instance of this class may be created by passing to the constructor either
+ * a single argument, or multiple arguments:
+ * <div class="mdetail-params"><ul>
+ * <li><b>single argument</b> : String/Array
+ * <div class="sub-desc">
+ * The single argument may be either a String or an Array:<ul>
+ * <li><tt>String</tt> : </li><pre><code>
+var t = new Ext.Template("<div>Hello {0}.</div>");
+t.{@link #append}('some-element', ['foo']);
+ * </code></pre>
+ * <li><tt>Array</tt> : </li>
+ * An Array will be combined with <code>join('')</code>.
<pre><code>
-var t = new Ext.Template(
+var t = new Ext.Template([
'<div name="{id}">',
'<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
- '</div>'
-);
-t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
+ '</div>',
+]);
+t.{@link #compile}();
+t.{@link #append}('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
</code></pre>
- * @constructor
- * @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
+ * </ul></div></li>
+ * <li><b>multiple arguments</b> : String, Object, Array, ...
+ * <div class="sub-desc">
+ * Multiple arguments will be combined with <code>join('')</code>.
+ * <pre><code>
+var t = new Ext.Template(
+ '<div name="{id}">',
+ '<span class="{cls}">{name} {value}</span>',
+ '</div>',
+ // a configuration object:
+ {
+ compiled: true, // {@link #compile} immediately
+ disableFormats: true // See Notes below.
+ }
+);
+ * </code></pre>
+ * <p><b>Notes</b>:</p>
+ * <div class="mdetail-params"><ul>
+ * <li>Formatting and <code>disableFormats</code> are not applicable for Ext Core.</li>
+ * <li>For a list of available format functions, see {@link Ext.util.Format}.</li>
+ * <li><code>disableFormats</code> reduces <code>{@link #apply}</code> time
+ * when no formatting is required.</li>
+ * </ul></div>
+ * </div></li>
+ * </ul></div>
+ * @param {Mixed} config
*/
Ext.Template = function(html){
var me = this,
/**@private*/
me.html = html;
+ /**
+ * @cfg {Boolean} compiled Specify <tt>true</tt> to compile the template
+ * immediately (see <code>{@link #compile}</code>).
+ * Defaults to <tt>false</tt>.
+ */
if (me.compiled) {
me.compile();
}
};
Ext.Template.prototype = {
/**
- * Returns an HTML fragment of this template with the specified values applied.
- * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
+ * @cfg {RegExp} re The regular expression used to match template variables.
+ * Defaults to:<pre><code>
+ * re : /\{([\w-]+)\}/g // for Ext Core
+ * re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g // for Ext JS
+ * </code></pre>
+ */
+ re : /\{([\w-]+)\}/g,
+ /**
+ * See <code>{@link #re}</code>.
+ * @type RegExp
+ * @property re
+ */
+
+ /**
+ * Returns an HTML fragment of this template with the specified <code>values</code> applied.
+ * @param {Object/Array} values
+ * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
+ * or an object (i.e. <code>{foo: 'bar'}</code>).
* @return {String} The HTML fragment
*/
applyTemplate : function(values){
return compile ? me.compile() : me;
},
- /**
- * The regular expression used to match template variables
- * @type RegExp
- * @property
- */
- re : /\{([\w-]+)\}/g,
-
/**
* Compiles the template into an internal function, eliminating the RegEx overhead.
* @return {Ext.Template} this
},
/**
- * Applies the supplied values to the template and appends the new node(s) to el.
+ * Applies the supplied <code>values</code> to the template and appends
+ * the new node(s) to the specified <code>el</code>.
+ * <p>For example usage {@link #Template see the constructor}.</p>
* @param {Mixed} el The context element
- * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
- * @param {Boolean} returnElement (optional) true to return a Ext.Element (defaults to undefined)
+ * @param {Object/Array} values
+ * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
+ * or an object (i.e. <code>{foo: 'bar'}</code>).
+ * @param {Boolean} returnElement (optional) true to return an Ext.Element (defaults to undefined)
* @return {HTMLElement/Ext.Element} The new node or Element
*/
append : function(el, values, returnElement){
};
/**
* Alias for {@link #applyTemplate}
- * Returns an HTML fragment of this template with the specified values applied.
- * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
+ * Returns an HTML fragment of this template with the specified <code>values</code> applied.
+ * @param {Object/Array} values
+ * The template values. Can be an array if the params are numeric (i.e. <code>{0}</code>)
+ * or an object (i.e. <code>{foo: 'bar'}</code>).
* @return {String} The HTML fragment
* @member Ext.Template
* @method apply
*/\r
Ext.apply(Ext.Template.prototype, {\r
/**\r
- * Returns an HTML fragment of this template with the specified values applied.\r
- * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})\r
- * @return {String} The HTML fragment\r
- * @hide repeat doc\r
+ * @cfg {Boolean} disableFormats Specify <tt>true</tt> to disable format\r
+ * functions in the template. If the template does not contain\r
+ * {@link Ext.util.Format format functions}, setting <code>disableFormats</code>\r
+ * to true will reduce <code>{@link #apply}</code> time. Defaults to <tt>false</tt>.\r
+ * <pre><code>\r
+var t = new Ext.Template(\r
+ '<div name="{id}">',\r
+ '<span class="{cls}">{name} {value}</span>',\r
+ '</div>',\r
+ {\r
+ compiled: true, // {@link #compile} immediately\r
+ disableFormats: true // reduce <code>{@link #apply}</code> time since no formatting\r
+ } \r
+);\r
+ * </code></pre>\r
+ * For a list of available format functions, see {@link Ext.util.Format}.\r
*/\r
- applyTemplate : function(values){\r
- var me = this,\r
+ disableFormats : false, \r
+ /**\r
+ * See <code>{@link #disableFormats}</code>.\r
+ * @type Boolean\r
+ * @property disableFormats\r
+ */\r
+\r
+ /**\r
+ * The regular expression used to match template variables\r
+ * @type RegExp\r
+ * @property\r
+ * @hide repeat doc\r
+ */\r
+ re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,\r
+\r
+ /**\r
+ * Returns an HTML fragment of this template with the specified values applied.\r
+ * @param {Object/Array} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})\r
+ * @return {String} The HTML fragment\r
+ * @hide repeat doc\r
+ */\r
+ applyTemplate : function(values){\r
+ var me = this,\r
useF = me.disableFormats !== true,\r
fm = Ext.util.Format, \r
tpl = me; \r
return me.html.replace(me.re, fn);\r
},\r
\r
- /**\r
- * <tt>true</tt> to disable format functions (defaults to <tt>false</tt>)\r
- * @type Boolean\r
- * @property\r
- */\r
- disableFormats : false, \r
- \r
- /**\r
- * The regular expression used to match template variables\r
- * @type RegExp\r
- * @property\r
- * @hide repeat doc\r
- */\r
- re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,\r
- \r
/**\r
* Compiles the template into an internal function, eliminating the RegEx overhead.\r
* @return {Ext.Template} this\r
},\r
\r
/**\r
- * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)\r
- * and the argument (if any) supplied in the selector.\r
+ * <p>Object hash of "pseudo class" filter functions which are used when filtering selections. Each function is passed\r
+ * two parameters:</p><div class="mdetail-params"><ul>\r
+ * <li><b>c</b> : Array<div class="sub-desc">An Array of DOM elements to filter.</div></li>\r
+ * <li><b>v</b> : String<div class="sub-desc">The argument (if any) supplied in the selector.</div></li>\r
+ * </ul></div>\r
+ * <p>A filter function returns an Array of DOM elements which conform to the pseudo class.</p>\r
+ * <p>In addition to the provided pseudo classes listed above such as <code>first-child</code> and <code>nth-child</code>,\r
+ * developers may add additional, custom psuedo class filters to select elements according to application-specific requirements.</p>\r
+ * <p>For example, to filter <code><a></code> elements to only return links to <i>external</i> resources:</p>\r
+ * <code><pre>\r
+Ext.DomQuery.pseudos.external = function(c, v){\r
+ var r = [], ri = -1;\r
+ for(var i = 0, ci; ci = c[i]; i++){\r
+// Include in result set only if it's a link to an external resource\r
+ if(ci.hostname != location.hostname){\r
+ r[++ri] = ci;\r
+ }\r
+ }\r
+ return r;\r
+};</pre></code>\r
+ * Then external links could be gathered with the following statement:<code><pre>\r
+var externalLinks = Ext.select("a:external");\r
+</code></pre>\r
*/\r
pseudos : {\r
"first-child" : function(c){\r
me.events = e || {};
};
-EXTUTIL.Observable.prototype = function(){
- var filterOptRe = /^(?:scope|delay|buffer|single)$/, toLower = function(s){
- return s.toLowerCase();
- };
-
- return {
- /**
- * <p>Fires the specified event with the passed parameters (minus the event name).</p>
- * <p>An event may be set to bubble up an Observable parent hierarchy (See {@link Ext.Component#getBubbleTarget})
- * by calling {@link #enableBubble}.</p>
- * @param {String} eventName The name of the event to fire.
- * @param {Object...} args Variable number of parameters are passed to handlers.
- * @return {Boolean} returns false if any of the handlers return false otherwise it returns true.
- */
+EXTUTIL.Observable.prototype = {
+ // private
+ filterOptRe : /^(?:scope|delay|buffer|single)$/,
- fireEvent : function(){
- var a = TOARRAY(arguments),
- ename = toLower(a[0]),
- me = this,
- ret = TRUE,
- ce = me.events[ename],
- q,
- c;
- if (me.eventsSuspended === TRUE) {
- if (q = me.suspendedEventsQueue) {
- q.push(a);
- }
+ /**
+ * <p>Fires the specified event with the passed parameters (minus the event name).</p>
+ * <p>An event may be set to bubble up an Observable parent hierarchy (See {@link Ext.Component#getBubbleTarget})
+ * by calling {@link #enableBubble}.</p>
+ * @param {String} eventName The name of the event to fire.
+ * @param {Object...} args Variable number of parameters are passed to handlers.
+ * @return {Boolean} returns false if any of the handlers return false otherwise it returns true.
+ */
+ fireEvent : function(){
+ var a = TOARRAY(arguments),
+ ename = a[0].toLowerCase(),
+ me = this,
+ ret = TRUE,
+ ce = me.events[ename],
+ q,
+ c;
+ if (me.eventsSuspended === TRUE) {
+ if (q = me.eventQueue) {
+ q.push(a);
}
- else if(ISOBJECT(ce) && ce.bubble){
- if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
- return FALSE;
- }
- c = me.getBubbleTarget && me.getBubbleTarget();
- if(c && c.enableBubble) {
+ }
+ else if(ISOBJECT(ce) && ce.bubble){
+ if(ce.fire.apply(ce, a.slice(1)) === FALSE) {
+ return FALSE;
+ }
+ c = me.getBubbleTarget && me.getBubbleTarget();
+ if(c && c.enableBubble) {
+ if(!c.events[ename] || !Ext.isObject(c.events[ename]) || !c.events[ename].bubble) {
c.enableBubble(ename);
- return c.fireEvent.apply(c, a);
}
+ return c.fireEvent.apply(c, a);
}
- else {
- if (ISOBJECT(ce)) {
- a.shift();
- ret = ce.fire.apply(ce, a);
- }
+ }
+ else {
+ if (ISOBJECT(ce)) {
+ a.shift();
+ ret = ce.fire.apply(ce, a);
}
- return ret;
- },
+ }
+ return ret;
+ },
- /**
- * Appends an event handler to this object.
- * @param {String} eventName The name of the event to listen for.
- * @param {Function} handler The method the event invokes.
- * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the handler function is executed.
- * <b>If omitted, defaults to the object which fired the event.</b>
- * @param {Object} options (optional) An object containing handler configuration.
- * properties. This may contain any of the following properties:<ul>
- * <li><b>scope</b> : Object<div class="sub-desc">The scope (<code><b>this</b></code> reference) in which the handler function is executed.
- * <b>If omitted, defaults to the object which fired the event.</b></div></li>
- * <li><b>delay</b> : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after the event fires.</div></li>
- * <li><b>single</b> : Boolean<div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
- * <li><b>buffer</b> : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
- * by the specified number of milliseconds. If the event fires again within that time, the original
- * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
- * <li><b>target</b> : Observable<div class="sub-desc">Only call the handler if the event was fired on the target Observable, <i>not</i>
- * if the event was bubbled up from a child Observable.</div></li>
- * </ul><br>
- * <p>
- * <b>Combining Options</b><br>
- * Using the options argument, it is possible to combine different types of listeners:<br>
- * <br>
- * A delayed, one-time listener.
- * <pre><code>
+ /**
+ * Appends an event handler to this object.
+ * @param {String} eventName The name of the event to listen for.
+ * @param {Function} handler The method the event invokes.
+ * @param {Object} scope (optional) The scope (<code><b>this</b></code> reference) in which the handler function is executed.
+ * <b>If omitted, defaults to the object which fired the event.</b>
+ * @param {Object} options (optional) An object containing handler configuration.
+ * properties. This may contain any of the following properties:<ul>
+ * <li><b>scope</b> : Object<div class="sub-desc">The scope (<code><b>this</b></code> reference) in which the handler function is executed.
+ * <b>If omitted, defaults to the object which fired the event.</b></div></li>
+ * <li><b>delay</b> : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after the event fires.</div></li>
+ * <li><b>single</b> : Boolean<div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
+ * <li><b>buffer</b> : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
+ * by the specified number of milliseconds. If the event fires again within that time, the original
+ * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
+ * <li><b>target</b> : Observable<div class="sub-desc">Only call the handler if the event was fired on the target Observable, <i>not</i>
+ * if the event was bubbled up from a child Observable.</div></li>
+ * </ul><br>
+ * <p>
+ * <b>Combining Options</b><br>
+ * Using the options argument, it is possible to combine different types of listeners:<br>
+ * <br>
+ * A delayed, one-time listener.
+ * <pre><code>
myDataView.on('click', this.onClick, this, {
- single: true,
- delay: 100
-});</code></pre>
- * <p>
- * <b>Attaching multiple handlers in 1 call</b><br>
- * The method also allows for a single argument to be passed which is a config object containing properties
- * which specify multiple handlers.
- * <p>
- * <pre><code>
-myGridPanel.on({
- 'click' : {
- fn: this.onClick,
- scope: this,
- delay: 100
- },
- 'mouseover' : {
- fn: this.onMouseOver,
- scope: this
- },
- 'mouseout' : {
- fn: this.onMouseOut,
- scope: this
- }
+single: true,
+delay: 100
});</code></pre>
* <p>
- * Or a shorthand syntax:<br>
+ * <b>Attaching multiple handlers in 1 call</b><br>
+ * The method also allows for a single argument to be passed which is a config object containing properties
+ * which specify multiple handlers.
+ * <p>
* <pre><code>
myGridPanel.on({
- 'click' : this.onClick,
- 'mouseover' : this.onMouseOver,
- 'mouseout' : this.onMouseOut,
- scope: this
+'click' : {
+ fn: this.onClick,
+ scope: this,
+ delay: 100
+},
+'mouseover' : {
+ fn: this.onMouseOver,
+ scope: this
+},
+'mouseout' : {
+ fn: this.onMouseOut,
+ scope: this
+}
});</code></pre>
- */
- addListener : function(eventName, fn, scope, o){
- var me = this,
- e,
- oe,
- isF,
- ce;
- if (ISOBJECT(eventName)) {
- o = eventName;
- for (e in o){
- oe = o[e];
- if (!filterOptRe.test(e)) {
- me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
- }
- }
- } else {
- eventName = toLower(eventName);
- ce = me.events[eventName] || TRUE;
- if (typeof ce == "boolean") {
- me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
+ * <p>
+ * Or a shorthand syntax:<br>
+ * <pre><code>
+myGridPanel.on({
+'click' : this.onClick,
+'mouseover' : this.onMouseOver,
+'mouseout' : this.onMouseOut,
+ scope: this
+});</code></pre>
+ */
+ addListener : function(eventName, fn, scope, o){
+ var me = this,
+ e,
+ oe,
+ isF,
+ ce;
+ if (ISOBJECT(eventName)) {
+ o = eventName;
+ for (e in o){
+ oe = o[e];
+ if (!me.filterOptRe.test(e)) {
+ me.addListener(e, oe.fn || oe, oe.scope || o.scope, oe.fn ? oe : o);
}
- ce.addListener(fn, scope, ISOBJECT(o) ? o : {});
}
- },
-
- /**
- * Removes an event handler.
- * @param {String} eventName The type of event the handler was associated with.
- * @param {Function} handler The handler to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
- * @param {Object} scope (optional) The scope originally specified for the handler.
- */
- removeListener : function(eventName, fn, scope){
- var ce = this.events[toLower(eventName)];
- if (ISOBJECT(ce)) {
- ce.removeListener(fn, scope);
+ } else {
+ eventName = eventName.toLowerCase();
+ ce = me.events[eventName] || TRUE;
+ if (Ext.isBoolean(ce)) {
+ me.events[eventName] = ce = new EXTUTIL.Event(me, eventName);
}
- },
+ ce.addListener(fn, scope, ISOBJECT(o) ? o : {});
+ }
+ },
- /**
- * Removes all listeners for this object
- */
- purgeListeners : function(){
- var events = this.events,
- evt,
- key;
- for(key in events){
- evt = events[key];
- if(ISOBJECT(evt)){
- evt.clearListeners();
- }
- }
- },
+ /**
+ * Removes an event handler.
+ * @param {String} eventName The type of event the handler was associated with.
+ * @param {Function} handler The handler to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
+ * @param {Object} scope (optional) The scope originally specified for the handler.
+ */
+ removeListener : function(eventName, fn, scope){
+ var ce = this.events[eventName.toLowerCase()];
+ if (ISOBJECT(ce)) {
+ ce.removeListener(fn, scope);
+ }
+ },
- /**
- * Used to define events on this Observable
- * @param {Object} object The object with the events defined
- */
- addEvents : function(o){
- var me = this;
- me.events = me.events || {};
- if (typeof o == 'string') {
- EACH(arguments, function(a) {
- me.events[a] = me.events[a] || TRUE;
- });
- } else {
- Ext.applyIf(me.events, o);
+ /**
+ * Removes all listeners for this object
+ */
+ purgeListeners : function(){
+ var events = this.events,
+ evt,
+ key;
+ for(key in events){
+ evt = events[key];
+ if(ISOBJECT(evt)){
+ evt.clearListeners();
}
- },
+ }
+ },
- /**
- * Checks to see if this object has any listeners for a specified event
- * @param {String} eventName The name of the event to check for
- * @return {Boolean} True if the event is being listened for, else false
- */
- hasListener : function(eventName){
- var e = this.events[eventName];
- return ISOBJECT(e) && e.listeners.length > 0;
- },
+ /**
+ * Adds the specified events to the list of events which this Observable may fire.
+ * @param {Object|String} o Either an object with event names as properties with a value of <code>true</code>
+ * or the first event name string if multiple event names are being passed as separate parameters.
+ * @param {string} Optional. Event name if multiple event names are being passed as separate parameters.
+ * Usage:<pre><code>
+this.addEvents('storeloaded', 'storecleared');
+</code></pre>
+ */
+ addEvents : function(o){
+ var me = this;
+ me.events = me.events || {};
+ if (Ext.isString(o)) {
+ EACH(arguments, function(a) {
+ me.events[a] = me.events[a] || TRUE;
+ });
+ } else {
+ Ext.applyIf(me.events, o);
+ }
+ },
- /**
- * Suspend the firing of all events. (see {@link #resumeEvents})
- * @param {Boolean} queueSuspended Pass as true to queue up suspended events to be fired
- * after the {@link #resumeEvents} call instead of discarding all suspended events;
- */
- suspendEvents : function(queueSuspended){
- this.eventsSuspended = TRUE;
- if (queueSuspended){
- this.suspendedEventsQueue = [];
- }
- },
+ /**
+ * Checks to see if this object has any listeners for a specified event
+ * @param {String} eventName The name of the event to check for
+ * @return {Boolean} True if the event is being listened for, else false
+ */
+ hasListener : function(eventName){
+ var e = this.events[eventName];
+ return ISOBJECT(e) && e.listeners.length > 0;
+ },
- /**
- * Resume firing events. (see {@link #suspendEvents})
- * If events were suspended using the <tt><b>queueSuspended</b></tt> parameter, then all
- * events fired during event suspension will be sent to any listeners now.
- */
- resumeEvents : function(){
- var me = this;
- me.eventsSuspended = !delete me.suspendedEventQueue;
- EACH(me.suspendedEventsQueue, function(e) {
- me.fireEvent.apply(me, e);
- });
+ /**
+ * Suspend the firing of all events. (see {@link #resumeEvents})
+ * @param {Boolean} queueSuspended Pass as true to queue up suspended events to be fired
+ * after the {@link #resumeEvents} call instead of discarding all suspended events;
+ */
+ suspendEvents : function(queueSuspended){
+ this.eventsSuspended = TRUE;
+ if(queueSuspended && !this.eventQueue){
+ this.eventQueue = [];
}
+ },
+
+ /**
+ * Resume firing events. (see {@link #suspendEvents})
+ * If events were suspended using the <tt><b>queueSuspended</b></tt> parameter, then all
+ * events fired during event suspension will be sent to any listeners now.
+ */
+ resumeEvents : function(){
+ var me = this,
+ queued = me.eventQueue || [];
+ me.eventsSuspended = FALSE;
+ delete me.eventQueue;
+ EACH(queued, function(e) {
+ me.fireEvent.apply(me, e);
+ });
}
-}();
+};
var OBSERVABLE = EXTUTIL.Observable.prototype;
/**
},\r
\r
/**\r
- * Used to enable bubbling of events\r
- * @param {Object} events\r
+ * <p>Enables events fired by this Observable to bubble up an owner hierarchy by calling\r
+ * <code>this.getBubbleTarget()</code> if present. There is no implementation in the Observable base class.</p>\r
+ * <p>This is commonly used by Ext.Components to bubble events to owner Containers. See {@link Ext.Component.getBubbleTarget}. The default\r
+ * implementation in Ext.Component returns the Component's immediate owner. But if a known target is required, this can be overridden to\r
+ * access the required target more quickly.</p>\r
+ * <p>Example:</p><pre><code>\r
+Ext.override(Ext.form.Field, {\r
+// Add functionality to Field's initComponent to enable the change event to bubble\r
+ initComponent: Ext.form.Field.prototype.initComponent.createSequence(function() {\r
+ this.enableBubble('change');\r
+ }),\r
+\r
+// We know that we want Field's events to bubble directly to the FormPanel.\r
+ getBubbleTarget: function() {\r
+ if (!this.formPanel) {\r
+ this.formPanel = this.findParentByType('form');\r
+ }\r
+ return this.formPanel;\r
+ }\r
+});\r
+\r
+var myForm = new Ext.formPanel({\r
+ title: 'User Details',\r
+ items: [{\r
+ ...\r
+ }],\r
+ listeners: {\r
+ change: function() {\r
+// Title goes red if form has been modified.\r
+ myForm.header.setStyle("color", "red");\r
+ }\r
+ }\r
+});\r
+</code></pre>\r
+ * @param {Object} events The event name to bubble, or an Array of event names.\r
*/\r
enableBubble: function(events){\r
var me = this;\r
- events = Ext.isArray(events) ? events : Ext.toArray(arguments);\r
- Ext.each(events, function(ename){\r
- ename = ename.toLowerCase();\r
- var ce = me.events[ename] || true;\r
- if (typeof ce == "boolean") {\r
- ce = new Ext.util.Event(me, ename);\r
- me.events[ename] = ce;\r
- }\r
- ce.bubble = true;\r
- });\r
+ if(!Ext.isEmpty(events)){\r
+ events = Ext.isArray(events) ? events : Ext.toArray(arguments);\r
+ Ext.each(events, function(ename){\r
+ ename = ename.toLowerCase();\r
+ var ce = me.events[ename] || true;\r
+ if (Ext.isBoolean(ce)) {\r
+ ce = new Ext.util.Event(me, ename);\r
+ me.events[ename] = ce;\r
+ }\r
+ ce.bubble = true;\r
+ });\r
+ }\r
}\r
};\r
}());\r
*/
Ext.EventManager = function(){
var docReadyEvent,
- docReadyProcId,
- docReadyState = false,
- E = Ext.lib.Event,
- D = Ext.lib.Dom,
- DOC = document,
- WINDOW = window,
- IEDEFERED = "ie-deferred-loader",
- DOMCONTENTLOADED = "DOMContentLoaded",
- elHash = {},
- propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
+ docReadyProcId,
+ docReadyState = false,
+ E = Ext.lib.Event,
+ D = Ext.lib.Dom,
+ DOC = document,
+ WINDOW = window,
+ IEDEFERED = "ie-deferred-loader",
+ DOMCONTENTLOADED = "DOMContentLoaded",
+ elHash = {},
+ propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
/// There is some jquery work around stuff here that isn't needed in Ext Core.
- function addListener(el, ename, fn, wrap, scope){
+ function addListener(el, ename, fn, wrap, scope){
var id = Ext.id(el),
- es = elHash[id] = elHash[id] || {};
+ es = elHash[id] = elHash[id] || {};
(es[ename] = es[ename] || []).push([fn, wrap, scope]);
E.on(el, ename, wrap);
// this is a workaround for jQuery and should somehow be removed from Ext Core in the future
// without breaking ExtJS.
if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
- var args = ["DOMMouseScroll", wrap, false];
- el.addEventListener.apply(el, args);
+ var args = ["DOMMouseScroll", wrap, false];
+ el.addEventListener.apply(el, args);
E.on(window, 'unload', function(){
- el.removeEventListener.apply(el, args);
+ el.removeEventListener.apply(el, args);
});
}
if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
};
function initDocReady(){
- var COMPLETE = "complete";
-
+ var COMPLETE = "complete";
+
docReadyEvent = new Ext.util.Event();
if (Ext.isGecko || Ext.isOpera) {
DOC.addEventListener(DOMCONTENTLOADED, fireDocReady, false);
function createTargeted(h, o){
return function(){
- var args = Ext.toArray(arguments);
+ var args = Ext.toArray(arguments);
if(o.target == Ext.EventObject.setEvent(args[0]).target){
h.apply(this, args);
}
function listen(element, ename, opt, fn, scope){
var o = !Ext.isObject(opt) ? {} : opt,
- el = Ext.getDom(element);
-
+ el = Ext.getDom(element);
+
fn = fn || o.fn;
scope = scope || o.scope;
};
var pub = {
- /**
- * Appends an event handler to an element. The shorthand version {@link #on} is equivalent. Typically you will
- * use {@link Ext.Element#addListener} directly on an Element in favor of calling this version.
- * @param {String/HTMLElement} el The html element or id to assign the event handler to
- * @param {String} eventName The type of event to listen for
- * @param {Function} handler The handler function the event invokes This function is passed
- * the following parameters:<ul>
- * <li>evt : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
- * <li>t : Element<div class="sub-desc">The {@link Ext.Element Element} which was the target of the event.
- * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
- * <li>o : Object<div class="sub-desc">The options object from the addListener call.</div></li>
- * </ul>
- * @param {Object} scope (optional) The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.
- * @param {Object} options (optional) An object containing handler configuration properties.
- * This may contain any of the following properties:<ul>
- * <li>scope : Object<div class="sub-desc">The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.</div></li>
- * <li>delegate : String<div class="sub-desc">A simple selector to filter the target or look for a descendant of the target</div></li>
- * <li>stopEvent : Boolean<div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>
- * <li>preventDefault : Boolean<div class="sub-desc">True to prevent the default action</div></li>
- * <li>stopPropagation : Boolean<div class="sub-desc">True to prevent event propagation</div></li>
- * <li>normalized : Boolean<div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>
- * <li>delay : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after te event fires.</div></li>
- * <li>single : Boolean<div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
- * <li>buffer : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
- * by the specified number of milliseconds. If the event fires again within that time, the original
- * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
- * <li>target : Element<div class="sub-desc">Only call the handler if the event was fired on the target Element, <i>not</i> if the event was bubbled up from a child node.</div></li>
- * </ul><br>
- * <p>See {@link Ext.Element#addListener} for examples of how to use these options.</p>
- */
- addListener : function(element, eventName, fn, scope, options){
+ /**
+ * Appends an event handler to an element. The shorthand version {@link #on} is equivalent. Typically you will
+ * use {@link Ext.Element#addListener} directly on an Element in favor of calling this version.
+ * @param {String/HTMLElement} el The html element or id to assign the event handler to.
+ * @param {String} eventName The name of the event to listen for.
+ * @param {Function} handler The handler function the event invokes. This function is passed
+ * the following parameters:<ul>
+ * <li>evt : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>
+ * <li>t : Element<div class="sub-desc">The {@link Ext.Element Element} which was the target of the event.
+ * Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>
+ * <li>o : Object<div class="sub-desc">The options object from the addListener call.</div></li>
+ * </ul>
+ * @param {Object} scope (optional) The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.
+ * @param {Object} options (optional) An object containing handler configuration properties.
+ * This may contain any of the following properties:<ul>
+ * <li>scope : Object<div class="sub-desc">The scope (<b><code>this</code></b> reference) in which the handler function is executed. <b>Defaults to the Element</b>.</div></li>
+ * <li>delegate : String<div class="sub-desc">A simple selector to filter the target or look for a descendant of the target</div></li>
+ * <li>stopEvent : Boolean<div class="sub-desc">True to stop the event. That is stop propagation, and prevent the default action.</div></li>
+ * <li>preventDefault : Boolean<div class="sub-desc">True to prevent the default action</div></li>
+ * <li>stopPropagation : Boolean<div class="sub-desc">True to prevent event propagation</div></li>
+ * <li>normalized : Boolean<div class="sub-desc">False to pass a browser event to the handler function instead of an Ext.EventObject</div></li>
+ * <li>delay : Number<div class="sub-desc">The number of milliseconds to delay the invocation of the handler after te event fires.</div></li>
+ * <li>single : Boolean<div class="sub-desc">True to add a handler to handle just the next firing of the event, and then remove itself.</div></li>
+ * <li>buffer : Number<div class="sub-desc">Causes the handler to be scheduled to run in an {@link Ext.util.DelayedTask} delayed
+ * by the specified number of milliseconds. If the event fires again within that time, the original
+ * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</div></li>
+ * <li>target : Element<div class="sub-desc">Only call the handler if the event was fired on the target Element, <i>not</i> if the event was bubbled up from a child node.</div></li>
+ * </ul><br>
+ * <p>See {@link Ext.Element#addListener} for examples of how to use these options.</p>
+ */
+ addListener : function(element, eventName, fn, scope, options){
if(Ext.isObject(eventName)){
- var o = eventName, e, val;
+ var o = eventName, e, val;
for(e in o){
- val = o[e];
- if(!propRe.test(e)){
- if(Ext.isFunction(val)){
- // shared options
- listen(element, e, o, val, o.scope);
- }else{
- // individual options
- listen(element, e, val);
- }
+ val = o[e];
+ if(!propRe.test(e)){
+ if(Ext.isFunction(val)){
+ // shared options
+ listen(element, e, o, val, o.scope);
+ }else{
+ // individual options
+ listen(element, e, val);
+ }
}
}
} else {
- listen(element, eventName, options, fn, scope);
- }
+ listen(element, eventName, options, fn, scope);
+ }
},
/**
* Removes an event handler from an element. The shorthand version {@link #un} is equivalent. Typically
* you will use {@link Ext.Element#removeListener} directly on an Element in favor of calling this version.
- * @param {String/HTMLElement} el The id or html element from which to remove the event
- * @param {String} eventName The type of event
- * @param {Function} fn The handler function to remove
+ * @param {String/HTMLElement} el The id or html element from which to remove the listener.
+ * @param {String} eventName The name of the event.
+ * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>
+ * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
+ * then this must refer to the same object.
*/
removeListener : function(element, eventName, fn, scope){
var el = Ext.getDom(element),
id = Ext.id(el),
- wrap;
-
- Ext.each((elHash[id] || {})[eventName], function (v,i,a) {
- if (Ext.isArray(v) && v[0] == fn && (!scope || v[2] == scope)) {
- E.un(el, eventName, wrap = v[1]);
- a.splice(i,1);
- return false;
- }
- });
+ wrap;
+
+ Ext.each((elHash[id] || {})[eventName], function (v,i,a) {
+ if (Ext.isArray(v) && v[0] == fn && (!scope || v[2] == scope)) {
+ E.un(el, eventName, wrap = v[1]);
+ a.splice(i,1);
+ return false;
+ }
+ });
// jQuery workaround that should be removed from Ext Core
- if(eventName == "mousewheel" && el.addEventListener && wrap){
- el.removeEventListener("DOMMouseScroll", wrap, false);
- }
-
- if(eventName == "mousedown" && el == DOC && wrap){ // fix stopped mousedowns on the document
- Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
- }
+ if(eventName == "mousewheel" && el.addEventListener && wrap){
+ el.removeEventListener("DOMMouseScroll", wrap, false);
+ }
+
+ if(eventName == "mousedown" && el == DOC && wrap){ // fix stopped mousedowns on the document
+ Ext.EventManager.stoppedMouseDownEvent.removeListener(wrap);
+ }
},
/**
* Removes all event handers from an element. Typically you will use {@link Ext.Element#removeAllListeners}
* directly on an Element in favor of calling this version.
- * @param {String/HTMLElement} el The id or html element from which to remove the event
+ * @param {String/HTMLElement} el The id or html element from which to remove all event handlers.
*/
removeAll : function(el){
- var id = Ext.id(el = Ext.getDom(el)),
- es = elHash[id],
- ename;
-
- for(ename in es){
- if(es.hasOwnProperty(ename)){
- Ext.each(es[ename], function(v) {
- E.un(el, ename, v.wrap);
- });
- }
- }
- elHash[id] = null;
+ var id = Ext.id(el = Ext.getDom(el)),
+ es = elHash[id],
+ ename;
+
+ for(ename in es){
+ if(es.hasOwnProperty(ename)){
+ Ext.each(es[ename], function(v) {
+ E.un(el, ename, v.wrap);
+ });
+ }
+ }
+ elHash[id] = null;
},
/**
- * Fires when the document is ready (before onload and before images are loaded). Can be
+ * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Can be
* accessed shorthanded as Ext.onReady().
- * @param {Function} fn The method the event invokes
- * @param {Object} scope (optional) An object that becomes the scope of the handler
- * @param {boolean} options (optional) An object containing standard {@link #addListener} options
+ * @param {Function} fn The method the event invokes.
+ * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
+ * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options
+ * <code>{single: true}</code> be used so that the handler is removed on first invocation.
*/
onDocumentReady : function(fn, scope, options){
if(docReadyState){ // if it already fired
} else {
if(!docReadyEvent) initDocReady();
options = options || {};
- options.delay = options.delay || 1;
- docReadyEvent.addListener(fn, scope, options);
+ options.delay = options.delay || 1;
+ docReadyEvent.addListener(fn, scope, options);
}
},
/**
* Appends an event handler to an element. Shorthand for {@link #addListener}.
* @param {String/HTMLElement} el The html element or id to assign the event handler to
- * @param {String} eventName The type of event to listen for
- * @param {Function} handler The handler function the event invokes
- * @param {Object} scope (optional) The scope in which to execute the handler
- * function (the handler function's "this" context)
+ * @param {String} eventName The name of the event to listen for.
+ * @param {Function} handler The handler function the event invokes.
+ * @param {Object} scope (optional) (<code>this</code> reference) in which the handler function executes. <b>Defaults to the Element</b>.
* @param {Object} options (optional) An object containing standard {@link #addListener} options
* @member Ext.EventManager
* @method on
pub.on = pub.addListener;
/**
* Removes an event handler from an element. Shorthand for {@link #removeListener}.
- * @param {String/HTMLElement} el The id or html element from which to remove the event
- * @param {String} eventName The type of event
- * @param {Function} fn The handler function to remove
- * @return {Boolean} True if a listener was actually removed, else false
+ * @param {String/HTMLElement} el The id or html element from which to remove the listener.
+ * @param {String} eventName The name of the event.
+ * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #on} call.</b>
+ * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,
+ * then this must refer to the same object.
* @member Ext.EventManager
* @method un
*/
return pub;
}();
/**
- * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Ext.EventManager#onDocumentReady}.
- * @param {Function} fn The method the event invokes
- * @param {Object} scope An object that becomes the scope of the handler
- * @param {boolean} options (optional) An object containing standard {@link #addListener} options
+ * Adds a listener to be notified when the document is ready (before onload and before images are loaded). Shorthand of {@link Ext.EventManager#onDocumentReady}.
+ * @param {Function} fn The method the event invokes.
+ * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function executes. Defaults to the browser window.
+ * @param {boolean} options (optional) Options object as passed to {@link Ext.Element#addListener}. It is recommended that the options
+ * <code>{single: true}</code> be used so that the handler is removed on first invocation.
* @member Ext
* @method onReady
*/
*/
Ext.EventObject = function(){
var E = Ext.lib.Event,
- // safari keypress events for special keys return bad keycodes
- safariKeys = {
- 3 : 13, // enter
- 63234 : 37, // left
- 63235 : 39, // right
- 63232 : 38, // up
- 63233 : 40, // down
- 63276 : 33, // page up
- 63277 : 34, // page down
- 63272 : 46, // delete
- 63273 : 36, // home
- 63275 : 35 // end
- },
- // normalize button clicks
- btnMap = Ext.isIE ? {1:0,4:1,2:2} :
+ // safari keypress events for special keys return bad keycodes
+ safariKeys = {
+ 3 : 13, // enter
+ 63234 : 37, // left
+ 63235 : 39, // right
+ 63232 : 38, // up
+ 63233 : 40, // down
+ 63276 : 33, // page up
+ 63277 : 34, // page down
+ 63272 : 46, // delete
+ 63273 : 36, // home
+ 63275 : 35 // end
+ },
+ // normalize button clicks
+ btnMap = Ext.isIE ? {1:0,4:1,2:2} :
(Ext.isWebKit ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
Ext.EventObjectImpl = function(e){
Ext.EventObjectImpl.prototype = {
/** @private */
setEvent : function(e){
- var me = this;
+ var me = this;
if(e == me || (e && e.browserEvent)){ // already wrapped
return e;
}
* Stop the event (preventDefault and stopPropagation)
*/
stopEvent : function(){
- var me = this;
+ var me = this;
if(me.browserEvent){
if(me.browserEvent.type == 'mousedown'){
Ext.EventManager.stoppedMouseDownEvent.fire(me);
* Cancels bubbling of the event.
*/
stopPropagation : function(){
- var me = this;
+ var me = this;
if(me.browserEvent){
if(me.browserEvent.type == 'mousedown'){
Ext.EventManager.stoppedMouseDownEvent.fire(me);
getKey : function(){
return this.normalizeKey(this.keyCode || this.charCode)
},
-
- // private
- normalizeKey: function(k){
- return Ext.isSafari ? (safariKeys[k] || k) : k;
- },
+
+ // private
+ normalizeKey: function(k){
+ return Ext.isSafari ? (safariKeys[k] || k) : k;
+ },
/**
* Gets the x coordinate of the event.
}
return delta;
},
-
- /**
- * Returns true if the target of this event is a child of el. Unless the allowEl parameter is set, it will return false if if the target is el.
- * Example usage:<pre><code>
- // Handle click on any child of an element
- Ext.getBody().on('click', function(e){
- if(e.within('some-el')){
- alert('Clicked on a child of some-el!');
- }
- });
-
- // Handle click directly on an element, ignoring clicks on child nodes
- Ext.getBody().on('click', function(e,t){
- if((t.id == 'some-el') && !e.within(t, true)){
- alert('Clicked directly on some-el!');
- }
- });
- </code></pre>
- * @param {Mixed} el The id, DOM element or Ext.Element to check
- * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
- * @param {Boolean} allowEl {optional} true to also check if the passed element is the target or related target
- * @return {Boolean}
- */
- within : function(el, related, allowEl){
+
+ /**
+ * Returns true if the target of this event is a child of el. Unless the allowEl parameter is set, it will return false if if the target is el.
+ * Example usage:<pre><code>
+ // Handle click on any child of an element
+ Ext.getBody().on('click', function(e){
+ if(e.within('some-el')){
+ alert('Clicked on a child of some-el!');
+ }
+ });
+
+ // Handle click directly on an element, ignoring clicks on child nodes
+ Ext.getBody().on('click', function(e,t){
+ if((t.id == 'some-el') && !e.within(t, true)){
+ alert('Clicked directly on some-el!');
+ }
+ });
+ </code></pre>
+ * @param {Mixed} el The id, DOM element or Ext.Element to check
+ * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
+ * @param {Boolean} allowEl {optional} true to also check if the passed element is the target or related target
+ * @return {Boolean}
+ */
+ within : function(el, related, allowEl){
if(el){
- var t = this[related ? "getRelatedTarget" : "getTarget"]();
- return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
+ var t = this[related ? "getRelatedTarget" : "getTarget"]();
+ return t && ((allowEl ? (t == Ext.getDom(el)) : false) || Ext.fly(el).contains(t));
}
return false;
- }
- };
+ }
+ };
return new Ext.EventObjectImpl();
}();/**\r
// note 1: IE fires ONLY the keydown event on specialkey autorepeat\r
// note 2: Safari < 3.1, Gecko (Mac/Linux) & Opera fire only the keypress event on specialkey autorepeat\r
// (research done by @Jan Wolter at http://unixpapa.com/js/key.html)\r
- useKeydown = Ext.isSafari ? \r
- Ext.num(navigator.userAgent.toLowerCase().match(/version\/(\d+\.\d)/)[1] || 2) >= 3.1 :\r
+ useKeydown = Ext.isWebKit ? \r
+ Ext.num(navigator.userAgent.match(/AppleWebKit\/(\d+)/)[1]) >= 525 :\r
!((Ext.isGecko && !Ext.isWindows) || Ext.isOpera);\r
\r
return { \r
}\r
}\r
if(o.style){\r
- Ext.DomHelper.applyStyles(el, o.style);\r
+ DH.applyStyles(el, o.style);\r
}\r
return this;\r
},\r
* @param {HtmlElement} t The target of the event.\r
* @param {Object} o The options configuration passed to the {@link #addListener} call.\r
*/\r
+ /**\r
+ * @event contextmenu\r
+ * Fires when a right click is detected within the element.\r
+ * @param {Ext.EventObject} e The {@link Ext.EventObject} encapsulating the DOM event.\r
+ * @param {HtmlElement} t The target of the event.\r
+ * @param {Object} o The options configuration passed to the {@link #addListener} call.\r
+ */\r
/**\r
* @event dblclick\r
* Fires when a mouse double click is detected within the element.\r
\r
/**\r
* Appends an event handler to this element. The shorthand version {@link #on} is equivalent.\r
- * @param {String} eventName The type of event to handle\r
+ * @param {String} eventName The name of event to handle.\r
* @param {Function} fn The handler function the event invokes. This function is passed\r
* the following parameters:<ul>\r
* <li><b>evt</b> : EventObject<div class="sub-desc">The {@link Ext.EventObject EventObject} describing the event.</div></li>\r
- * <li><b>el</b> : Element<div class="sub-desc">The {@link Ext.Element Element} which was the target of the event.\r
+ * <li><b>el</b> : HtmlElement<div class="sub-desc">The DOM element which was the target of the event.\r
* Note that this may be filtered by using the <tt>delegate</tt> option.</div></li>\r
* <li><b>o</b> : Object<div class="sub-desc">The options object from the addListener call.</div></li>\r
* </ul>\r
// or\r
el.un('click', this.handlerFn);\r
</code></pre>\r
- * @param {String} eventName the type of event to remove\r
- * @param {Function} fn the method the event invokes\r
- * @param {Object} scope (optional) The scope (The <tt>this</tt> reference) of the handler function. Defaults\r
- * to this Element.\r
+ * @param {String} eventName The name of the event from which to remove the handler.\r
+ * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>\r
+ * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,\r
+ * then this must refer to the same object.\r
* @return {Ext.Element} this\r
*/\r
removeListener : function(eventName, fn, scope){\r
dom = me.dom;\r
\r
me.removeAllListeners();\r
- delete El.cache[dom.id];\r
- delete El.dataCache[dom.id]\r
- Ext.removeNode(dom);\r
+ if (dom) {\r
+ delete me.dom;\r
+ delete El.cache[dom.id];\r
+ delete El.dataCache[dom.id];\r
+ Ext.removeNode(dom);\r
+ }\r
},\r
\r
/**\r
* Sets up event handlers to call the passed functions when the mouse is moved into and out of the Element.\r
* @param {Function} overFn The function to call when the mouse enters the Element.\r
* @param {Function} outFn The function to call when the mouse leaves the Element.\r
- * @param {Object} scope (optional) The scope (<tt>this</tt> reference) in which the functions are executed. Defaults to the Element's DOM element.\r
+ * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the functions are executed. Defaults to the Element's DOM element.\r
* @param {Object} options (optional) Options for the listener. See {@link Ext.util.Observable#addListener the <tt>options</tt> parameter}.\r
* @return {Ext.Element} this\r
*/\r
* @return {Ext.Element} this\r
*/\r
update : function(html) {\r
- this.dom.innerHTML = html;\r
+ if (this.dom) {\r
+ this.dom.innerHTML = html;\r
+ }\r
return this;\r
}\r
};\r
\r
/**\r
* Appends an event handler (shorthand for {@link #addListener}).\r
- * @param {String} eventName The type of event to handle\r
- * @param {Function} fn The handler function the event invokes\r
- * @param {Object} scope (optional) The scope (this element) of the handler function\r
+ * @param {String} eventName The name of event to handle.\r
+ * @param {Function} fn The handler function the event invokes.\r
+ * @param {Object} scope (optional) The scope (<code>this</code> reference) in which the handler function is executed.\r
* @param {Object} options (optional) An object containing standard {@link #addListener} options\r
* @member Ext.Element\r
* @method on\r
\r
/**\r
* Removes an event handler from this element (see {@link #removeListener} for additional notes).\r
- * @param {String} eventName the type of event to remove\r
- * @param {Function} fn the method the event invokes\r
- * @param {Object} scope (optional) The scope (The <tt>this</tt> reference) of the handler function. Defaults\r
- * to this Element.\r
+ * @param {String} eventName The name of the event from which to remove the handler.\r
+ * @param {Function} fn The handler function to remove. <b>This must be a reference to the function passed into the {@link #addListener} call.</b>\r
+ * @param {Object} scope If a scope (<b><code>this</code></b> reference) was specified when the listener was added,\r
+ * then this must refer to the same object.\r
* @return {Ext.Element} this\r
* @member Ext.Element\r
* @method un\r
if(arguments.length == 2){\r
return c[key]; \r
}else{\r
- c[key] = value;\r
+ return (c[key] = value);\r
}\r
};\r
\r
function() {\r
var GETDOM = Ext.getDom,\r
GET = Ext.get,\r
- DH = Ext.DomHelper,\r
- isEl = function(el){\r
- return (el.nodeType || el.dom || typeof el == 'string'); \r
- };\r
+ DH = Ext.DomHelper;\r
\r
return {\r
/**\r
*/\r
insertFirst: function(el, returnDom){\r
el = el || {};\r
- if(isEl(el)){ // element\r
+ if(el.nodeType || el.dom || typeof el == 'string'){ // element\r
el = GETDOM(el);\r
this.dom.insertBefore(el, this.dom.firstChild);\r
return !returnDom ? GET(el) : el;\r
}else{ // dh config\r
return this.createChild(el, this.dom.firstChild, returnDom);\r
}\r
- },\r
+ },\r
\r
/**\r
* Replaces the passed element with this element\r
replaceWith: function(el){\r
var me = this,\r
Element = Ext.Element;\r
- if(isEl(el)){\r
+ if(el.nodeType || el.dom || typeof el == 'string'){\r
el = GETDOM(el);\r
me.dom.parentNode.insertBefore(el, me.dom);\r
}else{\r
return rt;\r
}\r
};\r
-}());/**\r
- * @class Ext.Element\r
- */\r
-Ext.Element.addMethods(function(){ \r
- // local style camelizing for speed\r
- var propCache = {},\r
- camelRe = /(-[a-z])/gi,\r
- classReCache = {},\r
- view = document.defaultView,\r
- propFloat = Ext.isIE ? 'styleFloat' : 'cssFloat',\r
- opacityRe = /alpha\(opacity=(.*)\)/i,\r
- trimRe = /^\s+|\s+$/g,\r
- EL = Ext.Element, \r
- PADDING = "padding",\r
- MARGIN = "margin",\r
- BORDER = "border",\r
- LEFT = "-left",\r
- RIGHT = "-right",\r
- TOP = "-top",\r
- BOTTOM = "-bottom",\r
- WIDTH = "-width", \r
- MATH = Math,\r
- HIDDEN = 'hidden',\r
- ISCLIPPED = 'isClipped',\r
- OVERFLOW = 'overflow',\r
- OVERFLOWX = 'overflow-x',\r
- OVERFLOWY = 'overflow-y',\r
- ORIGINALCLIP = 'originalClip',\r
- // special markup used throughout Ext when box wrapping elements \r
- borders = {l: BORDER + LEFT + WIDTH, r: BORDER + RIGHT + WIDTH, t: BORDER + TOP + WIDTH, b: BORDER + BOTTOM + WIDTH},\r
- paddings = {l: PADDING + LEFT, r: PADDING + RIGHT, t: PADDING + TOP, b: PADDING + BOTTOM},\r
- margins = {l: MARGIN + LEFT, r: MARGIN + RIGHT, t: MARGIN + TOP, b: MARGIN + BOTTOM},\r
- data = Ext.Element.data;\r
- \r
- \r
- // private \r
- function camelFn(m, a) {\r
- return a.charAt(1).toUpperCase();\r
- }\r
- \r
- // private (needs to be called => addStyles.call(this, sides, styles))\r
- function addStyles(sides, styles){\r
- var val = 0; \r
- \r
- Ext.each(sides.match(/\w/g), function(s) {\r
- if (s = parseInt(this.getStyle(styles[s]), 10)) {\r
- val += MATH.abs(s); \r
- }\r
- },\r
- this);\r
- return val;\r
- }\r
-\r
- function chkCache(prop) {\r
- return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : prop.replace(camelRe, camelFn));\r
-\r
- }\r
- \r
- return { \r
- // private ==> used by Fx \r
- adjustWidth : function(width) {\r
- var me = this;\r
- var isNum = (typeof width == "number");\r
- if(isNum && me.autoBoxAdjust && !me.isBorderBox()){\r
- width -= (me.getBorderWidth("lr") + me.getPadding("lr"));\r
- }\r
- return (isNum && width < 0) ? 0 : width;\r
- },\r
- \r
- // private ==> used by Fx \r
- adjustHeight : function(height) {\r
- var me = this;\r
- var isNum = (typeof height == "number");\r
- if(isNum && me.autoBoxAdjust && !me.isBorderBox()){\r
- height -= (me.getBorderWidth("tb") + me.getPadding("tb")); \r
- }\r
- return (isNum && height < 0) ? 0 : height;\r
- },\r
- \r
- \r
- /**\r
- * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.\r
- * @param {String/Array} className The CSS class to add, or an array of classes\r
- * @return {Ext.Element} this\r
- */\r
- addClass : function(className){\r
- var me = this;\r
- Ext.each(className, function(v) {\r
- me.dom.className += (!me.hasClass(v) && v ? " " + v : ""); \r
- });\r
- return me;\r
- },\r
- \r
- /**\r
- * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.\r
- * @param {String/Array} className The CSS class to add, or an array of classes\r
- * @return {Ext.Element} this\r
- */\r
- radioClass : function(className){\r
- Ext.each(this.dom.parentNode.childNodes, function(v) {\r
- if(v.nodeType == 1) {\r
- Ext.fly(v, '_internal').removeClass(className); \r
- }\r
- });\r
- return this.addClass(className);\r
- },\r
- \r
- /**\r
- * Removes one or more CSS classes from the element.\r
- * @param {String/Array} className The CSS class to remove, or an array of classes\r
- * @return {Ext.Element} this\r
- */\r
- removeClass : function(className){\r
- var me = this;\r
- if (me.dom.className) {\r
- Ext.each(className, function(v) { \r
- me.dom.className = me.dom.className.replace(\r
- classReCache[v] = classReCache[v] || new RegExp('(?:^|\\s+)' + v + '(?:\\s+|$)', "g"), \r
- " "); \r
- }); \r
- }\r
- return me;\r
- },\r
- \r
- /**\r
- * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).\r
- * @param {String} className The CSS class to toggle\r
- * @return {Ext.Element} this\r
- */\r
- toggleClass : function(className){\r
- return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);\r
- },\r
- \r
- /**\r
- * Checks if the specified CSS class exists on this element's DOM node.\r
- * @param {String} className The CSS class to check for\r
- * @return {Boolean} True if the class exists, else false\r
- */\r
- hasClass : function(className){\r
- return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;\r
- },\r
- \r
- /**\r
- * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.\r
- * @param {String} oldClassName The CSS class to replace\r
- * @param {String} newClassName The replacement CSS class\r
- * @return {Ext.Element} this\r
- */\r
- replaceClass : function(oldClassName, newClassName){\r
- return this.removeClass(oldClassName).addClass(newClassName);\r
- },\r
- \r
- isStyle : function(style, val) {\r
- return this.getStyle(style) == val; \r
- },\r
- \r
- /**\r
- * Normalizes currentStyle and computedStyle.\r
- * @param {String} property The style property whose value is returned.\r
- * @return {String} The current value of the style property for this element.\r
- */\r
- getStyle : function(){ \r
- return view && view.getComputedStyle ?\r
- function(prop){\r
- var el = this.dom,\r
- v, \r
- cs;\r
- if(el == document) return null;\r
- prop = chkCache(prop);\r
- return (v = el.style[prop]) ? v : \r
- (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;\r
- } :\r
- function(prop){ \r
- var el = this.dom, \r
- m, \r
- cs; \r
- \r
- if(el == document) return null; \r
- if (prop == 'opacity') {\r
- if (el.style.filter.match) { \r
- if(m = el.style.filter.match(opacityRe)){\r
- var fv = parseFloat(m[1]);\r
- if(!isNaN(fv)){\r
- return fv ? fv / 100 : 0;\r
- }\r
- }\r
- }\r
- return 1;\r
- }\r
- prop = chkCache(prop); \r
- return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);\r
- };\r
- }(),\r
- \r
- /**\r
- * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values\r
- * are convert to standard 6 digit hex color.\r
- * @param {String} attr The css attribute\r
- * @param {String} defaultValue The default value to use when a valid color isn't found\r
- * @param {String} prefix (optional) defaults to #. Use an empty string when working with\r
- * color anims.\r
- */\r
- getColor : function(attr, defaultValue, prefix){\r
- var v = this.getStyle(attr),\r
- color = prefix || '#',\r
- h;\r
- \r
- if(!v || /transparent|inherit/.test(v)){\r
- return defaultValue;\r
- }\r
- if(/^r/.test(v)){\r
- Ext.each(v.slice(4, v.length -1).split(','), function(s){\r
- h = parseInt(s, 10);\r
- color += (h < 16 ? '0' : '') + h.toString(16); \r
- });\r
- }else{\r
- v = v.replace('#', '');\r
- color += v.length == 3 ? v.replace(/^(\w)(\w)(\w)$/, '$1$1$2$2$3$3') : v;\r
- }\r
- return(color.length > 5 ? color.toLowerCase() : defaultValue);\r
- },\r
- \r
- /**\r
- * Wrapper for setting style properties, also takes single object parameter of multiple styles.\r
- * @param {String/Object} property The style property to be set, or an object of multiple styles.\r
- * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.\r
- * @return {Ext.Element} this\r
- */\r
- setStyle : function(prop, value){\r
- var tmp, \r
- style,\r
- camel;\r
- if (!Ext.isObject(prop)) {\r
- tmp = {};\r
- tmp[prop] = value; \r
- prop = tmp;\r
- }\r
- for (style in prop) {\r
- value = prop[style]; \r
- style == 'opacity' ? \r
- this.setOpacity(value) : \r
- this.dom.style[chkCache(style)] = value;\r
- }\r
- return this;\r
- },\r
- \r
- /**\r
- * Set the opacity of the element\r
- * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc\r
- * @param {Boolean/Object} animate (optional) a standard Element animation config object or <tt>true</tt> for\r
- * the default animation (<tt>{duration: .35, easing: 'easeIn'}</tt>)\r
- * @return {Ext.Element} this\r
- */\r
- setOpacity : function(opacity, animate){\r
- var me = this,\r
- s = me.dom.style;\r
- \r
- if(!animate || !me.anim){ \r
- if(Ext.isIE){\r
- var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '', \r
- val = s.filter.replace(opacityRe, '').replace(trimRe, '');\r
-\r
- s.zoom = 1;\r
- s.filter = val + (val.length > 0 ? ' ' : '') + opac;\r
- }else{\r
- s.opacity = opacity;\r
- }\r
- }else{\r
- me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');\r
- }\r
- return me;\r
- },\r
- \r
- /**\r
- * Clears any opacity settings from this element. Required in some cases for IE.\r
- * @return {Ext.Element} this\r
- */\r
- clearOpacity : function(){\r
- var style = this.dom.style;\r
- if(Ext.isIE){\r
- if(!Ext.isEmpty(style.filter)){\r
- style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');\r
- }\r
- }else{\r
- style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';\r
- }\r
- return this;\r
- },\r
- \r
- /**\r
- * Returns the offset height of the element\r
- * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding\r
- * @return {Number} The element's height\r
- */\r
- getHeight : function(contentHeight){\r
- var me = this,\r
- dom = me.dom,\r
- h = MATH.max(dom.offsetHeight, dom.clientHeight) || 0;\r
- h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");\r
- return h < 0 ? 0 : h;\r
- },\r
- \r
- /**\r
- * Returns the offset width of the element\r
- * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding\r
- * @return {Number} The element's width\r
- */\r
- getWidth : function(contentWidth){\r
- var me = this,\r
- dom = me.dom,\r
- w = MATH.max(dom.offsetWidth, dom.clientWidth) || 0;\r
- w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");\r
- return w < 0 ? 0 : w;\r
- },\r
- \r
- /**\r
- * Set the width of this Element.\r
- * @param {Mixed} width The new width. This may be one of:<div class="mdetail-params"><ul>\r
- * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).</li>\r
- * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.\r
- * </ul></div>\r
- * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object\r
- * @return {Ext.Element} this\r
- */\r
- setWidth : function(width, animate){\r
- var me = this;\r
- width = me.adjustWidth(width);\r
- !animate || !me.anim ? \r
- me.dom.style.width = me.addUnits(width) :\r
- me.anim({width : {to : width}}, me.preanim(arguments, 1));\r
- return me;\r
- },\r
- \r
- /**\r
- * Set the height of this Element.\r
- * <pre><code>\r
-// change the height to 200px and animate with default configuration\r
-Ext.fly('elementId').setHeight(200, true);\r
-\r
-// change the height to 150px and animate with a custom configuration\r
-Ext.fly('elId').setHeight(150, {\r
- duration : .5, // animation will have a duration of .5 seconds\r
- // will change the content to "finished"\r
- callback: function(){ this.{@link #update}("finished"); } \r
-});\r
- * </code></pre>\r
- * @param {Mixed} height The new height. This may be one of:<div class="mdetail-params"><ul>\r
- * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels.)</li>\r
- * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>\r
- * </ul></div>\r
- * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object\r
- * @return {Ext.Element} this\r
- */\r
- setHeight : function(height, animate){\r
- var me = this;\r
- height = me.adjustHeight(height);\r
- !animate || !me.anim ? \r
- me.dom.style.height = me.addUnits(height) :\r
- me.anim({height : {to : height}}, me.preanim(arguments, 1));\r
- return me;\r
- },\r
- \r
- /**\r
- * Gets the width of the border(s) for the specified side(s)\r
- * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,\r
- * passing <tt>'lr'</tt> would get the border <b><u>l</u></b>eft width + the border <b><u>r</u></b>ight width.\r
- * @return {Number} The width of the sides passed added together\r
- */\r
- getBorderWidth : function(side){\r
- return addStyles.call(this, side, borders);\r
- },\r
- \r
- /**\r
- * Gets the width of the padding(s) for the specified side(s)\r
- * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,\r
- * passing <tt>'lr'</tt> would get the padding <b><u>l</u></b>eft + the padding <b><u>r</u></b>ight.\r
- * @return {Number} The padding of the sides passed added together\r
- */\r
- getPadding : function(side){\r
- return addStyles.call(this, side, paddings);\r
- },\r
- \r
- /**\r
- * Store the current overflow setting and clip overflow on the element - use <tt>{@link #unclip}</tt> to remove\r
- * @return {Ext.Element} this\r
- */\r
- clip : function(){\r
- var me = this,\r
- dom = me.dom;\r
- \r
- if(!data(dom, ISCLIPPED)){\r
- data(dom, ISCLIPPED, true);\r
- data(dom, ORIGINALCLIP, {\r
- o: me.getStyle(OVERFLOW),\r
- x: me.getStyle(OVERFLOWX),\r
- y: me.getStyle(OVERFLOWY)\r
- });\r
- me.setStyle(OVERFLOW, HIDDEN);\r
- me.setStyle(OVERFLOWX, HIDDEN);\r
- me.setStyle(OVERFLOWY, HIDDEN);\r
- }\r
- return me;\r
- },\r
- \r
- /**\r
- * Return clipping (overflow) to original clipping before <tt>{@link #clip}</tt> was called\r
- * @return {Ext.Element} this\r
- */\r
- unclip : function(){\r
- var me = this,\r
- dom = me.dom;\r
- \r
- if(data(dom, ISCLIPPED)){\r
- data(dom, ISCLIPPED, false);\r
- var o = data(dom, ORIGINALCLIP);\r
- if(o.o){\r
- me.setStyle(OVERFLOW, o.o);\r
- }\r
- if(o.x){\r
- me.setStyle(OVERFLOWX, o.x);\r
- }\r
- if(o.y){\r
- me.setStyle(OVERFLOWY, o.y);\r
- }\r
- }\r
- return me;\r
- },\r
- \r
- addStyles : addStyles,\r
- margins : margins\r
- }\r
-}() \r
-);/**\r
+}());/**
+ * @class Ext.Element
+ */
+Ext.Element.addMethods(function(){
+ // local style camelizing for speed
+ var propCache = {},
+ camelRe = /(-[a-z])/gi,
+ classReCache = {},
+ view = document.defaultView,
+ propFloat = Ext.isIE ? 'styleFloat' : 'cssFloat',
+ opacityRe = /alpha\(opacity=(.*)\)/i,
+ trimRe = /^\s+|\s+$/g,
+ EL = Ext.Element,
+ 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',
+ // special markup used throughout Ext when box wrapping elements
+ 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 = Ext.Element.data;
+
+
+ // private
+ function camelFn(m, a) {
+ return a.charAt(1).toUpperCase();
+ }
+
+ function chkCache(prop) {
+ return propCache[prop] || (propCache[prop] = prop == 'float' ? propFloat : prop.replace(camelRe, camelFn));
+ }
+
+ return {
+ // private ==> used by Fx
+ adjustWidth : function(width) {
+ var me = this;
+ var isNum = Ext.isNumber(width);
+ if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
+ width -= (me.getBorderWidth("lr") + me.getPadding("lr"));
+ }
+ return (isNum && width < 0) ? 0 : width;
+ },
+
+ // private ==> used by Fx
+ adjustHeight : function(height) {
+ var me = this;
+ var isNum = Ext.isNumber(height);
+ if(isNum && me.autoBoxAdjust && !me.isBorderBox()){
+ height -= (me.getBorderWidth("tb") + me.getPadding("tb"));
+ }
+ return (isNum && height < 0) ? 0 : height;
+ },
+
+
+ /**
+ * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
+ * @param {String/Array} className The CSS class to add, or an array of classes
+ * @return {Ext.Element} this
+ */
+ addClass : function(className){
+ var me = this;
+ Ext.each(className, function(v) {
+ me.dom.className += (!me.hasClass(v) && v ? " " + v : "");
+ });
+ return me;
+ },
+
+ /**
+ * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
+ * @param {String/Array} className The CSS class to add, or an array of classes
+ * @return {Ext.Element} this
+ */
+ radioClass : function(className){
+ Ext.each(this.dom.parentNode.childNodes, function(v) {
+ if(v.nodeType == 1) {
+ Ext.fly(v, '_internal').removeClass(className);
+ }
+ });
+ return this.addClass(className);
+ },
+
+ /**
+ * Removes one or more CSS classes from the element.
+ * @param {String/Array} className The CSS class to remove, or an array of classes
+ * @return {Ext.Element} this
+ */
+ removeClass : function(className){
+ var me = this;
+ if (me.dom && me.dom.className) {
+ Ext.each(className, function(v) {
+ me.dom.className = me.dom.className.replace(
+ classReCache[v] = classReCache[v] || new RegExp('(?:^|\\s+)' + v + '(?:\\s+|$)', "g"),
+ " ");
+ });
+ }
+ return me;
+ },
+
+ /**
+ * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
+ * @param {String} className The CSS class to toggle
+ * @return {Ext.Element} this
+ */
+ toggleClass : function(className){
+ return this.hasClass(className) ? this.removeClass(className) : this.addClass(className);
+ },
+
+ /**
+ * Checks if the specified CSS class exists on this element's DOM node.
+ * @param {String} className The CSS class to check for
+ * @return {Boolean} True if the class exists, else false
+ */
+ hasClass : function(className){
+ return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
+ },
+
+ /**
+ * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
+ * @param {String} oldClassName The CSS class to replace
+ * @param {String} newClassName The replacement CSS class
+ * @return {Ext.Element} this
+ */
+ replaceClass : function(oldClassName, newClassName){
+ return this.removeClass(oldClassName).addClass(newClassName);
+ },
+
+ isStyle : function(style, val) {
+ return this.getStyle(style) == val;
+ },
+
+ /**
+ * Normalizes currentStyle and computedStyle.
+ * @param {String} property The style property whose value is returned.
+ * @return {String} The current value of the style property for this element.
+ */
+ getStyle : function(){
+ return view && view.getComputedStyle ?
+ function(prop){
+ var el = this.dom,
+ v,
+ cs,
+ out;
+ if(el == document) return null;
+ prop = chkCache(prop);
+ out = (v = el.style[prop]) ? v :
+ (cs = view.getComputedStyle(el, "")) ? cs[prop] : null;
+
+ // Webkit returns rgb values for transparent.
+ if(Ext.isWebKit && out == 'rgba(0, 0, 0, 0)'){
+ out = 'transparent';
+ }
+ return out;
+ } :
+ function(prop){
+ var el = this.dom,
+ m,
+ cs;
+
+ if(el == document) return null;
+ if (prop == 'opacity') {
+ if (el.style.filter.match) {
+ if(m = el.style.filter.match(opacityRe)){
+ var fv = parseFloat(m[1]);
+ if(!isNaN(fv)){
+ return fv ? fv / 100 : 0;
+ }
+ }
+ }
+ return 1;
+ }
+ prop = chkCache(prop);
+ return el.style[prop] || ((cs = el.currentStyle) ? cs[prop] : null);
+ };
+ }(),
+
+ /**
+ * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
+ * are convert to standard 6 digit hex color.
+ * @param {String} attr The css attribute
+ * @param {String} defaultValue The default value to use when a valid color isn't found
+ * @param {String} prefix (optional) defaults to #. Use an empty string when working with
+ * color anims.
+ */
+ getColor : function(attr, defaultValue, prefix){
+ var v = this.getStyle(attr),
+ color = Ext.isDefined(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);
+ },
+
+ /**
+ * Wrapper for setting style properties, also takes single object parameter of multiple styles.
+ * @param {String/Object} property The style property to be set, or an object of multiple styles.
+ * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
+ * @return {Ext.Element} this
+ */
+ setStyle : function(prop, value){
+ var tmp,
+ style,
+ camel;
+ if (!Ext.isObject(prop)) {
+ tmp = {};
+ tmp[prop] = value;
+ prop = tmp;
+ }
+ for (style in prop) {
+ value = prop[style];
+ style == 'opacity' ?
+ this.setOpacity(value) :
+ this.dom.style[chkCache(style)] = value;
+ }
+ return this;
+ },
+
+ /**
+ * Set the opacity of the element
+ * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
+ * @param {Boolean/Object} animate (optional) a standard Element animation config object or <tt>true</tt> for
+ * the default animation (<tt>{duration: .35, easing: 'easeIn'}</tt>)
+ * @return {Ext.Element} this
+ */
+ setOpacity : function(opacity, animate){
+ var me = this,
+ s = me.dom.style;
+
+ if(!animate || !me.anim){
+ if(Ext.isIE){
+ var opac = opacity < 1 ? 'alpha(opacity=' + opacity * 100 + ')' : '',
+ val = s.filter.replace(opacityRe, '').replace(trimRe, '');
+
+ s.zoom = 1;
+ s.filter = val + (val.length > 0 ? ' ' : '') + opac;
+ }else{
+ s.opacity = opacity;
+ }
+ }else{
+ me.anim({opacity: {to: opacity}}, me.preanim(arguments, 1), null, .35, 'easeIn');
+ }
+ return me;
+ },
+
+ /**
+ * Clears any opacity settings from this element. Required in some cases for IE.
+ * @return {Ext.Element} this
+ */
+ clearOpacity : function(){
+ var style = this.dom.style;
+ if(Ext.isIE){
+ if(!Ext.isEmpty(style.filter)){
+ style.filter = style.filter.replace(opacityRe, '').replace(trimRe, '');
+ }
+ }else{
+ style.opacity = style['-moz-opacity'] = style['-khtml-opacity'] = '';
+ }
+ return this;
+ },
+
+ /**
+ * Returns the offset height of the element
+ * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
+ * @return {Number} The element's height
+ */
+ getHeight : function(contentHeight){
+ var me = this,
+ dom = me.dom,
+ hidden = Ext.isIE && me.isStyle('display', 'none'),
+ h = MATH.max(dom.offsetHeight, hidden ? 0 : dom.clientHeight) || 0;
+
+ h = !contentHeight ? h : h - me.getBorderWidth("tb") - me.getPadding("tb");
+ return h < 0 ? 0 : h;
+ },
+
+ /**
+ * Returns the offset width of the element
+ * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
+ * @return {Number} The element's width
+ */
+ getWidth : function(contentWidth){
+ var me = this,
+ dom = me.dom,
+ hidden = Ext.isIE && me.isStyle('display', 'none'),
+ w = MATH.max(dom.offsetWidth, hidden ? 0 : dom.clientWidth) || 0;
+ w = !contentWidth ? w : w - me.getBorderWidth("lr") - me.getPadding("lr");
+ return w < 0 ? 0 : w;
+ },
+
+ /**
+ * Set the width of this Element.
+ * @param {Mixed} width The new width. This may be one of:<div class="mdetail-params"><ul>
+ * <li>A Number specifying the new width in this Element's {@link #defaultUnit}s (by default, pixels).</li>
+ * <li>A String used to set the CSS width style. Animation may <b>not</b> be used.
+ * </ul></div>
+ * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
+ * @return {Ext.Element} this
+ */
+ setWidth : function(width, animate){
+ var me = this;
+ width = me.adjustWidth(width);
+ !animate || !me.anim ?
+ me.dom.style.width = me.addUnits(width) :
+ me.anim({width : {to : width}}, me.preanim(arguments, 1));
+ return me;
+ },
+
+ /**
+ * Set the height of this Element.
+ * <pre><code>
+// change the height to 200px and animate with default configuration
+Ext.fly('elementId').setHeight(200, true);
+
+// change the height to 150px and animate with a custom configuration
+Ext.fly('elId').setHeight(150, {
+ duration : .5, // animation will have a duration of .5 seconds
+ // will change the content to "finished"
+ callback: function(){ this.{@link #update}("finished"); }
+});
+ * </code></pre>
+ * @param {Mixed} height The new height. This may be one of:<div class="mdetail-params"><ul>
+ * <li>A Number specifying the new height in this Element's {@link #defaultUnit}s (by default, pixels.)</li>
+ * <li>A String used to set the CSS height style. Animation may <b>not</b> be used.</li>
+ * </ul></div>
+ * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
+ * @return {Ext.Element} this
+ */
+ setHeight : function(height, animate){
+ var me = this;
+ height = me.adjustHeight(height);
+ !animate || !me.anim ?
+ me.dom.style.height = me.addUnits(height) :
+ me.anim({height : {to : height}}, me.preanim(arguments, 1));
+ return me;
+ },
+
+ /**
+ * Gets the width of the border(s) for the specified side(s)
+ * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
+ * passing <tt>'lr'</tt> would get the border <b><u>l</u></b>eft width + the border <b><u>r</u></b>ight width.
+ * @return {Number} The width of the sides passed added together
+ */
+ getBorderWidth : function(side){
+ return this.addStyles(side, borders);
+ },
+
+ /**
+ * Gets the width of the padding(s) for the specified side(s)
+ * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
+ * passing <tt>'lr'</tt> would get the padding <b><u>l</u></b>eft + the padding <b><u>r</u></b>ight.
+ * @return {Number} The padding of the sides passed added together
+ */
+ getPadding : function(side){
+ return this.addStyles(side, paddings);
+ },
+
+ /**
+ * Store the current overflow setting and clip overflow on the element - use <tt>{@link #unclip}</tt> to remove
+ * @return {Ext.Element} this
+ */
+ 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;
+ },
+
+ /**
+ * Return clipping (overflow) to original clipping before <tt>{@link #clip}</tt> was called
+ * @return {Ext.Element} this
+ */
+ unclip : function(){
+ var me = this,
+ dom = me.dom;
+
+ if(data(dom, ISCLIPPED)){
+ data(dom, ISCLIPPED, false);
+ var o = data(dom, ORIGINALCLIP);
+ if(o.o){
+ me.setStyle(OVERFLOW, o.o);
+ }
+ if(o.x){
+ me.setStyle(OVERFLOWX, o.x);
+ }
+ if(o.y){
+ me.setStyle(OVERFLOWY, o.y);
+ }
+ }
+ return me;
+ },
+
+ // private
+ addStyles : function(sides, styles){
+ var val = 0;
+
+ Ext.each(sides.match(/\w/g), function(s) {
+ if (s = parseInt(this.getStyle(styles[s]), 10)) {
+ val += MATH.abs(s);
+ }
+ },
+ this);
+ return val;
+ },
+
+ margins : margins
+ }
+}()
+);
+/**\r
* @class Ext.Element\r
*/\r
\r
AUTO = "auto",\r
ZINDEX = "z-index";\r
\r
-function animTest(args, animate, i) {\r
- return this.preanim && !!animate ? this.preanim(args, i) : false \r
-}\r
-\r
Ext.Element.addMethods({\r
/**\r
* Gets the current X position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).\r
* @return {Ext.Element} this\r
*/\r
setX : function(x, animate){ \r
- return this.setXY([x, this.getY()], animTest.call(this, arguments, animate, 1));\r
+ return this.setXY([x, this.getY()], this.animTest(arguments, animate, 1));\r
},\r
\r
/**\r
* @return {Ext.Element} this\r
*/\r
setY : function(y, animate){ \r
- return this.setXY([this.getX(), y], animTest.call(this, arguments, animate, 1));\r
+ return this.setXY([this.getX(), y], this.animTest(arguments, animate, 1));\r
},\r
\r
/**\r
* @return {Ext.Element} this\r
*/\r
setLocation : function(x, y, animate){\r
- return this.setXY([x, y], animTest.call(this, arguments, animate, 2));\r
+ return this.setXY([x, y], this.animTest(arguments, animate, 2));\r
},\r
\r
/**\r
* @return {Ext.Element} this\r
*/\r
moveTo : function(x, y, animate){\r
- return this.setXY([x, y], animTest.call(this, arguments, animate, 2)); \r
+ return this.setXY([x, y], this.animTest(arguments, animate, 2)); \r
}, \r
\r
/**\r
return {left: (x - o[0] + l), top: (y - o[1] + t)}; \r
},\r
\r
- animTest : animTest\r
+ animTest : function(args, animate, i) {\r
+ return !!animate && this.preanim ? this.preanim(args, i) : false;\r
+ }\r
});\r
})();/**\r
* @class Ext.Element\r
* @return {Element} this\r
*/\r
scrollTo : function(side, value, animate){\r
- var tester = /top/i,\r
- prop = "scroll" + (tester.test(side) ? "Top" : "Left"),\r
- me = this,\r
- dom = me.dom;\r
+ var top = /top/i.test(side), //check if we're scrolling top or left\r
+ prop = 'scroll' + (top ? 'Left' : 'Top'), // if scrolling top, we need to grab scrollLeft, if left, scrollTop\r
+ me = this,\r
+ dom = me.dom;\r
if (!animate || !me.anim) {\r
dom[prop] = value;\r
} else {\r
- me.anim({scroll: {to: tester.test(prop) ? [dom[prop], value] : [value, dom[prop]]}},\r
- me.preanim(arguments, 2), 'scroll');\r
+ me.anim({scroll: {to: top ? [dom[prop], value] : [value, dom[prop]]}},\r
+ me.preanim(arguments, 2), 'scroll');\r
}\r
return me;\r
},\r
/**\r
* Sets the element's visibility mode. When setVisible() is called it\r
* will use this to determine whether to set the visibility or the display property.\r
- * @param visMode Ext.Element.VISIBILITY or Ext.Element.DISPLAY\r
+ * @param {Number} visMode Ext.Element.VISIBILITY or Ext.Element.DISPLAY\r
* @return {Ext.Element} this\r
*/\r
setVisibilityMode : function(visMode){ \r
shim;\r
el.frameBorder = '0';\r
el.className = 'ext-shim';\r
- if(Ext.isIE && Ext.isSecure){\r
- el.src = Ext.SSL_SECURE_URL;\r
- }\r
+ el.src = Ext.SSL_SECURE_URL;\r
shim = Ext.get(this.dom.parentNode.insertBefore(el, this.dom));\r
shim.autoBoxAdjust = false;\r
return shim;\r
* The callback is intended for any additional code that should run once a particular effect has completed. The Element\r
* being operated upon is passed as the first parameter.\r
* \r
- * @cfg {Object} scope The scope of the <tt>{@link #callback}</tt> function\r
+ * @cfg {Object} scope The scope (<code>this</code> reference) in which the <tt>{@link #callback}</tt> function is executed. Defaults to the browser window.\r
* \r
* @cfg {String} easing A valid Ext.lib.Easing value for the effect:</p><div class="mdetail-params"><ul>\r
* <li><b><tt>backBoth</tt></b></li>\r
active;\r
\r
me.queueFx(o, function(){\r
- color = color || "#C3DAF9"\r
+ color = color || '#C3DAF9'\r
if(color.length == 6){\r
- color = "#" + color;\r
+ color = '#' + color;\r
} \r
count = count || 1;\r
fly(dom).show();\r
queue = function(){\r
proxy = fly(document.body || document.documentElement).createChild({\r
style:{\r
- visbility: HIDDEN,\r
position : ABSOLUTE,\r
- "z-index": 35000, // yee haw\r
- border : "0px solid " + color\r
+ 'z-index': 35000, // yee haw\r
+ border : '0px solid ' + color\r
}\r
});\r
return proxy.queueFx({}, animFn);\r
\r
/* @private */\r
queueFx : function(o, fn){\r
- var me = this;\r
+ var me = fly(this.dom);\r
if(!me.hasFxBlock()){\r
Ext.applyIf(o, me.fxDefaults);\r
if(!o.concurrent){\r
fly(dom).clearPositioning();\r
fly(dom).setPositioning(pos);\r
if(!o.wrap){\r
- wrap.parentNode.insertBefore(dom, wrap);\r
+ var pn = fly(wrap).dom.parentNode;
+ pn.insertBefore(dom, wrap); \r
fly(wrap).remove();\r
}\r
},\r
/* @private */\r
afterFx : function(o){\r
var dom = this.dom,\r
- id = dom.id,\r
- notConcurrent = !o.concurrent;\r
+ id = dom.id;\r
if(o.afterStyle){\r
fly(dom).setStyle(o.afterStyle); \r
}\r
if(o.remove == TRUE){\r
fly(dom).remove();\r
}\r
- if(notConcurrent){\r
- getQueue(id).shift();\r
- }\r
if(o.callback){\r
o.callback.call(o.scope, fly(dom));\r
}\r
- if(notConcurrent){\r
+ if(!o.concurrent){\r
+ getQueue(id).shift();\r
fly(dom).nextFx();\r
}\r
},\r
//When included, Ext.Fx is automatically applied to Element so that all basic\r
//effects are available directly via the Element API\r
Ext.Element.addMethods(Ext.Fx);\r
-})();/**\r
+})();
+/**\r
* @class Ext.CompositeElementLite\r
- * Flyweight composite class. Reuses the same Ext.Element for element operations.\r
- <pre><code>\r
- var els = Ext.select("#some-el div.some-class");\r
- // or select directly from an existing element\r
- var el = Ext.get('some-el');\r
- el.select('div.some-class');\r
-\r
- els.setWidth(100); // all elements become 100 width\r
- els.hide(true); // all elements fade out and hide\r
- // or\r
- els.setWidth(100).hide(true);\r
- </code></pre><br><br>\r
- * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Ext.Element. All Ext.Element\r
- * actions will be performed on all the elements in this collection.</b>\r
+ * <p>This class encapsulates a <i>collection</i> of DOM elements, providing methods to filter\r
+ * members, or to perform collective actions upon the whole set.</p>\r
+ * <p>Although they are not listed, this class supports all of the methods of {@link Ext.Element} and\r
+ * {@link Ext.Fx}. The methods from these classes will be performed on all the elements in this collection.</p>\r
+ * Example:<pre><code>\r
+var els = Ext.select("#some-el div.some-class");\r
+// or select directly from an existing element\r
+var el = Ext.get('some-el');\r
+el.select('div.some-class');\r
+\r
+els.setWidth(100); // all elements become 100 width\r
+els.hide(true); // all elements fade out and hide\r
+// or\r
+els.setWidth(100).hide(true);\r
+</code>\r
*/\r
Ext.CompositeElementLite = function(els, root){\r
+ /**\r
+ * <p>The Array of DOM elements which this CompositeElement encapsulates. Read-only.</p>\r
+ * <p>This will not <i>usually</i> be accessed in developers' code, but developers wishing\r
+ * to augment the capabilities of the CompositeElementLite class may use it when adding\r
+ * methods to the class.</p>\r
+ * <p>For example to add the <code>nextAll</code> method to the class to <b>add</b> all\r
+ * following siblings of selected elements, the code would be</p><code><pre>\r
+Ext.override(Ext.CompositeElementLite, {\r
+ nextAll: function() {\r
+ var els = this.elements, i, l = els.length, n, r = [], ri = -1;\r
+\r
+// Loop through all elements in this Composite, accumulating\r
+// an Array of all siblings.\r
+ for (i = 0; i < l; i++) {\r
+ for (n = els[i].nextSibling; n; n = n.nextSibling) {\r
+ r[++ri] = n;\r
+ }\r
+ }\r
+\r
+// Add all found siblings to this Composite\r
+ return this.add(r);\r
+ }\r
+});</pre></code>\r
+ * @type Array\r
+ * @property elements\r
+ */\r
this.elements = [];\r
this.add(els, root);\r
this.el = new Ext.Element.Flyweight();\r
};\r
\r
Ext.CompositeElementLite.prototype = {\r
- isComposite: true, \r
- /**\r
- * Returns the number of elements in this composite\r
+ isComposite: true, \r
+ /**\r
+ * Returns the number of elements in this Composite.\r
* @return Number\r
*/\r
getCount : function(){\r
return this.elements.length;\r
}, \r
- add : function(els){\r
+ /**\r
+ * Adds elements to this Composite object.\r
+ * @param {Mixed} els Either an Array of DOM elements to add, or another Composite object who's elements should be added.\r
+ * @return {CompositeElement} This Composite object.\r
+ */\r
+ add : function(els){\r
if(els){\r
if (Ext.isArray(els)) {\r
this.elements = this.elements.concat(els);\r
} else {\r
- var yels = this.elements; \r
- Ext.each(els, function(e) {\r
+ var yels = this.elements; \r
+ Ext.each(els, function(e) {\r
yels.push(e);\r
});\r
}\r
},\r
invoke : function(fn, args){\r
var els = this.elements,\r
- el = this.el; \r
- Ext.each(els, function(e) { \r
+ el = this.el; \r
+ Ext.each(els, function(e) { \r
el.dom = e;\r
- Ext.Element.prototype[fn].apply(el, args);\r
+ Ext.Element.prototype[fn].apply(el, args);\r
});\r
return this;\r
},\r
* @return {Ext.Element}\r
*/\r
item : function(index){\r
- var me = this;\r
+ var me = this;\r
if(!me.elements[index]){\r
return null;\r
}\r
// fixes scope with flyweight\r
addListener : function(eventName, handler, scope, opt){\r
Ext.each(this.elements, function(e) {\r
- Ext.EventManager.on(e, eventName, handler, scope || e, opt);\r
+ Ext.EventManager.on(e, eventName, handler, scope || e, opt);\r
});\r
return this;\r
},\r
/**\r
- * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element\r
- * passed is the flyweight (shared) Ext.Element instance, so if you require a\r
- * a reference to the dom node, use el.dom.</b>\r
- * @param {Function} fn The function to call\r
- * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)\r
- * @return {CompositeElement} this\r
- */\r
+ * <p>Calls the passed function for each element in this composite.</p>\r
+ * @param {Function} fn The function to call. The function is passed the following parameters:<ul>\r
+ * <li><b>el</b> : Element<div class="sub-desc">The current Element in the iteration.\r
+ * <b>This is the flyweight (shared) Ext.Element instance, so if you require a\r
+ * a reference to the dom node, use el.dom.</b></div></li>\r
+ * <li><b>c</b> : Composite<div class="sub-desc">This Composite object.</div></li>\r
+ * <li><b>idx</b> : Number<div class="sub-desc">The zero-based index in the iteration.</div></li>\r
+ * </ul>\r
+ * @param {Object} scope (optional) The scope (<i>this</i> reference) in which the function is executed. (defaults to the Element)\r
+ * @return {CompositeElement} this\r
+ */\r
each : function(fn, scope){ \r
var me = this,\r
- el = me.el;\r
+ el = me.el;\r
\r
- Ext.each(me.elements, function(e,i) { \r
+ Ext.each(me.elements, function(e,i) { \r
el.dom = e;\r
- return fn.call(scope || el, el, me, i);\r
+ return fn.call(scope || el, el, me, i);\r
+ });\r
+ return me;\r
+ },\r
+ \r
+ /**\r
+ * Clears this Composite and adds the elements passed.\r
+ * @param {Mixed} els Either an array of DOM elements, or another Composite from which to fill this Composite.\r
+ * @return {CompositeElement} this\r
+ */\r
+ fill : function(els){\r
+ var me = this;\r
+ me.elements = [];\r
+ me.add(els);\r
+ return me;\r
+ },\r
+ \r
+ /**\r
+ * Filters this composite to only elements that match the passed selector.\r
+ * @param {String/Function} selector A string CSS selector or a comparison function.\r
+ * The comparison function will be called with the following arguments:<ul>\r
+ * <li><code>el</code> : Ext.Element<div class="sub-desc">The current DOM element.</div></li>\r
+ * <li><code>index</code> : Number<div class="sub-desc">The current index within the collection.</div></li>\r
+ * </ul>\r
+ * @return {CompositeElement} this\r
+ */\r
+ filter : function(selector){\r
+ var els = [],\r
+ me = this,\r
+ fn = Ext.isFunction(selector) ? selector\r
+ : function(el){\r
+ return el.is(selector);\r
+ }\r
+ me.each(function(el, self, i){\r
+ if(fn(el, i) !== false){\r
+ els[els.length] = el.dom;\r
+ }\r
});\r
+ me.fill(els);\r
return me;\r
},\r
\r
*/ \r
replaceElement : function(el, replacement, domReplace){\r
var index = !isNaN(el) ? el : this.indexOf(el),\r
- d;\r
+ d;\r
if(index > -1){\r
replacement = Ext.getDom(replacement);\r
if(domReplace){\r
\r
(function(){\r
var fnName,\r
- ElProto = Ext.Element.prototype,\r
- CelProto = Ext.CompositeElementLite.prototype;\r
- \r
+ ElProto = Ext.Element.prototype,\r
+ CelProto = Ext.CompositeElementLite.prototype;\r
+ \r
for(fnName in ElProto){\r
if(Ext.isFunction(ElProto[fnName])){\r
- (function(fnName){ \r
- CelProto[fnName] = CelProto[fnName] || function(){\r
- return this.invoke(fnName, arguments);\r
- };\r
- }).call(CelProto, fnName);\r
+ (function(fnName){ \r
+ CelProto[fnName] = CelProto[fnName] || function(){\r
+ return this.invoke(fnName, arguments);\r
+ };\r
+ }).call(CelProto, fnName);\r
\r
}\r
}\r
return this;\r
},\r
\r
- /**\r
- * Clears this composite and adds the elements returned by the passed selector.\r
- * @param {String/Array} els A string CSS selector, an array of elements or an element\r
- * @return {CompositeElement} this\r
- */\r
- fill : function(els){\r
- this.elements = [];\r
- this.add(els);\r
- return this;\r
- },\r
- \r
/**\r
* Returns the first Element\r
* @return {Ext.Element}\r
*/\r
contains : function(el){\r
return this.indexOf(el) != -1;\r
- },\r
-\r
- /**\r
- * Filters this composite to only elements that match the passed selector.\r
- * @param {String} selector A string CSS selector\r
- * @return {CompositeElement} this\r
- */\r
- filter : function(selector){\r
- var els = [];\r
- this.each(function(el){\r
- if(el.is(selector)){\r
- els[els.length] = el.dom;\r
- }\r
- });\r
- this.fill(els);\r
- return this;\r
},
/**\r
});\r
return this;\r
},\r
- \r
+\r
/**\r
* Adds elements to this composite.\r
* @param {String/Array} els A string CSS selector, an array of elements or an element\r
if(typeof els == "string"){\r
els = Ext.Element.selectorFunction(els, root);\r
}\r
- var yels = this.elements; \r
+ var yels = this.elements;\r
Ext.each(els, function(e) {\r
yels.push(Ext.get(e));\r
});\r
return this;\r
- }, \r
- \r
+ },\r
+\r
/**\r
* Returns the Element object at the specified index\r
* @param {Number} index\r
indexOf : function(el){\r
return this.elements.indexOf(Ext.get(el));\r
},\r
- \r
+\r
filter : function(selector){\r
var me = this,\r
out = [];\r
- \r
- Ext.each(me.elements, function(el) { \r
+\r
+ Ext.each(me.elements, function(el) {\r
if(el.is(selector)){\r
out.push(Ext.get(el));\r
}\r
me.elements = out;\r
return me;\r
},\r
- \r
- /**\r
- * Calls the passed function passing (el, this, index) for each element in this composite.\r
- * @param {Function} fn The function to call\r
- * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)\r
- * @return {CompositeElement} this\r
- */\r
- each : function(fn, scope){ \r
- Ext.each(this.elements, function(e,i) {\r
- return fn.call(scope || e, e, this, i);\r
+\r
+ /**\r
+ * Iterates each <code>element</code> in this <code>composite</code>\r
+ * calling the supplied function using {@link Ext#each}.\r
+ * @param {Function} fn The function to be called with each\r
+ * <code>element</code>. If the supplied function returns <tt>false</tt>,\r
+ * iteration stops. This function is called with the following arguments:\r
+ * <div class="mdetail-params"><ul>\r
+ * <li><code>element</code> : <i>Object</i>\r
+ * <div class="sub-desc">The element at the current <code>index</code>\r
+ * in the <code>composite</code></div></li>\r
+ * <li><code>composite</code> : <i>Object</i>\r
+ * <div class="sub-desc">This composite.</div></li>\r
+ * <li><code>index</code> : <i>Number</i>\r
+ * <div class="sub-desc">The current index within the <code>composite</code>\r
+ * </div></li>\r
+ * </ul></div>\r
+ * @param {Object} scope (optional) The scope to call the specified function.\r
+ * Defaults to the <code>element</code> at the current <code>index</code>\r
+ * within the composite.\r
+ * @return {CompositeElement} this\r
+ */\r
+ each : function(fn, scope){\r
+ Ext.each(this.elements, function(e, i){\r
+ return fn.call(scope || e, e, this, i);\r
}, this);\r
return this;\r
}\r
}\r
\r
return (unique === true) ? new Ext.CompositeElement(els) : new Ext.CompositeElementLite(els);\r
-};
+};\r
\r
/**\r
* Selects elements based on the passed CSS selector to enable {@link Ext.Element Element} methods\r
* @param {Object} options The options config object passed to the {@link #request} method.\r
*/\r
BEFOREREQUEST,\r
- /**\r
- * @event requestcomplete\r
- * Fires if the request was successfully completed.\r
- * @param {Connection} conn This Connection object.\r
- * @param {Object} response The XHR object containing the response data.\r
- * See <a href="http://www.w3.org/TR/XMLHttpRequest/">The XMLHttpRequest Object</a>\r
- * for details.\r
- * @param {Object} options The options config object passed to the {@link #request} method.\r
- */\r
- REQUESTCOMPLETE,\r
- /**\r
- * @event requestexception\r
- * Fires if an error HTTP status was returned from the server.\r
- * See <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP Status Code Definitions</a>\r
- * for details of HTTP status codes.\r
- * @param {Connection} conn This Connection object.\r
- * @param {Object} response The XHR object containing the response data.\r
- * See <a href="http://www.w3.org/TR/XMLHttpRequest/">The XMLHttpRequest Object</a>\r
- * for details.\r
- * @param {Object} options The options config object passed to the {@link #request} method.\r
- */\r
- REQUESTEXCEPTION\r
- );\r
- Ext.data.Connection.superclass.constructor.call(this);\r
- };\r
-\r
- // private\r
- function handleResponse(response){\r
- this.transId = false;\r
- var options = response.argument.options;\r
- response.argument = options ? options.argument : null;\r
- this.fireEvent(REQUESTCOMPLETE, this, response, options);\r
- if(options.success){\r
- options.success.call(options.scope, response, options);\r
- }\r
- if(options.callback){\r
- options.callback.call(options.scope, options, true, response);\r
- }\r
- }\r
-\r
- // private\r
- function handleFailure(response, e){\r
- this.transId = false;\r
- var options = response.argument.options;\r
- response.argument = options ? options.argument : null;\r
- this.fireEvent(REQUESTEXCEPTION, this, response, options, e);\r
- if(options.failure){\r
- options.failure.call(options.scope, response, options);\r
- }\r
- if(options.callback){\r
- options.callback.call(options.scope, options, false, response);\r
- }\r
- }\r
-\r
- // private\r
- function doFormUpload(o, ps, url){\r
- var id = Ext.id(),\r
- doc = document,\r
- frame = doc.createElement('iframe'),\r
- form = Ext.getDom(o.form),\r
- hiddens = [],\r
- hd,\r
- encoding = 'multipart/form-data',\r
- buf = {\r
- target: form.target,\r
- method: form.method,\r
- encoding: form.encoding,\r
- enctype: form.enctype,\r
- action: form.action\r
- };\r
- \r
- Ext.apply(frame, {\r
- id: id,\r
- name: id,\r
- className: 'x-hidden',\r
- src: Ext.SSL_SECURE_URL // for IE\r
- }); \r
- doc.body.appendChild(frame);\r
- \r
- // This is required so that IE doesn't pop the response up in a new window.\r
- if(Ext.isIE){\r
- document.frames[id].name = id;\r
- }\r
- \r
- Ext.apply(form, {\r
- target: id,\r
- method: POST,\r
- enctype: encoding,\r
- encoding: encoding,\r
- action: url || buf.action\r
- });\r
- \r
- // add dynamic params \r
- ps = Ext.urlDecode(ps, false);\r
- for(var k in ps){\r
- if(ps.hasOwnProperty(k)){\r
- hd = doc.createElement('input');\r
- hd.type = 'hidden'; \r
- hd.value = ps[hd.name = k];\r
- form.appendChild(hd);\r
- hiddens.push(hd);\r
- }\r
- } \r
-\r
- function cb(){\r
- var me = this,\r
- // bogus response object\r
- r = {responseText : '',\r
- responseXML : null,\r
- argument : o.argument},\r
- doc,\r
- firstChild;\r
-\r
- try{ \r
- doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;\r
- if(doc){\r
- if(doc.body){\r
- if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ // json response wrapped in textarea \r
- r.responseText = firstChild.value;\r
- }else{\r
- r.responseText = doc.body.innerHTML;\r
- }\r
- }\r
- //in IE the document may still have a body even if returns XML.\r
- r.responseXML = doc.XMLDocument || doc;\r
- }\r
- }\r
- catch(e) {}\r
-\r
- Ext.EventManager.removeListener(frame, LOAD, cb, me);\r
-\r
- me.fireEvent(REQUESTCOMPLETE, me, r, o);\r
- \r
- function runCallback(fn, scope, args){\r
- if(Ext.isFunction(fn)){\r
- fn.apply(scope, args);\r
- }\r
- }\r
-\r
- runCallback(o.success, o.scope, [r, o]);\r
- runCallback(o.callback, o.scope, [o, true, r]);\r
-\r
- if(!me.debugUploads){\r
- setTimeout(function(){Ext.removeNode(frame);}, 100);\r
- }\r
- }\r
-\r
- Ext.EventManager.on(frame, LOAD, cb, this);\r
- form.submit();\r
- \r
- Ext.apply(form, buf);\r
- Ext.each(hiddens, function(h) {\r
- Ext.removeNode(h);\r
- });\r
- }\r
+ /**\r
+ * @event requestcomplete\r
+ * Fires if the request was successfully completed.\r
+ * @param {Connection} conn This Connection object.\r
+ * @param {Object} response The XHR object containing the response data.\r
+ * See <a href="http://www.w3.org/TR/XMLHttpRequest/">The XMLHttpRequest Object</a>\r
+ * for details.\r
+ * @param {Object} options The options config object passed to the {@link #request} method.\r
+ */\r
+ REQUESTCOMPLETE,\r
+ /**\r
+ * @event requestexception\r
+ * Fires if an error HTTP status was returned from the server.\r
+ * See <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html">HTTP Status Code Definitions</a>\r
+ * for details of HTTP status codes.\r
+ * @param {Connection} conn This Connection object.\r
+ * @param {Object} response The XHR object containing the response data.\r
+ * See <a href="http://www.w3.org/TR/XMLHttpRequest/">The XMLHttpRequest Object</a>\r
+ * for details.\r
+ * @param {Object} options The options config object passed to the {@link #request} method.\r
+ */\r
+ REQUESTEXCEPTION\r
+ );\r
+ Ext.data.Connection.superclass.constructor.call(this);\r
+ };\r
\r
Ext.extend(Ext.data.Connection, Ext.util.Observable, {\r
/**\r
var p = o.params,\r
url = o.url || me.url, \r
method,\r
- cb = {success: handleResponse,\r
- failure: handleFailure,\r
+ cb = {success: me.handleResponse,\r
+ failure: me.handleFailure,\r
scope: me,\r
argument: {options: o},\r
timeout : o.timeout || me.timeout\r
if((form = Ext.getDom(o.form))){\r
url = url || form.action;\r
if(o.isUpload || /multipart\/form-data/i.test(form.getAttribute("enctype"))) { \r
- return doFormUpload.call(me, o, p, url);\r
+ return me.doFormUpload.call(me, o, p, url);\r
}\r
serForm = Ext.lib.Ajax.serializeForm(form); \r
p = p ? (p + '&' + serForm) : serForm;\r
if(transId || this.isLoading()){\r
Ext.lib.Ajax.abort(transId || this.transId);\r
}\r
+ },\r
+\r
+ // private\r
+ handleResponse : function(response){\r
+ this.transId = false;\r
+ var options = response.argument.options;\r
+ response.argument = options ? options.argument : null;\r
+ this.fireEvent(REQUESTCOMPLETE, this, response, options);\r
+ if(options.success){\r
+ options.success.call(options.scope, response, options);\r
+ }\r
+ if(options.callback){\r
+ options.callback.call(options.scope, options, true, response);\r
+ }\r
+ },\r
+\r
+ // private\r
+ handleFailure : function(response, e){\r
+ this.transId = false;\r
+ var options = response.argument.options;\r
+ response.argument = options ? options.argument : null;\r
+ this.fireEvent(REQUESTEXCEPTION, this, response, options, e);\r
+ if(options.failure){\r
+ options.failure.call(options.scope, response, options);\r
+ }\r
+ if(options.callback){\r
+ options.callback.call(options.scope, options, false, response);\r
+ }\r
+ },\r
+\r
+ // private\r
+ doFormUpload : function(o, ps, url){\r
+ var id = Ext.id(),\r
+ doc = document,\r
+ frame = doc.createElement('iframe'),\r
+ form = Ext.getDom(o.form),\r
+ hiddens = [],\r
+ hd,\r
+ encoding = 'multipart/form-data',\r
+ buf = {\r
+ target: form.target,\r
+ method: form.method,\r
+ encoding: form.encoding,\r
+ enctype: form.enctype,\r
+ action: form.action\r
+ };\r
+\r
+ Ext.fly(frame).set({\r
+ id: id,\r
+ name: id,\r
+ cls: 'x-hidden',\r
+ src: Ext.SSL_SECURE_URL // for IE\r
+ });\r
+ doc.body.appendChild(frame);\r
+\r
+ // This is required so that IE doesn't pop the response up in a new window.\r
+ if(Ext.isIE){\r
+ document.frames[id].name = id;\r
+ }\r
+\r
+ Ext.fly(form).set({\r
+ target: id,\r
+ method: POST,\r
+ enctype: encoding,\r
+ encoding: encoding,\r
+ action: url || buf.action\r
+ });\r
+\r
+ // add dynamic params\r
+ Ext.iterate(Ext.urlDecode(ps, false), function(k, v){\r
+ hd = doc.createElement('input');\r
+ Ext.fly(hd).set({\r
+ type: 'hidden',\r
+ value: v,\r
+ name: k\r
+ });\r
+ form.appendChild(hd);\r
+ hiddens.push(hd);\r
+ });\r
+\r
+ function cb(){\r
+ var me = this,\r
+ // bogus response object\r
+ r = {responseText : '',\r
+ responseXML : null,\r
+ argument : o.argument},\r
+ doc,\r
+ firstChild;\r
+\r
+ try{\r
+ doc = frame.contentWindow.document || frame.contentDocument || WINDOW.frames[id].document;\r
+ if(doc){\r
+ if(doc.body){\r
+ if(/textarea/i.test((firstChild = doc.body.firstChild || {}).tagName)){ // json response wrapped in textarea\r
+ r.responseText = firstChild.value;\r
+ }else{\r
+ r.responseText = doc.body.innerHTML;\r
+ }\r
+ }\r
+ //in IE the document may still have a body even if returns XML.\r
+ r.responseXML = doc.XMLDocument || doc;\r
+ }\r
+ }\r
+ catch(e) {}\r
+\r
+ Ext.EventManager.removeListener(frame, LOAD, cb, me);\r
+\r
+ me.fireEvent(REQUESTCOMPLETE, me, r, o);\r
+\r
+ function runCallback(fn, scope, args){\r
+ if(Ext.isFunction(fn)){\r
+ fn.apply(scope, args);\r
+ }\r
+ }\r
+\r
+ runCallback(o.success, o.scope, [r, o]);\r
+ runCallback(o.callback, o.scope, [o, true, r]);\r
+\r
+ if(!me.debugUploads){\r
+ setTimeout(function(){Ext.removeNode(frame);}, 100);\r
+ }\r
+ }\r
+\r
+ Ext.EventManager.on(frame, LOAD, cb, this);\r
+ form.submit();\r
+\r
+ Ext.fly(form).set(buf);\r
+ Ext.each(hiddens, function(h) {\r
+ Ext.removeNode(h);\r
+ });\r
}\r
});\r
})();\r
* Blank page URL to use with SSL file uploads (defaults to {@link Ext#SSL_SECURE_URL} if set, or "javascript:false").
* @type String
*/
- sslBlankUrl : (Ext.SSL_SECURE_URL || "javascript:false")
+ sslBlankUrl : Ext.SSL_SECURE_URL
};
a: {
g:1,
c:"if (results[{0}] == 'am') {\n"
- + "if (h == 12) { h = 0; }\n"
- + "} else { if (h < 12) { h += 12; }}",
+ + "if (!h || h == 12) { h = 0; }\n"
+ + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
s:"(am|pm)"
},
A: {
g:1,
c:"if (results[{0}] == 'AM') {\n"
- + "if (h == 12) { h = 0; }\n"
- + "} else { if (h < 12) { h += 12; }}",
+ + "if (!h || h == 12) { h = 0; }\n"
+ + "} else { if (!h || h < 12) { h = (h || 0) + 12; }}",
s:"(AM|PM)"
},
g: function() {
* @return {Number} 0 to 364 (365 in leap years).
*/
getDayOfYear: function() {
- var i = 0,
- num = 0,
+ var num = 0,
d = this.clone(),
- m = this.getMonth();
+ m = this.getMonth(),
+ i;
- for (i = 0, d.setMonth(0); i < m; d.setMonth(++i)) {
+ for (i = 0, d.setDate(1), d.setMonth(0); i < m; d.setMonth(++i)) {
num += d.getDaysInMonth();
}
return num + this.getDate() - 1;
* option <tt>buffer</tt> for {@link Ext.util.Observable#addListener addListener/on} will
* also setup a delayed task for you to buffer events.</p>
* @constructor The parameters to this constructor serve as defaults and are not required.
- * @param {Function} fn (optional) The default function to timeout
- * @param {Object} scope (optional) The default scope of that timeout
- * @param {Array} args (optional) The default Array of arguments
+ * @param {Function} fn (optional) The default function to call.
+ * @param {Object} scope The default scope (The <code><b>this</b></code> reference) in which the
+ * function is called. If not specified, <code>this</code> will refer to the browser window.
+ * @param {Array} args (optional) The default Array of arguments.
*/
Ext.util.DelayedTask = function(fn, scope, args){
var me = this,
* Cancels any pending timeout and queues a new one
* @param {Number} delay The milliseconds to delay
* @param {Function} newFn (optional) Overrides function passed to constructor
- * @param {Object} newScope (optional) Overrides scope passed to constructor
+ * @param {Object} newScope (optional) Overrides scope passed to constructor. Remember that if no scope
+ * is specified, <code>this</code> will refer to the browser window.
* @param {Array} newArgs (optional) Overrides args passed to constructor
*/
me.delay = function(delay, newFn, newScope, newArgs){
* @extends Ext.util.Observable\r
* A Collection class that maintains both numeric indexes and keys and exposes events.\r
* @constructor\r
- * @param {Boolean} allowFunctions True if the addAll function should add function references to the\r
- * collection (defaults to false)\r
+ * @param {Boolean} allowFunctions Specify <tt>true</tt> if the {@link #addAll}\r
+ * function should add function references to the collection. Defaults to\r
+ * <tt>false</tt>.\r
* @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection\r
* and return the key value for that item. This is used when available to look up the key on items that\r
* were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is\r
* @event clear\r
* Fires when the collection is cleared.\r
*/\r
- "clear",\r
+ 'clear',\r
/**\r
* @event add\r
* Fires when an item is added to the collection.\r
* @param {Object} o The item added.\r
* @param {String} key The key associated with the added item.\r
*/\r
- "add",\r
+ 'add',\r
/**\r
* @event replace\r
* Fires when an item is replaced in the collection.\r
* @param {Object} old The item being replaced.\r
* @param {Object} new The new item.\r
*/\r
- "replace",\r
+ 'replace',\r
/**\r
* @event remove\r
* Fires when an item is removed from the collection.\r
* @param {Object} o The item being removed.\r
* @param {String} key (optional) The key associated with the removed item.\r
*/\r
- "remove",\r
- "sort"\r
+ 'remove',\r
+ 'sort'\r
);\r
this.allowFunctions = allowFunctions === true;\r
if(keyFn){\r
};\r
\r
Ext.extend(Ext.util.MixedCollection, Ext.util.Observable, {\r
+\r
+ /**\r
+ * @cfg {Boolean} allowFunctions Specify <tt>true</tt> if the {@link #addAll}\r
+ * function should add function references to the collection. Defaults to\r
+ * <tt>false</tt>.\r
+ */\r
allowFunctions : false,\r
\r
-/**\r
- * Adds an item to the collection. Fires the {@link #add} event when complete.\r
- * @param {String} key <p>The key to associate with the item, or the new item.</p>\r
- * <p>If you supplied a {@link #getKey} implementation for this MixedCollection, or if the key\r
- * of your stored items is in a property called <tt><b>id</b></tt>, then the MixedCollection\r
- * will be able to <i>derive</i> the key for the new item. In this case just pass the new item in\r
- * this parameter.</p>\r
- * @param {Object} o The item to add.\r
- * @return {Object} The item added.\r
- */\r
- add: function(key, o){\r
+ /**\r
+ * Adds an item to the collection. Fires the {@link #add} event when complete.\r
+ * @param {String} key <p>The key to associate with the item, or the new item.</p>\r
+ * <p>If a {@link #getKey} implementation was specified for this MixedCollection,\r
+ * or if the key of the stored items is in a property called <tt><b>id</b></tt>,\r
+ * the MixedCollection will be able to <i>derive</i> the key for the new item.\r
+ * In this case just pass the new item in this parameter.</p>\r
+ * @param {Object} o The item to add.\r
+ * @return {Object} The item added.\r
+ */\r
+ add : function(key, o){\r
if(arguments.length == 1){\r
o = arguments[0];\r
key = this.getKey(o);\r
return o;\r
},\r
\r
-/**\r
- * MixedCollection has a generic way to fetch keys if you implement getKey. The default implementation\r
- * simply returns <tt style="font-weight:bold;">item.id</tt> but you can provide your own implementation\r
- * to return a different value as in the following examples:\r
-<pre><code>\r
+ /**\r
+ * MixedCollection has a generic way to fetch keys if you implement getKey. The default implementation\r
+ * simply returns <b><code>item.id</code></b> but you can provide your own implementation\r
+ * to return a different value as in the following examples:<pre><code>\r
// normal way\r
var mc = new Ext.util.MixedCollection();\r
mc.add(someEl.dom.id, someEl);\r
});\r
mc.add(someEl);\r
mc.add(otherEl);\r
-</code></pre>\r
- * @param {Object} item The item for which to find the key.\r
- * @return {Object} The key for the passed item.\r
- */\r
+ * </code></pre>\r
+ * @param {Object} item The item for which to find the key.\r
+ * @return {Object} The key for the passed item.\r
+ */\r
getKey : function(o){\r
return o.id;\r
},\r
\r
-/**\r
- * Replaces an item in the collection. Fires the {@link #replace} event when complete.\r
- * @param {String} key <p>The key associated with the item to replace, or the replacement item.</p>\r
- * <p>If you supplied a {@link #getKey} implementation for this MixedCollection, or if the key\r
- * of your stored items is in a property called <tt><b>id</b></tt>, then the MixedCollection\r
- * will be able to <i>derive</i> the key of the replacement item. If you want to replace an item\r
- * with one having the same key value, then just pass the replacement item in this parameter.</p>\r
- * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate\r
- * with that key.\r
- * @return {Object} The new item.\r
- */\r
+ /**\r
+ * Replaces an item in the collection. Fires the {@link #replace} event when complete.\r
+ * @param {String} key <p>The key associated with the item to replace, or the replacement item.</p>\r
+ * <p>If you supplied a {@link #getKey} implementation for this MixedCollection, or if the key\r
+ * of your stored items is in a property called <tt><b>id</b></tt>, then the MixedCollection\r
+ * will be able to <i>derive</i> the key of the replacement item. If you want to replace an item\r
+ * with one having the same key value, then just pass the replacement item in this parameter.</p>\r
+ * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate\r
+ * with that key.\r
+ * @return {Object} The new item.\r
+ */\r
replace : function(key, o){\r
if(arguments.length == 1){\r
o = arguments[0];\r
key = this.getKey(o);\r
}\r
var old = this.map[key];\r
- if(typeof key == "undefined" || key === null || typeof old == "undefined"){\r
+ if(typeof key == 'undefined' || key === null || typeof old == 'undefined'){\r
return this.add(key, o);\r
}\r
var index = this.indexOfKey(key);\r
this.items[index] = o;\r
this.map[key] = o;\r
- this.fireEvent("replace", key, old, o);\r
+ this.fireEvent('replace', key, old, o);\r
return o;\r
},\r
\r
-/**\r
- * Adds all elements of an Array or an Object to the collection.\r
- * @param {Object/Array} objs An Object containing properties which will be added to the collection, or\r
- * an Array of values, each of which are added to the collection.\r
- */\r
+ /**\r
+ * Adds all elements of an Array or an Object to the collection.\r
+ * @param {Object/Array} objs An Object containing properties which will be added\r
+ * to the collection, or an Array of values, each of which are added to the collection.\r
+ * Functions references will be added to the collection if <code>{@link #allowFunctions}</code>\r
+ * has been set to <tt>true</tt>.\r
+ */\r
addAll : function(objs){\r
if(arguments.length > 1 || Ext.isArray(objs)){\r
var args = arguments.length > 1 ? arguments : objs;\r
}\r
}else{\r
for(var key in objs){\r
- if(this.allowFunctions || typeof objs[key] != "function"){\r
+ if(this.allowFunctions || typeof objs[key] != 'function'){\r
this.add(key, objs[key]);\r
}\r
}\r
}\r
},\r
\r
-/**\r
- * Executes the specified function once for every item in the collection, passing the following arguments:\r
- * <div class="mdetail-params"><ul>\r
- * <li><b>item</b> : Mixed<p class="sub-desc">The collection item</p></li>\r
- * <li><b>index</b> : Number<p class="sub-desc">The item's index</p></li>\r
- * <li><b>length</b> : Number<p class="sub-desc">The total number of items in the collection</p></li>\r
- * </ul></div>\r
- * The function should return a boolean value. Returning false from the function will stop the iteration.\r
- * @param {Function} fn The function to execute for each item.\r
- * @param {Object} scope (optional) The scope in which to execute the function.\r
- */\r
+ /**\r
+ * Executes the specified function once for every item in the collection, passing the following arguments:\r
+ * <div class="mdetail-params"><ul>\r
+ * <li><b>item</b> : Mixed<p class="sub-desc">The collection item</p></li>\r
+ * <li><b>index</b> : Number<p class="sub-desc">The item's index</p></li>\r
+ * <li><b>length</b> : Number<p class="sub-desc">The total number of items in the collection</p></li>\r
+ * </ul></div>\r
+ * The function should return a boolean value. Returning false from the function will stop the iteration.\r
+ * @param {Function} fn The function to execute for each item.\r
+ * @param {Object} scope (optional) The scope in which to execute the function.\r
+ */\r
each : function(fn, scope){\r
var items = [].concat(this.items); // each safe for removal\r
for(var i = 0, len = items.length; i < len; i++){\r
}\r
},\r
\r
-/**\r
- * Executes the specified function once for every key in the collection, passing each\r
- * key, and its associated item as the first two parameters.\r
- * @param {Function} fn The function to execute for each item.\r
- * @param {Object} scope (optional) The scope in which to execute the function.\r
- */\r
+ /**\r
+ * Executes the specified function once for every key in the collection, passing each\r
+ * key, and its associated item as the first two parameters.\r
+ * @param {Function} fn The function to execute for each item.\r
+ * @param {Object} scope (optional) The scope in which to execute the function.\r
+ */\r
eachKey : function(fn, scope){\r
for(var i = 0, len = this.keys.length; i < len; i++){\r
fn.call(scope || window, this.keys[i], this.items[i], i, len);\r
return null;\r
},\r
\r
-/**\r
- * Inserts an item at the specified index in the collection. Fires the {@link #add} event when complete.\r
- * @param {Number} index The index to insert the item at.\r
- * @param {String} key The key to associate with the new item, or the item itself.\r
- * @param {Object} o (optional) If the second parameter was a key, the new item.\r
- * @return {Object} The item inserted.\r
- */\r
+ /**\r
+ * Inserts an item at the specified index in the collection. Fires the {@link #add} event when complete.\r
+ * @param {Number} index The index to insert the item at.\r
+ * @param {String} key The key to associate with the new item, or the item itself.\r
+ * @param {Object} o (optional) If the second parameter was a key, the new item.\r
+ * @return {Object} The item inserted.\r
+ */\r
insert : function(index, key, o){\r
if(arguments.length == 2){\r
o = arguments[1];\r
}\r
this.length++;\r
this.items.splice(index, 0, o);\r
- if(typeof key != "undefined" && key !== null){\r
+ if(typeof key != 'undefined' && key !== null){\r
this.map[key] = o;\r
}\r
this.keys.splice(index, 0, key);\r
- this.fireEvent("add", index, o, key);\r
+ this.fireEvent('add', index, o, key);\r
return o;\r
},\r
\r
-/**\r
- * Remove an item from the collection.\r
- * @param {Object} o The item to remove.\r
- * @return {Object} The item removed or false if no item was removed.\r
- */\r
+ /**\r
+ * Remove an item from the collection.\r
+ * @param {Object} o The item to remove.\r
+ * @return {Object} The item removed or false if no item was removed.\r
+ */\r
remove : function(o){\r
return this.removeAt(this.indexOf(o));\r
},\r
\r
-/**\r
- * Remove an item from a specified index in the collection. Fires the {@link #remove} event when complete.\r
- * @param {Number} index The index within the collection of the item to remove.\r
- * @return {Object} The item removed or false if no item was removed.\r
- */\r
+ /**\r
+ * Remove an item from a specified index in the collection. Fires the {@link #remove} event when complete.\r
+ * @param {Number} index The index within the collection of the item to remove.\r
+ * @return {Object} The item removed or false if no item was removed.\r
+ */\r
removeAt : function(index){\r
if(index < this.length && index >= 0){\r
this.length--;\r
var o = this.items[index];\r
this.items.splice(index, 1);\r
var key = this.keys[index];\r
- if(typeof key != "undefined"){\r
+ if(typeof key != 'undefined'){\r
delete this.map[key];\r
}\r
this.keys.splice(index, 1);\r
- this.fireEvent("remove", o, key);\r
+ this.fireEvent('remove', o, key);\r
return o;\r
}\r
return false;\r
},\r
\r
-/**\r
- * Removed an item associated with the passed key fom the collection.\r
- * @param {String} key The key of the item to remove.\r
- * @return {Object} The item removed or false if no item was removed.\r
- */\r
+ /**\r
+ * Removed an item associated with the passed key fom the collection.\r
+ * @param {String} key The key of the item to remove.\r
+ * @return {Object} The item removed or false if no item was removed.\r
+ */\r
removeKey : function(key){\r
return this.removeAt(this.indexOfKey(key));\r
},\r
\r
-/**\r
- * Returns the number of items in the collection.\r
- * @return {Number} the number of items in the collection.\r
- */\r
+ /**\r
+ * Returns the number of items in the collection.\r
+ * @return {Number} the number of items in the collection.\r
+ */\r
getCount : function(){\r
return this.length;\r
},\r
-\r
-/**\r
- * Returns index within the collection of the passed Object.\r
- * @param {Object} o The item to find the index of.\r
- * @return {Number} index of the item. Returns -1 if not found.\r
- */\r
+ \r
+ /**\r
+ * Returns index within the collection of the passed Object.\r
+ * @param {Object} o The item to find the index of.\r
+ * @return {Number} index of the item. Returns -1 if not found.\r
+ */\r
indexOf : function(o){\r
return this.items.indexOf(o);\r
},\r
\r
-/**\r
- * Returns index within the collection of the passed key.\r
- * @param {String} key The key to find the index of.\r
- * @return {Number} index of the key.\r
- */\r
+ /**\r
+ * Returns index within the collection of the passed key.\r
+ * @param {String} key The key to find the index of.\r
+ * @return {Number} index of the key.\r
+ */\r
indexOfKey : function(key){\r
return this.keys.indexOf(key);\r
},\r
\r
-/**\r
- * Returns the item associated with the passed key OR index. Key has priority over index. This is the equivalent\r
- * of calling {@link #key} first, then if nothing matched calling {@link #itemAt}.\r
- * @param {String/Number} key The key or index of the item.\r
- * @return {Object} If the item is found, returns the item. If the item was not found, returns <tt>undefined</tt>.\r
- * If an item was found, but is a Class, returns <tt>null</tt>.\r
- */\r
+ /**\r
+ * Returns the item associated with the passed key OR index.\r
+ * Key has priority over index. This is the equivalent\r
+ * of calling {@link #key} first, then if nothing matched calling {@link #itemAt}.\r
+ * @param {String/Number} key The key or index of the item.\r
+ * @return {Object} If the item is found, returns the item. If the item was not found, returns <tt>undefined</tt>.\r
+ * If an item was found, but is a Class, returns <tt>null</tt>.\r
+ */\r
item : function(key){\r
var mk = this.map[key],\r
item = mk !== undefined ? mk : (typeof key == 'number') ? this.items[key] : undefined;\r
return !Ext.isFunction(item) || this.allowFunctions ? item : null; // for prototype!\r
},\r
\r
-/**\r
- * Returns the item at the specified index.\r
- * @param {Number} index The index of the item.\r
- * @return {Object} The item at the specified index.\r
- */\r
+ /**\r
+ * Returns the item at the specified index.\r
+ * @param {Number} index The index of the item.\r
+ * @return {Object} The item at the specified index.\r
+ */\r
itemAt : function(index){\r
return this.items[index];\r
},\r
\r
-/**\r
- * Returns the item associated with the passed key.\r
- * @param {String/Number} key The key of the item.\r
- * @return {Object} The item associated with the passed key.\r
- */\r
+ /**\r
+ * Returns the item associated with the passed key.\r
+ * @param {String/Number} key The key of the item.\r
+ * @return {Object} The item associated with the passed key.\r
+ */\r
key : function(key){\r
return this.map[key];\r
},\r
\r
-/**\r
- * Returns true if the collection contains the passed Object as an item.\r
- * @param {Object} o The Object to look for in the collection.\r
- * @return {Boolean} True if the collection contains the Object as an item.\r
- */\r
+ /**\r
+ * Returns true if the collection contains the passed Object as an item.\r
+ * @param {Object} o The Object to look for in the collection.\r
+ * @return {Boolean} True if the collection contains the Object as an item.\r
+ */\r
contains : function(o){\r
return this.indexOf(o) != -1;\r
},\r
\r
-/**\r
- * Returns true if the collection contains the passed Object as a key.\r
- * @param {String} key The key to look for in the collection.\r
- * @return {Boolean} True if the collection contains the Object as a key.\r
- */\r
+ /**\r
+ * Returns true if the collection contains the passed Object as a key.\r
+ * @param {String} key The key to look for in the collection.\r
+ * @return {Boolean} True if the collection contains the Object as a key.\r
+ */\r
containsKey : function(key){\r
- return typeof this.map[key] != "undefined";\r
+ return typeof this.map[key] != 'undefined';\r
},\r
\r
-/**\r
- * Removes all items from the collection. Fires the {@link #clear} event when complete.\r
- */\r
+ /**\r
+ * Removes all items from the collection. Fires the {@link #clear} event when complete.\r
+ */\r
clear : function(){\r
this.length = 0;\r
this.items = [];\r
this.keys = [];\r
this.map = {};\r
- this.fireEvent("clear");\r
+ this.fireEvent('clear');\r
},\r
\r
-/**\r
- * Returns the first item in the collection.\r
- * @return {Object} the first item in the collection..\r
- */\r
+ /**\r
+ * Returns the first item in the collection.\r
+ * @return {Object} the first item in the collection..\r
+ */\r
first : function(){\r
return this.items[0];\r
},\r
\r
-/**\r
- * Returns the last item in the collection.\r
- * @return {Object} the last item in the collection..\r
- */\r
+ /**\r
+ * Returns the last item in the collection.\r
+ * @return {Object} the last item in the collection..\r
+ */\r
last : function(){\r
return this.items[this.length-1];\r
},\r
\r
- // private\r
+ /**\r
+ * @private\r
+ * @param {String} property Property to sort by ('key', 'value', or 'index')\r
+ * @param {String} dir (optional) Direction to sort 'ASC' or 'DESC'. Defaults to 'ASC'.\r
+ * @param {Function} fn (optional) Comparison function that defines the sort order.\r
+ * Defaults to sorting by numeric value. \r
+ */\r
_sort : function(property, dir, fn){\r
var i,\r
len,\r
- dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1,\r
+ dsc = String(dir).toUpperCase() == 'DESC' ? -1 : 1,\r
c = [], k = this.keys, items = this.items;\r
\r
fn = fn || function(a, b){\r
items[i] = c[i].value;\r
k[i] = c[i].key;\r
}\r
- this.fireEvent("sort", this);\r
+ this.fireEvent('sort', this);\r
},\r
\r
/**\r
- * Sorts this collection with the passed comparison function\r
- * @param {String} direction (optional) "ASC" or "DESC"\r
- * @param {Function} fn (optional) comparison function\r
+ * Sorts this collection by <b>item</b> value with the passed comparison function.\r
+ * @param {String} direction (optional) 'ASC' or 'DESC'. Defaults to 'ASC'.\r
+ * @param {Function} fn (optional) Comparison function that defines the sort order.\r
+ * Defaults to sorting by numeric value. \r
*/\r
sort : function(dir, fn){\r
- this._sort("value", dir, fn);\r
+ this._sort('value', dir, fn);\r
},\r
\r
/**\r
- * Sorts this collection by keys\r
- * @param {String} direction (optional) "ASC" or "DESC"\r
- * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)\r
+ * Sorts this collection by <b>key</b>s.\r
+ * @param {String} direction (optional) 'ASC' or 'DESC'. Defaults to 'ASC'.\r
+ * @param {Function} fn (optional) Comparison function that defines the sort order.\r
+ * Defaults to sorting by case insensitive string. \r
*/\r
keySort : function(dir, fn){\r
- this._sort("key", dir, fn || function(a, b){\r
+ this._sort('key', dir, fn || function(a, b){\r
var v1 = String(a).toUpperCase(), v2 = String(b).toUpperCase();\r
return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);\r
});\r
\r
/**\r
* Returns a range of items in this collection\r
- * @param {Number} startIndex (optional) defaults to 0\r
- * @param {Number} endIndex (optional) default to the last item\r
+ * @param {Number} startIndex (optional) The starting index. Defaults to 0.\r
+ * @param {Number} endIndex (optional) The ending index. Defaults to the last item.\r
* @return {Array} An array of items\r
*/\r
getRange : function(start, end){\r
return [];\r
}\r
start = start || 0;\r
- end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);\r
+ end = Math.min(typeof end == 'undefined' ? this.length-1 : end, this.length-1);\r
var i, r = [];\r
if(start <= end){\r
for(i = start; i <= end; i++) {\r
});\r
/**\r
* This method calls {@link #item item()}.\r
- * Returns the item associated with the passed key OR index. Key has priority over index. This is the equivalent\r
- * of calling {@link #key} first, then if nothing matched calling {@link #itemAt}.\r
+ * Returns the item associated with the passed key OR index. Key has priority\r
+ * over index. This is the equivalent of calling {@link #key} first, then if\r
+ * nothing matched calling {@link #itemAt}.\r
* @param {String/Number} key The key or index of the item.\r
- * @return {Object} If the item is found, returns the item. If the item was not found, returns <tt>undefined</tt>.\r
- * If an item was found, but is a Class, returns <tt>null</tt>.\r
+ * @return {Object} If the item is found, returns the item. If the item was\r
+ * not found, returns <tt>undefined</tt>. If an item was found, but is a Class,\r
+ * returns <tt>null</tt>.\r
*/\r
Ext.util.MixedCollection.prototype.get = Ext.util.MixedCollection.prototype.item;/**
* @class Ext.util.JSON
return eval("(" + json + ')');
},
doEncode = function(o){
- if(typeof o == "undefined" || o === null){
+ if(!Ext.isDefined(o) || o === null){
return "null";
}else if(Ext.isArray(o)){
return encodeArray(o);
- }else if(Object.prototype.toString.apply(o) === '[object Date]'){
+ }else if(Ext.isDate(o)){
return Ext.util.JSON.encodeDate(o);
- }else if(typeof o == "string"){
+ }else if(Ext.isString(o)){
return encodeString(o);
}else if(typeof o == "number"){
+ //don't use isNumber here, since finite checks happen inside isNumber
return isFinite(o) ? String(o) : "null";
- }else if(typeof o == "boolean"){
+ }else if(Ext.isBoolean(o)){
return String(o);
}else {
var a = ["{"], b, i, v;
for (i in o) {
- if(!useHasOwn || o.hasOwnProperty(i)) {
- v = o[i];
- switch (typeof v) {
- case "undefined":
- case "function":
- case "unknown":
- break;
- default:
- if(b){
- a.push(',');
+ // don't encode DOM objects
+ if(!o.getElementsByTagName){
+ if(!useHasOwn || o.hasOwnProperty(i)) {
+ v = o[i];
+ switch (typeof v) {
+ case "undefined":
+ case "function":
+ case "unknown":
+ break;
+ default:
+ if(b){
+ a.push(',');
+ }
+ a.push(doEncode(i), ":",
+ v === null ? "null" : doEncode(v));
+ b = true;
}
- a.push(doEncode(i), ":",
- v === null ? "null" : doEncode(v));
- b = true;
}
}
}
}();/**
* @class Ext.XTemplate
* @extends Ext.Template
- * <p>A template class that supports advanced functionality like autofilling arrays, conditional processing with
- * basic comparison operators, sub-templates, basic math function support, special built-in template variables,
- * inline code execution and more. XTemplate also provides the templating mechanism built into {@link Ext.DataView}.</p>
- * <p>XTemplate supports 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. The following examples demonstrate all of the supported features.
- * This is the data object used for reference in each code example:</p>
+ * <p>A template class that supports advanced functionality like:<div class="mdetail-params"><ul>
+ * <li>Autofilling arrays using templates and sub-templates</li>
+ * <li>Conditional processing with basic comparison operators</li>
+ * <li>Basic math function support</li>
+ * <li>Execute arbitrary inline code with special built-in template variables</li>
+ * <li>Custom member functions</li>
+ * <li>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</li>
+ * </ul></div></p>
+ * <p>XTemplate provides the templating mechanism built into:<div class="mdetail-params"><ul>
+ * <li>{@link Ext.DataView}</li>
+ * <li>{@link Ext.ListView}</li>
+ * <li>{@link Ext.form.ComboBox}</li>
+ * <li>{@link Ext.grid.TemplateColumn}</li>
+ * <li>{@link Ext.grid.GroupingView}</li>
+ * <li>{@link Ext.menu.Item}</li>
+ * <li>{@link Ext.layout.MenuLayout}</li>
+ * <li>{@link Ext.ColorPalette}</li>
+ * </ul></div></p>
+ *
+ * <p>For example usage {@link #XTemplate see the constructor}.</p>
+ *
+ * @constructor
+ * The {@link Ext.Template#Template Ext.Template constructor} describes
+ * the acceptable parameters to pass to the constructor. The following
+ * examples demonstrate all of the supported features.</p>
+ *
+ * <div class="mdetail-params"><ul>
+ *
+ * <li><b><u>Sample Data</u></b>
+ * <div class="sub-desc">
+ * <p>This is the data object used for reference in each code example:</p>
* <pre><code>
var data = {
name: 'Jack Slocum',
}]
};
* </code></pre>
- * <p><b>Auto filling of arrays</b><br/>The <tt>tpl</tt> tag and the <tt>for</tt> operator are used
- * to process the provided data object. If <tt>for="."</tt> is specified, the data object provided
- * is examined. If the variable in <tt>for</tt> is an array, it will auto-fill, repeating the template
- * block inside the <tt>tpl</tt> tag for each item in the array:</p>
+ * </div>
+ * </li>
+ *
+ *
+ * <li><b><u>Auto filling of arrays</u></b>
+ * <div class="sub-desc">
+ * <p>The <b><tt>tpl</tt></b> tag and the <b><tt>for</tt></b> operator are used
+ * to process the provided data object:
+ * <ul>
+ * <li>If the value specified in <tt>for</tt> is an array, it will auto-fill,
+ * repeating the template block inside the <tt>tpl</tt> tag for each item in the
+ * array.</li>
+ * <li>If <tt>for="."</tt> is specified, the data object provided is examined.</li>
+ * <li>While processing an array, the special variable <tt>{#}</tt>
+ * will provide the current array index + 1 (starts at 1, not 0).</li>
+ * </ul>
+ * </p>
+ * <pre><code>
+<tpl <b>for</b>=".">...</tpl> // loop through array at root node
+<tpl <b>for</b>="foo">...</tpl> // loop through array at foo node
+<tpl <b>for</b>="foo.bar">...</tpl> // loop through array at foo.bar node
+ * </code></pre>
+ * Using the sample data above:
* <pre><code>
var tpl = new Ext.XTemplate(
'<p>Kids: ',
- '<tpl for=".">',
- '<p>{name}</p>',
+ '<tpl <b>for</b>=".">', // 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
* </code></pre>
- * <p><b>Scope switching</b><br/>The <tt>for</tt> property can be leveraged to access specified members
- * of the provided data object to populate the template:</p>
+ * <p>An example illustrating how the <b><tt>for</tt></b> property can be leveraged
+ * to access specified members of the provided data object to populate the template:</p>
* <pre><code>
var tpl = new Ext.XTemplate(
'<p>Name: {name}</p>',
'<p>Title: {title}</p>',
'<p>Company: {company}</p>',
'<p>Kids: ',
- '<tpl <b>for="kids"</b>>', // interrogate the kids property within the data
+ '<tpl <b>for="kids"</b>>', // 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
+ * </code></pre>
+ * <p>Flat arrays that contain values (and not objects) can be auto-rendered
+ * using the special <b><tt>{.}</tt></b> variable inside a loop. This variable
+ * will represent the value of the array at the current index:</p>
+ * <pre><code>
+var tpl = new Ext.XTemplate(
+ '<p>{name}\'s favorite beverages:</p>',
+ '<tpl for="drinks">',
+ '<div> - {.}</div>',
+ '</tpl>'
+);
tpl.overwrite(panel.body, data);
* </code></pre>
- * <p><b>Access to parent object from within sub-template scope</b><br/>When processing a sub-template, for example while
- * looping through a child array, you can access the parent object's members via the <tt>parent</tt> object:</p>
+ * <p>When processing a sub-template, for example while looping through a child array,
+ * you can access the parent object's members via the <b><tt>parent</tt></b> object:</p>
* <pre><code>
var tpl = new Ext.XTemplate(
'<p>Name: {name}</p>',
'<p>Kids: ',
'<tpl for="kids">',
- '<tpl if="age &gt; 1">', // <-- Note that the > is encoded
+ '<tpl if="age > 1">',
'<p>{name}</p>',
- '<p>Dad: {parent.name}</p>',
+ '<p>Dad: {<b>parent</b>.name}</p>',
'</tpl>',
'</tpl></p>'
);
tpl.overwrite(panel.body, data);
-</code></pre>
- * <p><b>Array item index and basic math support</b> <br/>While processing an array, the special variable <tt>{#}</tt>
- * will provide the current array index + 1 (starts at 1, not 0). Templates also support the basic math operators
- * + - * and / that can be applied directly on numeric data values:</p>
+ * </code></pre>
+ * </div>
+ * </li>
+ *
+ *
+ * <li><b><u>Conditional processing with basic comparison operators</u></b>
+ * <div class="sub-desc">
+ * <p>The <b><tt>tpl</tt></b> tag and the <b><tt>if</tt></b> operator are used
+ * to provide conditional checks for deciding whether or not to render specific
+ * parts of the template. Notes:<div class="sub-desc"><ul>
+ * <li>Double quotes must be encoded if used within the conditional</li>
+ * <li>There is no <tt>else</tt> operator — if needed, two opposite
+ * <tt>if</tt> statements should be used.</li>
+ * </ul></div>
+ * <pre><code>
+<tpl if="age > 1 && age < 10">Child</tpl>
+<tpl if="age >= 10 && age < 18">Teenager</tpl>
+<tpl <b>if</b>="this.isGirl(name)">...</tpl>
+<tpl <b>if</b>="id==\'download\'">...</tpl>
+<tpl <b>if</b>="needsIcon"><img src="{icon}" class="{iconCls}"/></tpl>
+// no good:
+<tpl if="name == "Jack"">Hello</tpl>
+// encode " if it is part of the condition, e.g.
+<tpl if="name == &quot;Jack&quot;">Hello</tpl>
+ * </code></pre>
+ * Using the sample data above:
* <pre><code>
var tpl = new Ext.XTemplate(
'<p>Name: {name}</p>',
'<p>Kids: ',
'<tpl for="kids">',
- '<tpl if="age &gt; 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 if="age > 1">',
+ '<p>{name}</p>',
'</tpl>',
'</tpl></p>'
);
tpl.overwrite(panel.body, data);
-</code></pre>
- * <p><b>Auto-rendering of flat arrays</b> <br/>Flat arrays that contain values (and not objects) can be auto-rendered
- * using the special <tt>{.}</tt> variable inside a loop. This variable will represent the value of
- * the array at the current index:</p>
- * <pre><code>
-var tpl = new Ext.XTemplate(
- '<p>{name}\'s favorite beverages:</p>',
- '<tpl for="drinks">',
- '<div> - {.}</div>',
- '</tpl>'
-);
-tpl.overwrite(panel.body, data);
-</code></pre>
- * <p><b>Basic conditional logic</b> <br/>Using the <tt>tpl</tt> tag and the <tt>if</tt>
- * operator you can provide conditional checks for deciding whether or not to render specific parts of the template.
- * Note that there is no <tt>else</tt> operator — if needed, you should use two opposite <tt>if</tt> statements.
- * Properly-encoded attributes are required as seen in the following example:</p>
+ * </code></pre>
+ * </div>
+ * </li>
+ *
+ *
+ * <li><b><u>Basic math support</u></b>
+ * <div class="sub-desc">
+ * <p>The following basic math operators may be applied directly on numeric
+ * data values:</p><pre>
+ * + - * /
+ * </pre>
+ * For example:
* <pre><code>
var tpl = new Ext.XTemplate(
'<p>Name: {name}</p>',
'<p>Kids: ',
'<tpl for="kids">',
'<tpl if="age &gt; 1">', // <-- Note that the > is encoded
- '<p>{name}</p>',
+ '<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);
</code></pre>
- * <p><b>Ability to execute arbitrary inline code</b> <br/>In an XTemplate, anything between {[ ... ]} is considered
- * code to be executed in the scope of the template. There are some special variables available in that code:
+ * </div>
+ * </li>
+ *
+ *
+ * <li><b><u>Execute arbitrary inline code with special built-in template variables</u></b>
+ * <div class="sub-desc">
+ * <p>Anything between <code>{[ ... ]}</code> is considered code to be executed
+ * in the scope of the template. There are some special variables available in that code:
* <ul>
- * <li><b><tt>values</tt></b>: The values in the current scope. If you are using scope changing sub-templates, you
- * can change what <tt>values</tt> is.</li>
+ * <li><b><tt>values</tt></b>: The values in the current scope. If you are using
+ * scope changing sub-templates, you can change what <tt>values</tt> is.</li>
* <li><b><tt>parent</tt></b>: The scope (values) of the ancestor template.</li>
- * <li><b><tt>xindex</tt></b>: If you are in a looping template, the index of the loop you are in (1-based).</li>
- * <li><b><tt>xcount</tt></b>: If you are in a looping template, the total length of the array you are looping.</li>
+ * <li><b><tt>xindex</tt></b>: If you are in a looping template, the index of the
+ * loop you are in (1-based).</li>
+ * <li><b><tt>xcount</tt></b>: If you are in a looping template, the total length
+ * of the array you are looping.</li>
* <li><b><tt>fm</tt></b>: An alias for <tt>Ext.util.Format</tt>.</li>
* </ul>
- * This example demonstrates basic row striping using an inline code block and the <tt>xindex</tt> variable:</p>
+ * This example demonstrates basic row striping using an inline code block and the
+ * <tt>xindex</tt> variable:</p>
* <pre><code>
var tpl = new Ext.XTemplate(
'<p>Name: {name}</p>',
'</tpl></p>'
);
tpl.overwrite(panel.body, data);
-</code></pre>
- * <p><b>Template member functions</b> <br/>One or more member functions can be defined directly on the config
+ * </code></pre>
+ * </div>
+ * </li>
+ *
+ * <li><b><u>Template member functions</u></b>
+ * <div class="sub-desc">
+ * <p>One or more member functions can be specified in a configuration
* object passed into the XTemplate constructor for more complex processing:</p>
* <pre><code>
var tpl = new Ext.XTemplate(
'<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>', {
- isGirl: function(name){
- return name == 'Sara Grace';
- },
- isBaby: function(age){
- return age < 1;
- }
-});
+ '</tpl></p>',
+ {
+ // XTemplate configuration:
+ compiled: true,
+ disableFormats: true,
+ // member functions:
+ isGirl: function(name){
+ return name == 'Sara Grace';
+ },
+ isBaby: function(age){
+ return age < 1;
+ }
+ }
+);
tpl.overwrite(panel.body, data);
-</code></pre>
- * @constructor
- * @param {String/Array/Object} parts The HTML fragment or an array of fragments to join(""), or multiple arguments
- * to join("") that can also include a config object
+ * </code></pre>
+ * </div>
+ * </li>
+ *
+ * </ul></div>
+ *
+ * @param {Mixed} config
*/
Ext.XTemplate = function(){
Ext.XTemplate.superclass.constructor.apply(this, arguments);
}
function codeFn(m, code){
- return "'"+ sep +'('+code+')'+sep+"'";
+ // Single quotes get escaped when the template is compiled, however we want to undo this when running code.
+ return "'" + sep + '(' + code.replace(/\\'/g, "'") + ')' + sep + "'";
}
// branched to use + in gecko and [].join() in others
try{// try catch for cross domain access issue\r
var ssRules = ss.cssRules || ss.rules;\r
for(var j = ssRules.length-1; j >= 0; --j){\r
- rules[ssRules[j].selectorText] = ssRules[j];\r
+ rules[ssRules[j].selectorText.toLowerCase()] = ssRules[j];\r
}\r
}catch(e){}\r
},\r
getRule : function(selector, refreshCache){\r
var rs = this.getRules(refreshCache);\r
if(!Ext.isArray(selector)){\r
- return rs[selector];\r
+ return rs[selector.toLowerCase()];\r
}\r
for(var i = 0; i < selector.length; i++){\r
if(rs[selector[i]]){\r
- return rs[selector[i]];\r
+ return rs[selector[i].toLowerCase()];\r
}\r
}\r
return null;\r
*/
forceKeyDown : false,
- // private
- prepareEvent : function(e){
- var k = e.getKey();
- var h = this.keyToHandler[k];
- if(Ext.isSafari2 && h && k >= 37 && k <= 40){
- e.stopEvent();
- }
- },
-
// private
relay : function(e){
var k = e.getKey();
27 : "esc",
9 : "tab"
},
+
+ stopKeyUp: function(e) {
+ var k = e.getKey();
+
+ if (k >= 37 && k <= 40) {
+ // *** bugfix - safari 2.x fires 2 keyup events on cursor keys
+ // *** (note: this bugfix sacrifices the "keyup" event originating from keyNav elements in Safari 2)
+ e.stopEvent();
+ }
+ },
/**
* Enable this KeyNav
*/
- enable: function(){
- if(this.disabled){
- // ie won't do special keys on keypress, no one else will repeat keys with keydown
- // the EventObject will normalize Safari automatically
- if(this.isKeydown()){
- this.el.on("keydown", this.relay, this);
- }else{
- this.el.on("keydown", this.prepareEvent, this);
- this.el.on("keypress", this.relay, this);
+ enable: function() {
+ if (this.disabled) {
+ if (Ext.isSafari2) {
+ // call stopKeyUp() on "keyup" event
+ this.el.on('keyup', this.stopKeyUp, this);
}
- this.disabled = false;
- }
- },
+
+ this.el.on(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
+ this.disabled = false;
+ }
+ },
/**
* Disable this KeyNav
*/
- disable: function(){
- if(!this.disabled){
- if(this.isKeydown()){
- this.el.un("keydown", this.relay, this);
- }else{
- this.el.un("keydown", this.prepareEvent, this);
- this.el.un("keypress", this.relay, this);
+ disable: function() {
+ if (!this.disabled) {
+ if (Ext.isSafari2) {
+ // remove "keyup" event handler
+ this.el.un('keyup', this.stopKeyUp, this);
}
- this.disabled = true;
- }
- },
+
+ this.el.un(this.isKeydown()? 'keydown' : 'keypress', this.relay, this);
+ this.disabled = true;
+ }
+ },
/**
* Convenience function for setting disabled/enabled by boolean.
* Create a cookie with the specified name and value. Additional settings\r
* for the cookie may be optionally specified (for example: expiration,\r
* access restriction, SSL).\r
- * @param {Object} name\r
- * @param {Object} value\r
+ * @param {String} name The name of the cookie to set. \r
+ * @param {Mixed} value The value to set for the cookie.\r
* @param {Object} expires (Optional) Specify an expiration date the\r
* cookie is to persist until. Note that the specified Date object will\r
* be converted to Greenwich Mean Time (GMT). \r
* <pre><code>\r
* var validStatus = Ext.util.Cookies.get("valid");\r
* </code></pre>\r
- * @param {Object} name The name of the cookie to get\r
+ * @param {String} name The name of the cookie to get\r
* @return {Mixed} Returns the cookie value for the specified name;\r
* null if the cookie name does not exist.\r
*/\r
\r
/**\r
* Removes a cookie with the provided name from the browser\r
- * if found.\r
- * @param {Object} name The name of the cookie to remove\r
+ * if found by setting its expiration date to sometime in the past. \r
+ * @param {String} name The name of the cookie to remove\r
*/\r
clear : function(name){\r
if(Ext.util.Cookies.get(name)){\r