Roo.js
[roojs1] / Roo.js
1 /*
2  * Based on:
3  * Ext JS Library 1.1.1
4  * Copyright(c) 2006-2007, Ext JS, LLC.
5  *
6  * Originally Released Under LGPL - original licence link has changed is not relivant.
7  *
8  * Fork - LGPL
9  * <script type="text/javascript">
10  */
11  
12
13
14
15
16 // for old browsers
17 window["undefined"] = window["undefined"];
18
19 /**
20  * @class Roo
21  * Roo core utilities and functions.
22  * @singleton
23  */
24 var Roo = {}; 
25 /**
26  * Copies all the properties of config to obj.
27  * @param {Object} obj The receiver of the properties
28  * @param {Object} config The source of the properties
29  * @param {Object} defaults A different object that will also be applied for default values
30  * @return {Object} returns obj
31  * @member Roo apply
32  */
33
34  
35 Roo.apply = function(o, c, defaults){
36     if(defaults){
37         // no "this" reference for friendly out of scope calls
38         Roo.apply(o, defaults);
39     }
40     if(o && c && typeof c == 'object'){
41         for(var p in c){
42             o[p] = c[p];
43         }
44     }
45     return o;
46 };
47
48
49 (function(){
50     var idSeed = 0;
51     var ua = navigator.userAgent.toLowerCase();
52
53     var isStrict = document.compatMode == "CSS1Compat",
54         isOpera = ua.indexOf("opera") > -1,
55         isSafari = (/webkit|khtml/).test(ua),
56         isIE = ua.indexOf("msie") > -1,
57         isIE7 = ua.indexOf("msie 7") > -1,
58         isGecko = !isSafari && ua.indexOf("gecko") > -1,
59         isBorderBox = isIE && !isStrict,
60         isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61         isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62         isLinux = (ua.indexOf("linux") != -1),
63         isSecure = window.location.href.toLowerCase().indexOf("https") === 0;
64
65     // remove css image flicker
66         if(isIE && !isIE7){
67         try{
68             document.execCommand("BackgroundImageCache", false, true);
69         }catch(e){}
70     }
71     
72     Roo.apply(Roo, {
73         /**
74          * True if the browser is in strict mode
75          * @type Boolean
76          */
77         isStrict : isStrict,
78         /**
79          * True if the page is running over SSL
80          * @type Boolean
81          */
82         isSecure : isSecure,
83         /**
84          * True when the document is fully initialized and ready for action
85          * @type Boolean
86          */
87         isReady : false,
88         /**
89          * Turn on debugging output (currently only the factory uses this)
90          * @type Boolean
91          */
92         
93         debug: false,
94
95         /**
96          * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
97          * @type Boolean
98          */
99         enableGarbageCollector : true,
100
101         /**
102          * True to automatically purge event listeners after uncaching an element (defaults to false).
103          * Note: this only happens if enableGarbageCollector is true.
104          * @type Boolean
105          */
106         enableListenerCollection:false,
107
108         /**
109          * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
110          * the IE insecure content warning (defaults to javascript:false).
111          * @type String
112          */
113         SSL_SECURE_URL : "javascript:false",
114
115         /**
116          * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
117          * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
118          * @type String
119          */
120         BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
121
122         emptyFn : function(){},
123         /**
124          *   Deep object/array copy. Function clones are actually wrappers around the
125          *   original function. Array-like objects are treated as arrays. Primitives are
126          *   returned untouched. Optionally, a function can be provided to handle other data
127          *   types, filter keys, validate values, etc.
128          *
129          *   **Note:** Cloning a non-trivial object is a reasonably heavy operation, due to
130          *   the need to recursively iterate down non-primitive properties. Clone should be
131          *   used only when a deep clone down to leaf level properties is explicitly
132          *   required. This method will also
133          *
134             In many cases (for example, when trying to isolate objects used as hashes for
135             configuration properties), a shallow copy, using `Y.merge()` is normally
136             sufficient. If more than one level of isolation is required, `Y.merge()` can be
137             used selectively at each level which needs to be isolated from the original
138             without going all the way to leaf properties.
139
140             @method clone
141             @param {object} o what to clone.
142             @param {boolean} safe if true, objects will not have prototype items from the
143                 source. If false, they will. In this case, the original is initially
144                 protected, but the clone is not completely immune from changes to the source
145                 object prototype. Also, cloned prototype items that are deleted from the
146                 clone will result in the value of the source prototype being exposed. If
147                 operating on a non-safe clone, items should be nulled out rather than
148                 deleted.
149             @param {function} f optional function to apply to each item in a collection; it
150                 will be executed prior to applying the value to the new object.
151                 Return false to prevent the copy.
152             @param {object} c optional execution context for f.
153             @param {object} owner Owner object passed when clone is iterating an object.
154                 Used to set up context for cloned functions.
155             @param {object} cloned hash of previously cloned objects to avoid multiple
156                 clones.
157             @return {Array|Object} the cloned object.
158           **/
159         clone : function(o, safe, f, c, owner, cloned) {
160             var o2, marked, stamp;
161
162             // Does not attempt to clone:
163             //
164             // * Non-typeof-object values, "primitive" values don't need cloning.
165             //
166             // * YUI instances, cloning complex object like YUI instances is not
167             //   advised, this is like cloning the world.
168             //
169             // * DOM nodes (#2528250), common host objects like DOM nodes cannot be
170             //   "subclassed" in Firefox and old versions of IE. Trying to use
171             //   `Object.create()` or `Y.extend()` on a DOM node will throw an error in
172             //   these browsers.
173             //
174             // Instad, the passed-in `o` will be return as-is when it matches one of the
175             // above criteria.
176 //            if (!L.isObject(o) ||
177 //                    Y.instanceOf(o, YUI) ||
178 //                    (o.addEventListener || o.attachEvent)) {
179 //
180 //                return o;
181 //            }
182
183             marked = cloned || {};
184
185             switch (this.type(o)) {
186                 case 'date':
187                     return new Date(o);
188                 case 'regexp':
189                     // if we do this we need to set the flags too
190                     // return new RegExp(o.source);
191                     return o;
192                 case 'function':
193                     // o2 = Y.bind(o, owner);
194                     // break;
195                     return o;
196                 case 'array':
197                     o2 = [];
198                     break;
199                 default:
200                     
201                     // #2528250 only one clone of a given object should be created.
202                     if (o['_~roo~_']) {
203                         return marked[o['_~roo~_']];
204                     }
205
206                     stamp = Roo.id();
207
208 //                    o2 = (safe) ? {} : Roo.Object(o);
209                     o2 = {};
210                     o['_~roo~_'] = stamp;
211                     marked[stamp] = o;
212             }
213
214             Roo.each(o, function(v, k) {
215                 if ((k || k === 0) && (!f || (f.call(c || this, v, k, this, o) !== false))) {
216                     if (k !== '_~roo~_') {
217                         if (k == 'prototype') {
218                             // skip the prototype
219                         // } else if (o[k] === o) {
220                         //     this[k] = this;
221                         } else {
222                             this[k] =
223                                 Roo.clone(v, safe, f, c, owner || o, marked);
224                         }
225                     }
226                 }
227             }, o2);
228
229             if (!cloned) {
230                 Roo.each(marked, function(v, k) {
231                     if (v['_~roo~_']) {
232                         try {
233                             delete v['_~roo~_'];
234                         } catch (e) {
235                             v['_~roo~_'] = null;
236                         }
237                     }
238                 }, this);
239                 marked = null;
240             }
241
242             return o2;
243         },
244         /**
245          * Copies all the properties of config to obj if they don't already exist.
246          * @param {Object} obj The receiver of the properties
247          * @param {Object} config The source of the properties
248          * @return {Object} returns obj
249          */
250         applyIf : function(o, c){
251             if(o && c){
252                 for(var p in c){
253                     if(typeof o[p] == "undefined"){ o[p] = c[p]; }
254                 }
255             }
256             return o;
257         },
258
259         /**
260          * Applies event listeners to elements by selectors when the document is ready.
261          * The event name is specified with an @ suffix.
262 <pre><code>
263 Roo.addBehaviors({
264    // add a listener for click on all anchors in element with id foo
265    '#foo a@click' : function(e, t){
266        // do something
267    },
268
269    // add the same listener to multiple selectors (separated by comma BEFORE the @)
270    '#foo a, #bar span.some-class@mouseover' : function(){
271        // do something
272    }
273 });
274 </code></pre>
275          * @param {Object} obj The list of behaviors to apply
276          */
277         addBehaviors : function(o){
278             if(!Roo.isReady){
279                 Roo.onReady(function(){
280                     Roo.addBehaviors(o);
281                 });
282                 return;
283             }
284             var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
285             for(var b in o){
286                 var parts = b.split('@');
287                 if(parts[1]){ // for Object prototype breakers
288                     var s = parts[0];
289                     if(!cache[s]){
290                         cache[s] = Roo.select(s);
291                     }
292                     cache[s].on(parts[1], o[b]);
293                 }
294             }
295             cache = null;
296         },
297
298         /**
299          * Generates unique ids. If the element already has an id, it is unchanged
300          * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
301          * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
302          * @return {String} The generated Id.
303          */
304         id : function(el, prefix){
305             prefix = prefix || "roo-gen";
306             el = Roo.getDom(el);
307             var id = prefix + (++idSeed);
308             return el ? (el.id ? el.id : (el.id = id)) : id;
309         },
310          
311        
312         /**
313          * Extends one class with another class and optionally overrides members with the passed literal. This class
314          * also adds the function "override()" to the class that can be used to override
315          * members on an instance.
316          * @param {Object} subclass The class inheriting the functionality
317          * @param {Object} superclass The class being extended
318          * @param {Object} overrides (optional) A literal with members
319          * @method extend
320          */
321         extend : function(){
322             // inline overrides
323             var io = function(o){
324                 for(var m in o){
325                     this[m] = o[m];
326                 }
327             };
328             return function(sb, sp, overrides){
329                 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
330                     overrides = sp;
331                     sp = sb;
332                     sb = function(){sp.apply(this, arguments);};
333                 }
334                 var F = function(){}, sbp, spp = sp.prototype;
335                 F.prototype = spp;
336                 sbp = sb.prototype = new F();
337                 sbp.constructor=sb;
338                 sb.superclass=spp;
339                 
340                 if(spp.constructor == Object.prototype.constructor){
341                     spp.constructor=sp;
342                    
343                 }
344                 
345                 sb.override = function(o){
346                     Roo.override(sb, o);
347                 };
348                 sbp.override = io;
349                 Roo.override(sb, overrides);
350                 return sb;
351             };
352         }(),
353
354         /**
355          * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
356          * Usage:<pre><code>
357 Roo.override(MyClass, {
358     newMethod1: function(){
359         // etc.
360     },
361     newMethod2: function(foo){
362         // etc.
363     }
364 });
365  </code></pre>
366          * @param {Object} origclass The class to override
367          * @param {Object} overrides The list of functions to add to origClass.  This should be specified as an object literal
368          * containing one or more methods.
369          * @method override
370          */
371         override : function(origclass, overrides){
372             if(overrides){
373                 var p = origclass.prototype;
374                 for(var method in overrides){
375                     p[method] = overrides[method];
376                 }
377             }
378         },
379         /**
380          * Creates namespaces to be used for scoping variables and classes so that they are not global.  Usage:
381          * <pre><code>
382 Roo.namespace('Company', 'Company.data');
383 Company.Widget = function() { ... }
384 Company.data.CustomStore = function(config) { ... }
385 </code></pre>
386          * @param {String} namespace1
387          * @param {String} namespace2
388          * @param {String} etc
389          * @method namespace
390          */
391         namespace : function(){
392             var a=arguments, o=null, i, j, d, rt;
393             for (i=0; i<a.length; ++i) {
394                 d=a[i].split(".");
395                 rt = d[0];
396                 /** eval:var:o */
397                 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
398                 for (j=1; j<d.length; ++j) {
399                     o[d[j]]=o[d[j]] || {};
400                     o=o[d[j]];
401                 }
402             }
403         },
404         /**
405          * Creates namespaces to be used for scoping variables and classes so that they are not global.  Usage:
406          * <pre><code>
407 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
408 Roo.factory(conf, Roo.data);
409 </code></pre>
410          * @param {String} classname
411          * @param {String} namespace (optional)
412          * @method factory
413          */
414          
415         factory : function(c, ns)
416         {
417             // no xtype, no ns or c.xns - or forced off by c.xns
418             if (!c.xtype   || (!ns && !c.xns) ||  (c.xns === false)) { // not enough info...
419                 return c;
420             }
421             ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
422             if (c.constructor == ns[c.xtype]) {// already created...
423                 return c;
424             }
425             if (ns[c.xtype]) {
426                 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
427                 var ret = new ns[c.xtype](c);
428                 ret.xns = false;
429                 return ret;
430             }
431             c.xns = false; // prevent recursion..
432             return c;
433         },
434          /**
435          * Logs to console if it can.
436          *
437          * @param {String|Object} string
438          * @method log
439          */
440         log : function(s)
441         {
442             if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
443                 return; // alerT?
444             }
445             console.log(s);
446             
447         },
448         /**
449          * Takes an object and converts it to an encoded URL. e.g. Roo.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2".  Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value.
450          * @param {Object} o
451          * @return {String}
452          */
453         urlEncode : function(o){
454             if(!o){
455                 return "";
456             }
457             var buf = [];
458             for(var key in o){
459                 var ov = o[key], k = Roo.encodeURIComponent(key);
460                 var type = typeof ov;
461                 if(type == 'undefined'){
462                     buf.push(k, "=&");
463                 }else if(type != "function" && type != "object"){
464                     buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
465                 }else if(ov instanceof Array){
466                     if (ov.length) {
467                             for(var i = 0, len = ov.length; i < len; i++) {
468                                 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
469                             }
470                         } else {
471                             buf.push(k, "=&");
472                         }
473                 }
474             }
475             buf.pop();
476             return buf.join("");
477         },
478          /**
479          * Safe version of encodeURIComponent
480          * @param {String} data 
481          * @return {String} 
482          */
483         
484         encodeURIComponent : function (data)
485         {
486             try {
487                 return encodeURIComponent(data);
488             } catch(e) {} // should be an uri encode error.
489             
490             if (data == '' || data == null){
491                return '';
492             }
493             // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
494             function nibble_to_hex(nibble){
495                 var chars = '0123456789ABCDEF';
496                 return chars.charAt(nibble);
497             }
498             data = data.toString();
499             var buffer = '';
500             for(var i=0; i<data.length; i++){
501                 var c = data.charCodeAt(i);
502                 var bs = new Array();
503                 if (c > 0x10000){
504                         // 4 bytes
505                     bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
506                     bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
507                     bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
508                     bs[3] = 0x80 | (c & 0x3F);
509                 }else if (c > 0x800){
510                          // 3 bytes
511                     bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
512                     bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
513                     bs[2] = 0x80 | (c & 0x3F);
514                 }else if (c > 0x80){
515                        // 2 bytes
516                     bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
517                     bs[1] = 0x80 | (c & 0x3F);
518                 }else{
519                         // 1 byte
520                     bs[0] = c;
521                 }
522                 for(var j=0; j<bs.length; j++){
523                     var b = bs[j];
524                     var hex = nibble_to_hex((b & 0xF0) >>> 4) 
525                             + nibble_to_hex(b &0x0F);
526                     buffer += '%'+hex;
527                }
528             }
529             return buffer;    
530              
531         },
532
533         /**
534          * Takes an encoded URL and and converts it to an object. e.g. Roo.urlDecode("foo=1&bar=2"); would return {foo: 1, bar: 2} or Roo.urlDecode("foo=1&bar=2&bar=3&bar=4", true); would return {foo: 1, bar: [2, 3, 4]}.
535          * @param {String} string
536          * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
537          * @return {Object} A literal with members
538          */
539         urlDecode : function(string, overwrite){
540             if(!string || !string.length){
541                 return {};
542             }
543             var obj = {};
544             var pairs = string.split('&');
545             var pair, name, value;
546             for(var i = 0, len = pairs.length; i < len; i++){
547                 pair = pairs[i].split('=');
548                 name = decodeURIComponent(pair[0]);
549                 value = decodeURIComponent(pair[1]);
550                 if(overwrite !== true){
551                     if(typeof obj[name] == "undefined"){
552                         obj[name] = value;
553                     }else if(typeof obj[name] == "string"){
554                         obj[name] = [obj[name]];
555                         obj[name].push(value);
556                     }else{
557                         obj[name].push(value);
558                     }
559                 }else{
560                     obj[name] = value;
561                 }
562             }
563             return obj;
564         },
565
566         /**
567          * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
568          * passed array is not really an array, your function is called once with it.
569          * The supplied function is called with (Object item, Number index, Array allItems).
570          * @param {Array/NodeList/Mixed} array
571          * @param {Function} fn
572          * @param {Object} scope
573          */
574         each : function(array, fn, scope){
575             if(typeof array.length == "undefined" || typeof array == "string"){
576                 array = [array];
577             }
578             for(var i = 0, len = array.length; i < len; i++){
579                 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
580             }
581         },
582
583         // deprecated
584         combine : function(){
585             var as = arguments, l = as.length, r = [];
586             for(var i = 0; i < l; i++){
587                 var a = as[i];
588                 if(a instanceof Array){
589                     r = r.concat(a);
590                 }else if(a.length !== undefined && !a.substr){
591                     r = r.concat(Array.prototype.slice.call(a, 0));
592                 }else{
593                     r.push(a);
594                 }
595             }
596             return r;
597         },
598
599         /**
600          * Escapes the passed string for use in a regular expression
601          * @param {String} str
602          * @return {String}
603          */
604         escapeRe : function(s) {
605             return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
606         },
607
608         // internal
609         callback : function(cb, scope, args, delay){
610             if(typeof cb == "function"){
611                 if(delay){
612                     cb.defer(delay, scope, args || []);
613                 }else{
614                     cb.apply(scope, args || []);
615                 }
616             }
617         },
618
619         /**
620          * Return the dom node for the passed string (id), dom node, or Roo.Element
621          * @param {String/HTMLElement/Roo.Element} el
622          * @return HTMLElement
623          */
624         getDom : function(el){
625             if(!el){
626                 return null;
627             }
628             return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
629         },
630
631         /**
632         * Shorthand for {@link Roo.ComponentMgr#get}
633         * @param {String} id
634         * @return Roo.Component
635         */
636         getCmp : function(id){
637             return Roo.ComponentMgr.get(id);
638         },
639          
640         num : function(v, defaultValue){
641             if(typeof v != 'number'){
642                 return defaultValue;
643             }
644             return v;
645         },
646
647         destroy : function(){
648             for(var i = 0, a = arguments, len = a.length; i < len; i++) {
649                 var as = a[i];
650                 if(as){
651                     if(as.dom){
652                         as.removeAllListeners();
653                         as.remove();
654                         continue;
655                     }
656                     if(typeof as.purgeListeners == 'function'){
657                         as.purgeListeners();
658                     }
659                     if(typeof as.destroy == 'function'){
660                         as.destroy();
661                     }
662                 }
663             }
664         },
665
666         // inpired by a similar function in mootools library
667         /**
668          * Returns the type of object that is passed in. If the object passed in is null or undefined it
669          * return false otherwise it returns one of the following values:<ul>
670          * <li><b>string</b>: If the object passed is a string</li>
671          * <li><b>number</b>: If the object passed is a number</li>
672          * <li><b>boolean</b>: If the object passed is a boolean value</li>
673          * <li><b>function</b>: If the object passed is a function reference</li>
674          * <li><b>object</b>: If the object passed is an object</li>
675          * <li><b>array</b>: If the object passed is an array</li>
676          * <li><b>regexp</b>: If the object passed is a regular expression</li>
677          * <li><b>element</b>: If the object passed is a DOM Element</li>
678          * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
679          * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
680          * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
681          * @param {Mixed} object
682          * @return {String}
683          */
684         type : function(o){
685             if(o === undefined || o === null){
686                 return false;
687             }
688             if(o.htmlElement){
689                 return 'element';
690             }
691             var t = typeof o;
692             if(t == 'object' && o.nodeName) {
693                 switch(o.nodeType) {
694                     case 1: return 'element';
695                     case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
696                 }
697             }
698             if(t == 'object' || t == 'function') {
699                 switch(o.constructor) {
700                     case Array: return 'array';
701                     case RegExp: return 'regexp';
702                 }
703                 if(typeof o.length == 'number' && typeof o.item == 'function') {
704                     return 'nodelist';
705                 }
706             }
707             return t;
708         },
709
710         /**
711          * Returns true if the passed value is null, undefined or an empty string (optional).
712          * @param {Mixed} value The value to test
713          * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
714          * @return {Boolean}
715          */
716         isEmpty : function(v, allowBlank){
717             return v === null || v === undefined || (!allowBlank ? v === '' : false);
718         },
719         
720         /** @type Boolean */
721         isOpera : isOpera,
722         /** @type Boolean */
723         isSafari : isSafari,
724         /** @type Boolean */
725         isIE : isIE,
726         /** @type Boolean */
727         isIE7 : isIE7,
728         /** @type Boolean */
729         isGecko : isGecko,
730         /** @type Boolean */
731         isBorderBox : isBorderBox,
732         /** @type Boolean */
733         isWindows : isWindows,
734         /** @type Boolean */
735         isLinux : isLinux,
736         /** @type Boolean */
737         isMac : isMac,
738
739         /**
740          * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
741          * you may want to set this to true.
742          * @type Boolean
743          */
744         useShims : ((isIE && !isIE7) || (isGecko && isMac)),
745         
746         
747                 
748         /**
749          * Selects a single element as a Roo Element
750          * This is about as close as you can get to jQuery's $('do crazy stuff')
751          * @param {String} selector The selector/xpath query
752          * @param {Node} root (optional) The start of the query (defaults to document).
753          * @return {Roo.Element}
754          */
755         selectNode : function(selector, root) 
756         {
757             var node = Roo.DomQuery.selectNode(selector,root);
758             return node ? Roo.get(node) : new Roo.Element(false);
759         }
760         
761     });
762
763
764 })();
765
766 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
767                 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");