4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
17 window["undefined"] = window["undefined"];
21 * Roo core utilities and functions.
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
35 Roo.apply = function(o, c, defaults){
37 // no "this" reference for friendly out of scope calls
38 Roo.apply(o, defaults);
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
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;
65 // remove css image flicker
68 document.execCommand("BackgroundImageCache", false, true);
74 * True if the browser is in strict mode
79 * True if the page is running over SSL
84 * True when the document is fully initialized and ready for action
89 * Turn on debugging output (currently only the factory uses this)
96 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
99 enableGarbageCollector : true,
102 * True to automatically purge event listeners after uncaching an element (defaults to false).
103 * Note: this only happens if enableGarbageCollector is true.
106 enableListenerCollection:false,
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).
113 SSL_SECURE_URL : "javascript:false",
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).
120 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
122 emptyFn : function(){},
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.
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
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.
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
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
157 @return {Array|Object} the cloned object.
159 clone : function(o, safe, f, c, owner, cloned) {
160 var o2, marked, stamp;
162 // Does not attempt to clone:
164 // * Non-typeof-object values, "primitive" values don't need cloning.
166 // * YUI instances, cloning complex object like YUI instances is not
167 // advised, this is like cloning the world.
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
174 // Instad, the passed-in `o` will be return as-is when it matches one of the
176 // if (!L.isObject(o) ||
177 // Y.instanceOf(o, YUI) ||
178 // (o.addEventListener || o.attachEvent)) {
183 marked = cloned || {};
189 // if we do this we need to set the flags too
190 // return new RegExp(o.source);
193 // o2 = Y.bind(o, owner);
201 // #2528250 only one clone of a given object should be created.
202 if (o[CLONE_MARKER]) {
203 return marked[o[CLONE_MARKER]];
208 o2 = (safe) ? {} : Y.Object(o);
210 o[CLONE_MARKER] = stamp;
214 Y.each(o, function(v, k) {
215 if ((k || k === 0) && (!f || (f.call(c || this, v, k, this, o) !== false))) {
216 if (k !== CLONE_MARKER) {
217 if (k == 'prototype') {
218 // skip the prototype
219 // } else if (o[k] === o) {
223 Y.clone(v, safe, f, c, owner || o, marked);
230 Y.Object.each(marked, function(v, k) {
231 if (v[CLONE_MARKER]) {
233 delete v[CLONE_MARKER];
235 v[CLONE_MARKER] = null;
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
250 applyIf : function(o, c){
253 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
260 * Applies event listeners to elements by selectors when the document is ready.
261 * The event name is specified with an @ suffix.
264 // add a listener for click on all anchors in element with id foo
265 '#foo a@click' : function(e, t){
269 // add the same listener to multiple selectors (separated by comma BEFORE the @)
270 '#foo a, #bar span.some-class@mouseover' : function(){
275 * @param {Object} obj The list of behaviors to apply
277 addBehaviors : function(o){
279 Roo.onReady(function(){
284 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
286 var parts = b.split('@');
287 if(parts[1]){ // for Object prototype breakers
290 cache[s] = Roo.select(s);
292 cache[s].on(parts[1], o[b]);
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.
304 id : function(el, prefix){
305 prefix = prefix || "roo-gen";
307 var id = prefix + (++idSeed);
308 return el ? (el.id ? el.id : (el.id = id)) : id;
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
323 var io = function(o){
328 return function(sb, sp, overrides){
329 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
332 sb = function(){sp.apply(this, arguments);};
334 var F = function(){}, sbp, spp = sp.prototype;
336 sbp = sb.prototype = new F();
340 if(spp.constructor == Object.prototype.constructor){
345 sb.override = function(o){
349 Roo.override(sb, overrides);
355 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
357 Roo.override(MyClass, {
358 newMethod1: function(){
361 newMethod2: function(foo){
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.
371 override : function(origclass, overrides){
373 var p = origclass.prototype;
374 for(var method in overrides){
375 p[method] = overrides[method];
380 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
382 Roo.namespace('Company', 'Company.data');
383 Company.Widget = function() { ... }
384 Company.data.CustomStore = function(config) { ... }
386 * @param {String} namespace1
387 * @param {String} namespace2
388 * @param {String} etc
391 namespace : function(){
392 var a=arguments, o=null, i, j, d, rt;
393 for (i=0; i<a.length; ++i) {
397 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
398 for (j=1; j<d.length; ++j) {
399 o[d[j]]=o[d[j]] || {};
405 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
407 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
408 Roo.factory(conf, Roo.data);
410 * @param {String} classname
411 * @param {String} namespace (optional)
415 factory : function(c, ns)
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...
421 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
422 if (c.constructor == ns[c.xtype]) {// already created...
426 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
427 var ret = new ns[c.xtype](c);
431 c.xns = false; // prevent recursion..
435 * Logs to console if it can.
437 * @param {String|Object} string
442 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
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.
453 urlEncode : function(o){
459 var ov = o[key], k = Roo.encodeURIComponent(key);
460 var type = typeof ov;
461 if(type == 'undefined'){
463 }else if(type != "function" && type != "object"){
464 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
465 }else if(ov instanceof Array){
467 for(var i = 0, len = ov.length; i < len; i++) {
468 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
479 * Safe version of encodeURIComponent
480 * @param {String} data
484 encodeURIComponent : function (data)
487 return encodeURIComponent(data);
488 } catch(e) {} // should be an uri encode error.
490 if (data == '' || data == null){
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);
498 data = data.toString();
500 for(var i=0; i<data.length; i++){
501 var c = data.charCodeAt(i);
502 var bs = new Array();
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){
511 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
512 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
513 bs[2] = 0x80 | (c & 0x3F);
516 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
517 bs[1] = 0x80 | (c & 0x3F);
522 for(var j=0; j<bs.length; j++){
524 var hex = nibble_to_hex((b & 0xF0) >>> 4)
525 + nibble_to_hex(b &0x0F);
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
539 urlDecode : function(string, overwrite){
540 if(!string || !string.length){
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"){
553 }else if(typeof obj[name] == "string"){
554 obj[name] = [obj[name]];
555 obj[name].push(value);
557 obj[name].push(value);
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
574 each : function(array, fn, scope){
575 if(typeof array.length == "undefined" || typeof array == "string"){
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; };
584 combine : function(){
585 var as = arguments, l = as.length, r = [];
586 for(var i = 0; i < l; i++){
588 if(a instanceof Array){
590 }else if(a.length !== undefined && !a.substr){
591 r = r.concat(Array.prototype.slice.call(a, 0));
600 * Escapes the passed string for use in a regular expression
601 * @param {String} str
604 escapeRe : function(s) {
605 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
609 callback : function(cb, scope, args, delay){
610 if(typeof cb == "function"){
612 cb.defer(delay, scope, args || []);
614 cb.apply(scope, args || []);
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
624 getDom : function(el){
628 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
632 * Shorthand for {@link Roo.ComponentMgr#get}
634 * @return Roo.Component
636 getCmp : function(id){
637 return Roo.ComponentMgr.get(id);
640 num : function(v, defaultValue){
641 if(typeof v != 'number'){
647 destroy : function(){
648 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
652 as.removeAllListeners();
656 if(typeof as.purgeListeners == 'function'){
659 if(typeof as.destroy == 'function'){
666 // inpired by a similar function in mootools library
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
685 if(o === undefined || o === null){
692 if(t == 'object' && o.nodeName) {
694 case 1: return 'element';
695 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
698 if(t == 'object' || t == 'function') {
699 switch(o.constructor) {
700 case Array: return 'array';
701 case RegExp: return 'regexp';
703 if(typeof o.length == 'number' && typeof o.item == 'function') {
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
716 isEmpty : function(v, allowBlank){
717 return v === null || v === undefined || (!allowBlank ? v === '' : false);
731 isBorderBox : isBorderBox,
733 isWindows : isWindows,
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.
744 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
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}
755 selectNode : function(selector, root)
757 var node = Roo.DomQuery.selectNode(selector,root);
758 return node ? Roo.get(node) : new Roo.Element(false);
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");